/* ============================================================================
   TASARIST CANADA · tasarist.ca
   Built with top-design. Image-first packaging-studio identity — NOT the
   ADWORKS system, NOT a reskin of it. Structure designed from scratch around
   the studio's real packaging renders.

   Signature moment: "The Grid ignites" — a full-bleed, zero-gap mosaic of the
   real work that cascades in on load, with one electric-blue tile, monumental
   Montserrat overlay that settles as you scroll.

   Brand locks (BRAND.md): Montserrat · electric blue #0A00FF used as a single
   spark · near-black ink · white/soft-paper base · blush warmth · print-mark
   line craft as the house texture (no stock decoration, no gradient orbs).
   ============================================================================ */

@import url('assets/fonts/montserrat.bdcac6.css');

/* ----------------------------------------------------------------- tokens -- */
:root{
  --blue:#0a00ff;          /* THE spark — sampled from the real logo */
  --blue-ink:#0800cc;
  --blue-soft:#ecebff;

  --ink:#0b0b0d;           /* near-black, never #000 */
  --ink-2:#3a3a40;
  --mute:#6a6a72;
  --paper:#ffffff;
  --paper-2:#f4f3f0;       /* warm off-white for section alternation */
  --line:#e6e5e2;
  --line-ink:rgba(255,255,255,.16);

  --blush:#f2c6bf;
  --blush-soft:#fae6e2;
  --rose:#c2886e;
  --copper:#c87f4f;

  --font:'Montserrat',system-ui,-apple-system,'Segoe UI',Helvetica,Arial,sans-serif;
  --maxw:1440px;
  --gutter:clamp(1.25rem,4.5vw,5rem);

  /* elite motion — custom curves only, never ease/linear */
  /* height of the fixed header once scrolled — the pinned Approach stage sits
     below it on mobile, and tasarist.js reads it back for its scroll maths */
  --hdr:64px;

  --expo:cubic-bezier(.16,1,.3,1);
  --quart:cubic-bezier(.25,1,.5,1);
  --expo-io:cubic-bezier(.87,0,.13,1);
}

*{box-sizing:border-box}
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth}
body{
  margin:0;background:var(--paper);color:var(--ink);
  font-family:var(--font);font-weight:400;
  font-size:clamp(15.5px,.35vw + 14.5px,17.5px);line-height:1.6;
  -webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;
  overflow-x:hidden;
}
img{display:block;max-width:100%}
figure{margin:0}   /* kill the UA figure margin (1em 40px) so tiles fill their grid cells */
a{color:inherit;text-decoration:none}
::selection{background:var(--blue);color:#fff}
:focus-visible{outline:2px solid var(--blue);outline-offset:3px;border-radius:2px}

h1,h2,h3,h4{margin:0;font-weight:800;line-height:1;letter-spacing:-.03em;color:var(--ink)}
.wrap{width:100%;max-width:var(--maxw);margin-inline:auto;padding-inline:var(--gutter)}
.section{padding-block:clamp(5rem,11vw,10rem)}

/* shared editorial atoms ---------------------------------------------------- */
.eyebrow{
  font-weight:700;font-size:.7rem;letter-spacing:.28em;text-transform:uppercase;
  color:var(--blue);margin:0 0 1.4rem;display:flex;align-items:center;gap:.7rem;
}
.eyebrow::before{content:"";width:26px;height:1px;background:var(--blue)}
.eyebrow.center{justify-content:center}
/* centered eyebrows: drop the single leading line; use a print registration
   crossmark on both sides (added inline in markup, inherits the eyebrow colour) */
.eyebrow.center,.contact .eyebrow{gap:.6rem}
.eyebrow.center::before,.contact .eyebrow::before{display:none}
.eyebrow .xmark{width:1.66em;height:1.66em;flex:none;stroke-width:.7}
.u{color:var(--blue)}

.btn{
  --bg:var(--blue);--fg:#fff;
  display:inline-flex;align-items:center;gap:.55rem;
  background:var(--bg);color:var(--fg);
  font-weight:700;font-size:.8rem;letter-spacing:.04em;
  padding:.95rem 1.5rem;border-radius:2px;border:1px solid var(--bg);
  transition:transform .5s var(--expo),background .35s var(--expo),color .35s var(--expo);
  will-change:transform;
}
.btn .arw{transition:transform .5s var(--expo)}
.btn:hover{transform:translateY(-2px)}
.btn:hover .arw{transform:translate(3px,-3px)}
.btn.ghost{--bg:transparent;--fg:var(--ink);border-color:var(--ink)}
.btn.ghost:hover{--bg:var(--ink);--fg:#fff}
.btn.on-dark.ghost{--fg:#fff;border-color:rgba(255,255,255,.55)}
.btn.on-dark.ghost:hover{--bg:#fff;--fg:var(--ink);border-color:#fff}

/* ------------------------------------------------------------------ header -- */
.site-header{
  position:fixed;inset:0 0 auto;z-index:60;
  display:flex;align-items:center;justify-content:space-between;
  padding:1.15rem var(--gutter);
  transition:background .5s var(--expo),box-shadow .5s var(--expo),padding .5s var(--expo);
}
.site-header.scrolled{
  background:rgba(255,255,255,.82);backdrop-filter:blur(14px);
  box-shadow:0 1px 0 var(--line);padding-block:.7rem;
}
.brand{display:flex;align-items:center;gap:.6rem}
.brand .logo{height:26px;width:auto}
.brand .logo--dark{display:none}
.brand .logo--light{display:block}
.site-header.scrolled .brand .logo--dark{display:block}
.site-header.scrolled .brand .logo--light{display:none}
.brand .locale{
  display:inline-flex;align-items:center;gap:.4rem;
  font-weight:700;font-size:.64rem;letter-spacing:.22em;text-transform:uppercase;
  color:#fff;transition:color .5s var(--expo);
}
.site-header.scrolled .brand .locale{color:var(--ink)}
.brand .leaf{width:.9rem;height:.9rem;flex:none;fill:#d80621}   /* Canadian red maple leaf, always red */
.nav{display:flex;align-items:center;gap:2rem}
/* menu-only furniture — the mobile press sheet reveals these, desktop never does */
.nav__mark,.nav__foot{display:none}
.nav > a:not(.btn){
  font-weight:600;font-size:.8rem;letter-spacing:.02em;color:#fff;
  position:relative;transition:color .5s var(--expo);
}
.site-header.scrolled .nav > a:not(.btn){color:var(--ink)}
.nav > a:not(.btn)::after{
  content:"";position:absolute;left:0;bottom:-6px;width:100%;height:1px;
  background:var(--blue);transform:scaleX(0);transform-origin:left;
  transition:transform .5s var(--expo);
}
.nav > a:not(.btn):hover::after{transform:scaleX(1)}
/* Language switch: an outlined box so it reads as a control, not a section
   link. Same type, padding and border as .btn, so it matches its height. */
.nav > a.lang{
  display:inline-flex;align-items:center;
  font-weight:700;letter-spacing:.04em;
  padding:.95rem 1.1rem;border:1px solid var(--blue);border-radius:2px;
  transition:background .35s var(--expo),color .35s var(--expo);
}
.nav > a.lang::after{display:none}
.nav > a.lang:hover,.site-header.scrolled .nav > a.lang:hover,.site-header--solid .nav > a.lang:hover{background:var(--blue);color:#fff}
.nav-toggle{display:none}

/* ================================================================= SHOWCASE ==
   Hero = the work. Full-bleed zero-gap mosaic of real packaging renders,
   with a monumental type overlay on the first screen. Doubles as #work. */
/* hero copy and mosaic share one grid cell: the mosaic sets the scroll height,
   the copy pins over it and releases exactly at the mosaic's end (no over-stay) */
.showcase{position:relative;background:var(--ink);display:grid;grid-template-columns:minmax(0,1fr)}
.showcase>.mosaic,.showcase>.hero-overlay{grid-area:1/1}
.mosaic{
  position:relative;z-index:1;   /* scrolls beneath the pinned hero-overlay */
  display:grid;grid-template-columns:repeat(4,1fr);
  grid-auto-rows:clamp(150px,20vw,260px);grid-auto-flow:dense;
  gap:12px;   /* one value = identical vertical and horizontal spacing */
}
.tile{position:relative;overflow:hidden;background:#111}
.tile img{
  width:100%;height:100%;object-fit:cover;
  transition:transform 1.1s var(--expo),filter .6s var(--expo);
  will-change:transform;
}
.tile:hover img{transform:scale(1.06)}
/* asymmetric spans for rhythm */
.tile.big{grid-column:span 2;grid-row:span 2}
.tile.wide{grid-column:span 2}
.tile.tall{grid-row:span 2}

/* per-tile hover label */
.tile .meta{
  position:absolute;inset:auto 0 0 0;z-index:2;
  display:flex;align-items:baseline;justify-content:space-between;gap:.5rem;
  padding:1rem 1.15rem;
  background:linear-gradient(to top,rgba(6,6,10,.86),rgba(6,6,10,0));
  transform:translateY(101%);transition:transform .6s var(--expo);
}
.tile:hover .meta,.tile:focus-within .meta{transform:translateY(0)}
.tile .meta .nm{font-weight:800;font-size:.98rem;letter-spacing:-.01em;color:#fff}
.tile .meta .ct{font-weight:600;font-size:.62rem;letter-spacing:.14em;text-transform:uppercase;color:rgba(255,255,255,.72)}

/* the electric-blue "ignite" tile */
.tile.ignite{
  background:var(--blue);display:flex;flex-direction:column;justify-content:space-between;
  padding:1.4rem;color:#fff;overflow:hidden;
}
.tile.ignite .dmd{font-size:1rem;opacity:.9}
.tile.ignite .ig-lead{font-weight:800;font-size:clamp(1.1rem,1.6vw,1.6rem);letter-spacing:-.02em;line-height:1.02}
.tile.ignite .ig-foot{font-weight:600;font-size:.6rem;letter-spacing:.2em;text-transform:uppercase;opacity:.85}
.tile.ignite .printfield .pm{stroke:rgba(255,255,255,.5)}

/* type overlay on the first screen */
.hero-overlay{
  position:sticky;top:0;align-self:start;z-index:10;pointer-events:none;
  /* pinned; releases at the mosaic's end, then rides up with the award bar.
     svh (small viewport height) where supported so the pin does not resize
     as a phone's URL bar hides and returns — vh would jolt the hero mid-scroll. */
  height:100vh;height:100svh;
  display:flex;flex-direction:column;justify-content:center;
  padding:clamp(6rem,10vh,8rem) var(--gutter) clamp(2rem,5vw,4rem);
  /* the original gradient — a left wash plus soft top/bottom fades. Now that the
     layer is pinned (not scrolling), the gradient stays put instead of drifting
     over the tiles, which is what looked off before. */
  background:
    linear-gradient(100deg,rgba(6,6,10,.92) 0%,rgba(6,6,10,.78) 32%,rgba(6,6,10,.34) 56%,rgba(6,6,10,0) 78%),
    linear-gradient(180deg,rgba(6,6,10,.5) 0%,transparent 26%,transparent 74%,rgba(6,6,10,.5) 100%);
}
.hero-overlay .inner{max-width:min(100%,640px);pointer-events:auto}
.hero-kicker{
  font-weight:700;font-size:clamp(.66rem,.8vw,.78rem);letter-spacing:.26em;text-transform:uppercase;
  color:#fff;display:flex;align-items:center;gap:.6rem;margin:0 0 1.3rem;flex-wrap:wrap;
}
.hero-kicker .dmd{color:#fff}
.hero-h1{
  color:#fff;font-weight:900;
  font-size:clamp(2.7rem,6vw,5.6rem);letter-spacing:-.045em;line-height:.92;
  max-width:min(100%,12ch);text-wrap:balance;
}
.hero-h1 .u{color:#fff;-webkit-text-stroke:0}
.hero-h1 .spark{
  display:inline-block;color:#fff;background:var(--blue);
  padding:0 .12em;box-decoration-break:clone;-webkit-box-decoration-break:clone;
}
.hero-lead{
  color:rgba(255,255,255,.9);font-weight:400;max-width:52ch;
  font-size:clamp(1rem,1.35vw,1.24rem);line-height:1.55;margin:1.7rem 0 0;
}
.hero-lead b{font-weight:700;color:#fff}
.hero-cta{display:flex;gap:.9rem;flex-wrap:wrap;margin-top:2.2rem}
.hero-meta{
  display:flex;gap:clamp(1.6rem,4vw,3.2rem);flex-wrap:wrap;margin-top:2.8rem;
}
.hero-meta .n{font-weight:800;font-size:clamp(1.5rem,2.4vw,2.2rem);letter-spacing:-.02em;color:#fff;display:block;line-height:1}
.hero-meta .n em{font-style:normal;color:#fff;background:var(--blue);padding:0 .1em}
.hero-meta .l{font-weight:500;font-size:.66rem;letter-spacing:.12em;text-transform:uppercase;color:rgba(255,255,255,.66);margin-top:.55rem;display:block;max-width:21ch;line-height:1.4}
/* vertical scroll cue pinned to the far-right edge of the first screen.
   right-offset (not left+translate) keeps it inside the viewport — no side-scroll. */
.scroll-cue{
  position:absolute;right:clamp(.9rem,2.4vw,2rem);bottom:clamp(1.6rem,4vh,2.6rem);z-index:11;
  writing-mode:vertical-rl;pointer-events:none;
  font-weight:600;font-size:.6rem;letter-spacing:.26em;text-transform:uppercase;color:rgba(255,255,255,.72);
  display:flex;align-items:center;gap:.85rem;
}
.scroll-cue::after{content:"";width:1px;height:42px;background:linear-gradient(rgba(255,255,255,.75),transparent);animation:cue 2.4s var(--expo) infinite}
@keyframes cue{0%{transform:scaleY(0);transform-origin:top}45%{transform:scaleY(1);transform-origin:top}55%{transform:scaleY(1);transform-origin:bottom}100%{transform:scaleY(0);transform-origin:bottom}}

/* work caption strip under the mosaic */
/* ---- sticky award credential ---------------------------------------------
   The caption + jury marquee pin below the fixed header once they reach it and
   ride the whole Why section, then Services pushes them off. The pin's end is
   set by the WRAPPER's bottom edge, which is why .stickyzone encloses the bar
   AND the Why section. z-index sits under the header (60) and over section
   content. Never give .stickyzone overflow:hidden/clip — sticky dies. */
.stickyzone{position:relative}
.stickyzone__bar{position:sticky;top:var(--hdr);z-index:45}

.work-cap{
  background:var(--ink);
  display:flex;justify-content:flex-end;align-items:flex-end;
  padding:1.4rem var(--gutter) .4rem;border-top:1px solid var(--line-ink);
}
.work-cap__note{
  font-weight:600;font-size:clamp(.76rem,1vw,.92rem);letter-spacing:.03em;
  color:rgba(255,255,255,.82);text-align:right;
}
/* Brand blue is #0a00ff — near-black on this ink panel — so the highlight uses
   the light campaign blue instead. Same brand hue, legible on the dark bar. */
.work-cap__note em{font-style:normal;font-weight:800;color:var(--blue-soft)}

/* ---------------------------------------------------------------- award bar -- */
.awardbar{background:var(--ink);color:#fff;overflow:hidden;padding:1.25rem 0;position:relative}
.awardbar::before,.awardbar::after{content:"";position:absolute;top:0;bottom:0;width:12%;z-index:2;pointer-events:none}
.awardbar::before{left:0;background:linear-gradient(90deg,var(--ink),transparent)}
.awardbar::after{right:0;background:linear-gradient(270deg,var(--ink),transparent)}
/* Each jury name carries a copper trophy in front of it; the trophy also does
   the separating, so there is no divider glyph. Spacing is padding on the
   item, not flex gap: the loop slides exactly -50%, and a gap would leave the
   two halves half a gap out of step. */
.awardbar__track{display:flex;align-items:center;width:max-content;animation:marquee 42s linear infinite}
.awardbar__track .aw{display:inline-flex;align-items:center;gap:.6rem;padding-right:2.6rem;font-weight:600;font-size:.82rem;letter-spacing:.04em;white-space:nowrap;color:rgba(255,255,255,.86)}
.aw__ico{width:1.25rem;height:1.25rem;flex:none;color:var(--copper)}
@keyframes marquee{to{transform:translateX(-50%)}}

/* ------------------------------------------------------------------- why ---- */
.section-head{
  display:grid;grid-template-columns:1.05fr .95fr;gap:clamp(1.5rem,4vw,4rem);
  align-items:end;margin-bottom:clamp(2.8rem,5vw,4.5rem);
}
.section-head h2{font-size:clamp(2rem,5vw,4rem);max-width:16ch}
.section-head p{color:var(--mute);font-size:clamp(1rem,1.2vw,1.15rem);max-width:46ch}
/* Stacked heads inherit the two-column grid's `gap`, which is tuned as a
   COLUMN gutter (up to 4rem) and left a chasm between the heading and the line
   underneath it. Row gap is set independently so the supporting line reads as
   part of the heading at every width. */
.section-head.stack{grid-template-columns:1fr;row-gap:clamp(.8rem,1.4vw,1.15rem)}

.why{background:var(--paper)}
.why-grid{display:grid;grid-template-columns:1.1fr .9fr;gap:clamp(1.5rem,4vw,4rem);align-items:start}
.why-copy{display:flex;flex-direction:column;gap:1.6rem}
.why-card{border-top:1px solid var(--ink);padding-top:1.5rem}
.why-card .no{font-weight:800;font-size:.8rem;letter-spacing:.14em;color:var(--blue)}
.why-card h3{font-size:clamp(1.35rem,2.2vw,1.9rem);letter-spacing:-.025em;margin:.7rem 0 .8rem}
.why-card h3 em{font-style:italic;font-weight:800;color:var(--blue)}
.why-card p{color:var(--ink-2);margin:0 0 1rem}
.why-card ul{margin:0;padding:0;list-style:none;display:grid;gap:.55rem}
.why-card li{position:relative;padding-left:1.3rem;font-size:.92rem;color:var(--ink-2)}
.why-card li::before{content:"";position:absolute;left:0;top:.55em;width:7px;height:7px;background:var(--blue)}
.why-card li b{color:var(--ink);font-weight:700}
/* featured project — dominant hero + aligned detail pair + caption, animated in.
   Composition (top-design): one image leads by scale, two aligned equals give
   rhythm, consistent gaps hold the negative space; subtle depth via soft shadow. */
.feat{
  display:flex;flex-direction:column;gap:14px;
  padding:clamp(1rem,1.8vw,1.5rem);
  /* soft blush panel that ties to the project's pastels and lifts the light
     product shots off the white page */
  background:linear-gradient(168deg,#faf4f3 0%,#f5f3f1 72%);
  border:1px solid #ecdfdc;
}
.feat__img{overflow:hidden;background:#fff;border:1px solid #ece1df;box-shadow:0 12px 30px -20px rgba(60,20,30,.3)}
.feat__img img{width:100%;height:100%;object-fit:cover;display:block;transition:transform 1.1s var(--expo)}
.feat__img:hover img{transform:scale(1.05)}
.feat__hero{aspect-ratio:3/2}
.feat__strip{display:grid;grid-template-columns:1fr 1fr;gap:14px}
.feat__strip .feat__img{aspect-ratio:1/1}
.feat__card{padding-top:.7rem}
.feat__k{display:block;font-weight:700;font-size:.62rem;letter-spacing:.2em;text-transform:uppercase;color:var(--blue);margin-bottom:.75rem}
.feat__t{font-size:clamp(1.45rem,2.2vw,1.9rem);letter-spacing:-.025em}
.feat__d{color:var(--ink-2);margin:.7rem 0 1.25rem;font-size:.92rem;line-height:1.55;max-width:48ch}
.feat__btn{align-self:flex-start}

/* --------------------------------------------------------------- services --- */
.services{background:var(--paper-2)}

/* ---- services head + the blue endorsement, side by side -------------------
   The heading and its supporting line stack in the left column; Didem's panel
   takes the right, so the section opens with what the studio does AND who
   sells it into North American retail, in one row. */
.svc-top{
  display:grid;grid-template-columns:1.05fr .95fr;
  gap:clamp(1.5rem,4vw,4rem);
  /* The head block is ~330px, Didem's panel ~570px. Aligned to `start` the
     mismatch fell as dead space UNDER the lede, which read as a layout bug.
     Aligned to `end` the same space sits ABOVE the heading, where it reads as
     a deliberate editorial drop: the panel opens the section top-right, and
     the heading, the lede and the panel all land on one baseline that runs
     straight into the service list's top rule. Do not switch this back to
     `start` without also giving the left column more to carry. */
  align-items:end;
  margin-bottom:clamp(2.8rem,5vw,4.5rem);
}
.svc-top .section-head{margin-bottom:0}

/* Solid brand blue rather than a bordered card, so it reads as a statement
   instead of another service row. */
.exec{
  margin:0;background:var(--blue);color:#fff;
  padding:clamp(1.5rem,3vw,2.4rem);
  display:flex;flex-direction:column;
}
.exec__h{
  margin:0;color:#fff;font-size:clamp(1.5rem,2.7vw,2.15rem);
  letter-spacing:-.03em;line-height:1.06;text-wrap:balance;
}
.exec__lede{
  margin:.9rem 0 0;font-size:clamp(.92rem,1.15vw,1.05rem);line-height:1.6;
  color:rgba(255,255,255,.86);max-width:46ch;
}
.exec__who{
  display:flex;align-items:center;gap:.95rem;
  margin-top:clamp(1.1rem,2.2vw,1.6rem);
  padding-top:clamp(1.1rem,2.2vw,1.6rem);
  border-top:1px solid rgba(255,255,255,.28);
}
.exec__avatar{
  width:clamp(84px,9vw,120px);aspect-ratio:1;flex:none;
  border-radius:50%;overflow:hidden;
  border:2px solid rgba(255,255,255,.5);background:rgba(255,255,255,.12);
  display:grid;place-items:center;
}
.exec__avatar img{width:100%;height:100%;object-fit:cover;display:block}
.exec__avatar span{font-weight:800;font-size:clamp(1.3rem,2.2vw,1.7rem);letter-spacing:.04em;color:#fff}
.exec__id{display:flex;flex-direction:column;gap:.35rem}
.exec__name{font-weight:800;font-size:clamp(.95rem,1.4vw,1.12rem);letter-spacing:-.01em;color:#fff}
.exec__role{
  font-weight:600;font-size:.63rem;letter-spacing:.15em;text-transform:uppercase;
  color:rgba(255,255,255,.72);line-height:1.45;
}
/* Where each of them sits. Same micro-type as the role, one step dimmer, so
   the credit reads name -> what they do -> where they are without a third
   competing weight. Akin's counterpart is .dir__sign .loc; the two are
   deliberately styled alike even though one stacks and one runs inline. */
.exec__loc{
  font-weight:600;font-size:.63rem;letter-spacing:.15em;text-transform:uppercase;
  color:rgba(255,255,255,.56);line-height:1.45;
}
/* The quote now leads and the attribution sits under it, so it carries the
   panel and is sized to be read before the name, not after it. */
.exec__q{margin:clamp(1.3rem,2.6vw,1.9rem) 0 0}
.exec__q p{
  margin:0;font-weight:700;text-wrap:balance;color:#fff;
  font-size:clamp(1.18rem,2.1vw,1.6rem);line-height:1.32;letter-spacing:-.025em;
}
.exec__q p::before{content:"\201C"}
.exec__q p::after{content:"\201D"}

.svc-list{border-top:1px solid var(--line)}
.svc{
  display:grid;grid-template-columns:5rem 1fr 1.1fr;gap:clamp(1rem,3vw,3rem);
  padding:clamp(1.8rem,3.5vw,2.8rem) 0;border-bottom:1px solid var(--line);
  align-items:start;transition:padding-left .6s var(--expo);
}
.svc:hover{padding-left:.7rem}
.svc__no{font-weight:800;font-size:1rem;color:var(--blue);letter-spacing:.06em;padding-top:.4rem}
.svc__t h3{font-size:clamp(1.4rem,2.6vw,2.2rem);letter-spacing:-.03em}
.svc__t p{color:var(--mute);margin:.7rem 0 0;font-size:.95rem;max-width:34ch}
.svc__tags{display:flex;flex-wrap:wrap;gap:.5rem;padding-top:.5rem}
.svc__tags span{
  font-weight:600;font-size:.72rem;letter-spacing:.02em;color:var(--ink-2);
  border:1px solid var(--line);padding:.4rem .7rem;border-radius:2px;background:var(--paper);
}

/* --------------------------------------------------------------- approach --- */
/* "STRATEGIC DESIGN™, READ SIDEWAYS" — the signature moment of this page.
   The electric-blue panel PINS to the viewport and the method scrolls THROUGH
   it horizontally, spread by spread, like turning a magazine on its side.
   Vertical scroll distance is mapped 1:1 onto horizontal travel in tasarist.js,
   so nothing is hijacked: stop scrolling and the spread stops with you.

   Styling is carried over from the old static block — electric-blue ground,
   white type on an opacity ladder, white line-craft iconography, print-mark
   texture. Only the structure changed.

   CONTENT SOURCE: tasarist.net/strategy (Creative Branding Process), captured
   2026-09-04. The 165% Bingo Glass Cleaner Spray figure, the "200 most valuable
   brands" line and the 5m/3m/1m perception distances are all the STUDIO's own
   published claims, reproduced and attributed — not estimated here. */

.approach{position:relative;background:var(--blue);color:#fff}

/* the pinned viewport. NOTE: `overflow` lives HERE and never on .approach —
   an overflow on the sticky element's containing block kills the pin. */
.ap-stage{position:sticky;top:0;height:100vh;height:100svh;overflow:hidden}
.ap-stage .printfield{opacity:.55}

.ap-track{display:flex;height:100%;will-change:transform;transform:translate3d(0,0,0)}

.ap-panel{
  flex:0 0 auto;width:var(--w,72vw);position:relative;z-index:2;
  /* top-aligned, not centred: every spread starts its headline on the same
     baseline, so the eye has a fixed entry point as the track moves sideways.
     Centring made each spread float at its own height and read as unsettled. */
  display:flex;flex-direction:column;justify-content:flex-start;
  padding:clamp(5.5rem,11vh,7.5rem) clamp(1.6rem,3.4vw,4.5rem) clamp(6rem,12vh,8rem);
}
/* column rules between spreads — the magazine tell */
.ap-panel + .ap-panel{border-left:1px solid rgba(255,255,255,.2)}

/* ---- panel typography ladder ---- */
.ap-eyebrow{
  display:flex;align-items:center;gap:.7rem;margin:0 0 1.4rem;
  font-size:.7rem;font-weight:700;letter-spacing:.18em;text-transform:uppercase;
  color:rgba(255,255,255,.72);
}
.ap-eyebrow .ap-no{
  display:grid;place-items:center;width:26px;height:26px;flex:0 0 26px;
  border:1px solid rgba(255,255,255,.45);border-radius:50%;
  font-size:.66rem;letter-spacing:.04em;color:#fff;
}
.ap-h{margin:0;color:#fff;font-weight:800;letter-spacing:-.03em;line-height:1.03;
  font-size:clamp(1.9rem,3.4vw,3.4rem);max-width:17ch;text-wrap:balance}
.ap-p{color:rgba(255,255,255,.82);font-size:clamp(.94rem,1.02vw,1.06rem);max-width:52ch;margin:1.3rem 0 0}
.ap-p b{color:#fff;font-weight:600}
.approach .u{color:#fff;text-decoration:underline;text-decoration-thickness:2px;text-underline-offset:6px}
.ap-blush{color:var(--blush)}

/* opening spread — monumental, sets the question. The only centred spread:
   it is a title page, so it should sit in the middle of its own field, while
   the chapters that follow all start from the same top baseline. */
.ap-panel--open{justify-content:center}
.ap-panel--open .ap-h{font-size:clamp(2.4rem,5.4vw,5.6rem);max-width:15ch}
.ap-panel--open .ap-p{font-size:clamp(1rem,1.25vw,1.2rem);max-width:46ch}
.ap-tm{
  display:block;margin:0 0 1.8rem;font-weight:800;letter-spacing:.2em;
  text-transform:uppercase;font-size:clamp(.68rem,.8vw,.8rem);color:var(--blush);
}
.ap-swipe{
  display:flex;align-items:center;gap:.85rem;margin:clamp(2rem,4vh,3rem) 0 0;
  font-size:.7rem;font-weight:700;letter-spacing:.18em;text-transform:uppercase;
  color:rgba(255,255,255,.8);
}
.ap-swipe i{display:block;width:clamp(48px,7vw,110px);height:1px;background:rgba(255,255,255,.45);position:relative}
.ap-swipe i::after{
  content:"";position:absolute;top:0;left:0;height:1px;width:34%;background:#fff;
  animation:apSwipe 2.6s var(--expo) infinite;
}
@keyframes apSwipe{0%{transform:translateX(-100%)}60%,100%{transform:translateX(300%)}}

/* two-column spreads: diagram beside argument */
.ap-split{display:grid;grid-template-columns:1.02fr .98fr;gap:clamp(2rem,4.5vw,5.5rem);align-items:center}
.ap-split--wide{grid-template-columns:1fr;gap:clamp(1.8rem,4vh,3rem)}
.ap-split--flip{grid-template-columns:.9fr 1.1fr}

/* the pull-quote spread — the two questions CBP is built to answer */
.ap-qs{display:grid;gap:clamp(1.1rem,2.4vh,1.9rem);margin:clamp(1.6rem,3.5vh,2.6rem) 0 0}
.ap-q{
  display:grid;grid-template-columns:auto 1fr;gap:clamp(1rem,2vw,1.8rem);align-items:baseline;
  border-top:1px solid rgba(255,255,255,.28);padding-top:clamp(.9rem,2vh,1.4rem);
}
.ap-q__k{font-size:.68rem;font-weight:700;letter-spacing:.18em;text-transform:uppercase;color:var(--blush)}
.ap-q__t{margin:0;font-weight:700;letter-spacing:-.025em;line-height:1.12;
  font-size:clamp(1.35rem,2.5vw,2.5rem);color:#fff;text-wrap:balance}

/* proof spread — real render, attributed figure */
.ap-proof{display:grid;gap:clamp(1.2rem,3vh,2rem)}
/* The spread is pinned to one screen, so this figure cannot be sized by width
   alone: at 4/3 it grew to 552px on a 1440x900 desktop and pushed the closing
   paragraph entirely below the fold. 16/9 sets the shape, and the svh cap is
   what actually guarantees the fit — it scales with the stage, so a short
   laptop gets a shorter figure instead of losing copy. object-fit:cover on the
   img means the cap crops rather than distorts. */
.ap-proof__img{position:relative;overflow:hidden;aspect-ratio:16/9;max-height:38svh;background:rgba(255,255,255,.08)}
.ap-proof__img img{width:100%;height:100%;object-fit:cover;transform:scale(1.05);
  transition:transform 1.4s var(--expo)}
.ap-panel.in .ap-proof__img img{transform:none}
.ap-proof__cap{
  position:absolute;left:0;bottom:0;padding:.5rem .8rem;background:var(--blue);
  font-size:.64rem;font-weight:700;letter-spacing:.14em;text-transform:uppercase;color:#fff;
}
.ap-fig{display:flex;align-items:baseline;gap:.9rem;margin:0}
.ap-fig__n{font-size:clamp(3.2rem,6vw,6rem);font-weight:800;letter-spacing:-.045em;line-height:.86;color:var(--blush)}
.ap-fig__l{font-size:.72rem;font-weight:700;letter-spacing:.14em;text-transform:uppercase;color:rgba(255,255,255,.8);max-width:18ch;line-height:1.5}

/* closing spread — the default .btn is blue-on-blue here, so invert it */
.ap-cta{display:flex;flex-wrap:wrap;gap:.8rem;margin:clamp(1.8rem,4vh,2.6rem) 0 0}
.ap-cta .btn{--bg:#fff;--fg:var(--blue);border-color:#fff}
.ap-cta .btn:hover{--bg:transparent;--fg:#fff}
.ap-cta .btn.on-dark.ghost{--bg:transparent;--fg:#fff;border-color:rgba(255,255,255,.55)}
.ap-cta .btn.on-dark.ghost:hover{--bg:#fff;--fg:var(--blue);border-color:#fff}

/* ---- CBP diagrams, redrawn from the tasarist.net PNGs as live SVG ---- */
.cbp{display:block;width:100%;height:auto;font-family:var(--font);overflow:visible}
.cbp-triad{max-width:min(46vw,560px)}
.cbp-chain{max-width:none}
.cbp-dist{max-width:min(74vw,900px)}
.cbp line,.cbp path,.cbp circle,.cbp rect{vector-effect:non-scaling-stroke}
.cbp-ring,.cbp-hex,.cbp-arc,.cbp-rule{fill:none;stroke:#fff;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round}
.cbp-arrow{fill:none;stroke:#fff;stroke-width:1.5;stroke-linejoin:round}
.cbp-link{fill:none;stroke:rgba(255,255,255,.5);stroke-width:1.2;stroke-dasharray:5 7}
.cbp-ico{fill:none;stroke:#fff;stroke-width:1.6;stroke-linecap:round;stroke-linejoin:round}
.cbp-ico .knock{fill:var(--blue);stroke:#fff}
.cbp-ico .hot{fill:var(--blush);stroke:none}
.cbp-rays{stroke:var(--blush)}
.cbp-lbl{fill:rgba(255,255,255,.9);font-size:20px;font-weight:700;letter-spacing:-.01em;text-anchor:middle}
.cbp-num{fill:#fff;font-size:46px;font-weight:300;letter-spacing:.02em;text-anchor:middle}
.cbp-word{fill:var(--blush);font-size:30px;font-weight:800;letter-spacing:-.02em;text-anchor:middle}
.cbp-m{fill:var(--blush);font-size:48px;font-weight:800;letter-spacing:-.03em;text-anchor:middle}
.cbp-cap{fill:#fff;font-size:23px;font-weight:700;letter-spacing:-.01em;text-anchor:middle}
.cbp-tag{fill:rgba(255,255,255,.85);font-size:22px;font-weight:700;letter-spacing:-.01em;text-anchor:middle}
.cbp-hot{fill:var(--blush);stroke:none}
/* strokes draw themselves in when the spread arrives */
.cbp .draw{stroke-dasharray:1;stroke-dashoffset:1}
.ap-panel.in .cbp .draw{animation:draw 1.7s var(--expo) forwards}
.ap-panel.in .cbp .draw.d2{animation-delay:.16s}
.ap-panel.in .cbp .draw.d3{animation-delay:.32s}
.ap-panel.in .cbp .draw.d4{animation-delay:.48s}
.ap-panel.in .cbp .draw.d5{animation-delay:.64s}

/* legend under the triad */
.ap-legend{display:grid;gap:clamp(.9rem,2vh,1.4rem);margin:clamp(1.4rem,3vh,2rem) 0 0}
.ap-leg{display:grid;grid-template-columns:auto 1fr;gap:.9rem;align-items:start;
  border-top:1px solid rgba(255,255,255,.24);padding-top:.85rem}
.ap-leg__n{font-size:.68rem;font-weight:700;letter-spacing:.14em;color:var(--blush);padding-top:.2rem}
.ap-leg h4{margin:0 0 .25rem;font-size:clamp(.98rem,1.25vw,1.2rem);font-weight:700;letter-spacing:-.02em;color:#fff}
.ap-leg p{margin:0;font-size:.86rem;line-height:1.55;color:rgba(255,255,255,.76)}

/* ---- the chapter rail (pinned to the bottom of the stage) ---- */
.ap-rail{
  position:absolute;left:0;right:0;bottom:0;z-index:6;pointer-events:none;
  display:flex;align-items:center;gap:clamp(1rem,2.4vw,2.4rem);
  padding:0 clamp(1.6rem,3.4vw,4.5rem) clamp(1.1rem,2.6vh,1.9rem);
}
.ap-rail__mark{
  font-size:.66rem;font-weight:800;letter-spacing:.2em;text-transform:uppercase;
  color:rgba(255,255,255,.6);white-space:nowrap;
}
.ap-chapters{display:flex;align-items:center;gap:clamp(.7rem,1.6vw,1.6rem);list-style:none;margin:0;padding:0}
.ap-chap{
  display:flex;align-items:center;gap:.5rem;white-space:nowrap;
  font-size:.66rem;font-weight:700;letter-spacing:.13em;text-transform:uppercase;
  color:rgba(255,255,255,.42);transition:color .6s var(--expo);
}
/* +25%: 17px -> 21px */
.ap-chap svg{width:21px;height:21px;flex:0 0 21px;opacity:.5;transition:opacity .6s var(--expo)}
.ap-chap.on{color:#fff}
.ap-chap.on svg{opacity:1}
.ap-bar{flex:1;min-width:40px;height:1px;background:rgba(255,255,255,.28);position:relative;overflow:hidden}
.ap-bar i{position:absolute;inset:0;background:#fff;transform-origin:0 50%;transform:scaleX(0)}

/* ---- per-spread choreography: contents rise as the spread swings in ---- */
.ap-panel .r{
  opacity:0;transform:translateY(26px);
  transition:opacity .85s var(--expo),transform 1.05s var(--expo);
  transition-delay:calc(var(--d,0) * 85ms);
}
.ap-panel .r.side{transform:translateX(42px)}
.ap-panel.in .r{opacity:1;transform:none}

/* ---- unpinned mode: touch devices + reduced motion ------------------------
   The spread stops being scroll-driven and becomes a native swipe rail with
   snap points. Same content, same order, no transform, nothing unreachable. */
.approach:not(.ap--pinned){height:auto!important}
.approach:not(.ap--pinned) .ap-stage{position:static;height:auto;overflow:visible}
.approach:not(.ap--pinned) .ap-track{
  height:auto;transform:none!important;will-change:auto;
  overflow-x:auto;overflow-y:hidden;scroll-snap-type:x mandatory;
  -webkit-overflow-scrolling:touch;scrollbar-width:none;
}
.approach:not(.ap--pinned) .ap-track::-webkit-scrollbar{height:0;display:none}
.approach:not(.ap--pinned) .ap-panel{
  width:min(86vw,560px);scroll-snap-align:center;
  padding-block:clamp(3.5rem,9vw,5.5rem) clamp(3rem,7vw,4.5rem);
}
.approach:not(.ap--pinned) .ap-rail{position:static;padding-top:1.4rem;flex-wrap:wrap;row-gap:.9rem}
.approach:not(.ap--pinned) .ap-bar{display:none}
.approach:not(.ap--pinned) .cbp-triad,
.approach:not(.ap--pinned) .cbp-dist{max-width:100%}
.approach:not(.ap--pinned) .ap-split,
.approach:not(.ap--pinned) .ap-split--flip{grid-template-columns:1fr;gap:clamp(1.4rem,4vw,2.2rem)}

/* ---- phone scale ---------------------------------------------------------
   The rail stretches every spread to the height of the tallest one, so the
   CBP triad spread (diagram stacked over three legend entries in a single
   column) was setting the height for all seven and pushing 256px of every
   spread below the fold. Everything below is about getting the tallest
   spread back inside one screen. Nothing is hidden — only tightened. */
/* ---- portrait twins of the two landscape diagrams ------------------------
   The chain (1400 units wide) and the distance walk (920) are landscape by
   nature; squeezed onto a phone they render their words at 7-9px. Each has a
   portrait twin in the markup. Exactly one is displayed at any width. */
/* Breakpoint-aware copy. A phone spread has roughly half the reading room of
   a desktop one, so the Approach text runs short there: supporting clauses in
   .wide-only drop out, and where a sentence needs rewording rather than
   trimming, a .narrow-only twin takes its place. Desktop keeps the full
   argument; mobile keeps the point. */
.narrow-only{display:none}
@media(max-width:900px){
  .wide-only{display:none}
  .narrow-only{display:inline}
}

.cbp-chain-v,.cbp-dist-v{display:none}
.cbp-word--v{text-anchor:start}
.cbp-m--v{font-size:44px}
.cbp-cap--v,.cbp-tag--v{font-size:21px}

@media(max-width:900px){
  /* Same pinned spread as desktop — vertical scroll still drives the track
     sideways — but each spread is a full-width portrait page. Everything
     below exists to fit one spread inside one screen: top padding clears the
     64px fixed header, bottom clears the chapter rail. */
  /* The fixed header (64px once scrolled) is opaque over this section, so the
     pinned stage starts BELOW it and is shortened to match, rather than
     sliding underneath and relying on panel padding to dodge it. The section's
     own blue fills the strip behind the header, so it still reads full-bleed.
     tasarist.js reads this offset back off the stage to keep its scroll maths
     honest. */
  .ap-stage{top:var(--hdr);height:calc(100svh - var(--hdr))}
  /* Rail clearance, held in two custom properties so the panels don't have to
     know WHICH end the rail is on. Tablet keeps it at the bottom; the ≤760px
     block below flips both values and moves the rail to the top of the stage.
     Panel padding is written as base + clearance so the short-phone ladder
     further down can retune the base without touching this. */
  .approach{--ap-clear-t:0rem;--ap-clear-b:2.2rem}
  .ap-panel{width:100vw;padding:calc(1.7rem + 5vh + var(--ap-clear-t)) 1.35rem calc(1.4rem + var(--ap-clear-b))}
  /* must match the unpinned block's specificity (0,3,0) — a media query
     contributes none of its own, so a bare .ap-panel would lose to it */
  .approach:not(.ap--pinned) .ap-panel{width:100vw;padding:calc(1.7rem + 5vh + var(--ap-clear-t)) 1.35rem calc(1.4rem + var(--ap-clear-b))}
  .approach:not(.ap--pinned) .ap-rail{padding-top:.85rem;row-gap:.7rem}
  .ap-panel + .ap-panel{border-left:0}

  .ap-h{font-size:clamp(1.5rem,6vw,2rem)}
  .ap-panel--open .ap-h{font-size:clamp(2rem,8.6vw,2.8rem)}
  .ap-p{font-size:.86rem;line-height:1.52;margin-top:.8rem;max-width:none}
  .ap-panel--open .ap-p{font-size:.97rem}
  .ap-eyebrow{margin-bottom:.9rem}
  .ap-tm{margin-bottom:1.1rem}
  .ap-swipe{margin-top:1.4rem}

  /* portrait twins in, landscape out, sized to actually read */
  .cbp-chain,.cbp-dist{display:none}
  .cbp-chain-v,.cbp-dist-v{display:block;margin-inline:auto}
  /* widths chosen so each renders at a legible type size: the chain is a
     tall 300x510, the distance walk a wide 560x340 */
  .cbp-chain-v{max-width:min(58vw,219px)}
  .cbp-dist-v{max-width:100%}
  /* The triad's labels are 20 units in a 600-unit viewBox, which lands at 8px
     on a phone. Its icons are ~13px there — mush. So drop the icons and spend
     the room on type: bigger labels, wider line spacing, bigger numerals.
     The circles and their arrows carry the diagram; the icons were garnish. */
  .approach .cbp-triad{max-width:min(72vw,280px);margin-inline:auto}
  .cbp-triad .cbp-ico{display:none}
  .cbp-triad .cbp-lbl{font-size:36px;transform:translateY(6px)}
  .cbp-triad .cbp-lbl.l2{transform:translateY(24px)}
  .cbp-triad .cbp-num{font-size:58px;transform:translateY(38px)}

  /* The diagram plus the three numbered headings already name the inputs; the
     descriptions underneath are the most expendable copy on the section, and
     dropping them buys ~110px — enough to keep the triad at a readable size
     on a short phone instead of shrinking it to nothing. */
  .ap-legend{gap:.42rem;margin-top:.9rem}
  .ap-leg{gap:.6rem;padding-top:.45rem;align-items:baseline}
  .ap-leg h4{font-size:.9rem;margin-bottom:0}
  .ap-leg p{display:none}

  .ap-qs{margin-top:1.2rem;gap:.85rem}
  .ap-q{padding-top:.7rem;gap:.7rem}
  .ap-q__t{font-size:1.25rem}
  .ap-proof{gap:.9rem}
  .ap-proof__img{aspect-ratio:16/10}
  .ap-fig__n{font-size:2.8rem}
  .ap-fig__l{font-size:.65rem}
  .ap-cta{margin-top:1.3rem;gap:.6rem}
  .ap-cta .btn{padding:.8rem 1.15rem;font-size:.74rem}
}

/* Short phones — a real handset with browser chrome showing is nearer 640px
   tall than the 844 a spec sheet quotes, which leaves ~576px of stage. Tighten
   the type ladder and the diagrams again so every spread still lands whole. */
@media(max-width:900px) and (max-height:730px){
  /* Base top padding comes down from 1.2rem: on a phone the rail now sits at
     the top of the stage, so it already separates the header from the copy and
     the extra breathing room was pushing the tallest spread past the fold. */
  .approach:not(.ap--pinned) .ap-panel,
  .ap-panel{padding:calc(.7rem + 5vh + var(--ap-clear-t)) 1.35rem calc(.9rem + var(--ap-clear-b))}
  .ap-h{font-size:clamp(1.32rem,5.2vw,1.6rem)}
  .ap-panel--open .ap-h{font-size:clamp(1.7rem,7.2vw,2.2rem)}
  .ap-p{font-size:.8rem;line-height:1.45;margin-top:.6rem}
  .ap-panel--open .ap-p{font-size:.88rem}
  .ap-eyebrow{margin-bottom:.65rem}
  .approach .cbp-triad{max-width:min(52vw,200px)}
  .cbp-chain-v{max-width:min(48vw,178px)}
  .cbp-dist-v{max-width:88%}
  .ap-legend{gap:.3rem;margin-top:.7rem}
  .ap-leg{padding-top:.35rem}
  .ap-leg h4{font-size:.82rem}
  .ap-q__t{font-size:1.05rem}
  .ap-qs{margin-top:.9rem;gap:.6rem}
  .ap-fig__n{font-size:2.2rem}
  .ap-proof__img{aspect-ratio:2/1}
}

/* ---------------------------------------------------------------- awards ---- */
/* The reach section already closes on ~158px of white as its gradient
   resolves; the awards' own top padding stacked a second 158px on top of
   that, leaving a ~317px void. The boundary keeps one section's worth. */
.awards{background:var(--paper);padding-top:0}
.awards__top{display:grid;grid-template-columns:auto 1fr;gap:clamp(1.5rem,5vw,5rem);align-items:end;margin-bottom:clamp(2.5rem,5vw,4rem)}
.awards__big{line-height:1}
.awards__big .num{font-weight:900;font-size:clamp(4.5rem,11vw,9rem);letter-spacing:-.05em;color:var(--blue);display:block}
.awards__big .cap{font-weight:600;font-size:.7rem;letter-spacing:.16em;text-transform:uppercase;color:var(--mute);display:block;margin-top:.4rem}
/* the claim carries the blue up from the 50+; the date range stays grey so the
   eye reads "50+ international awards" as one unit and the span as a footnote */
.awards__big .cap em{font-style:normal;color:var(--blue)}
.awards__intro h2{font-size:clamp(1.7rem,3.6vw,2.8rem);max-width:18ch}
.awards__intro p{color:var(--mute);margin-top:1rem;max-width:60ch}
.awards__list{border-top:1px solid var(--ink)}
.aw-row{
  display:grid;grid-template-columns:5.5rem 1fr auto;gap:1rem;align-items:baseline;
  padding:1.15rem 0;border-bottom:1px solid var(--line);
  transition:background .4s var(--expo),padding-left .5s var(--expo);
}
.aw-row:hover{padding-left:.6rem;background:linear-gradient(90deg,var(--blue-soft),transparent)}
.aw-row .yr{font-weight:800;color:var(--ink);font-size:.95rem}
.aw-row .desc{display:flex;flex-direction:column;gap:.15rem}
.aw-row .proj{font-weight:700;color:var(--ink)}
.aw-row .comp{font-size:.8rem;color:var(--mute)}
.aw-row .tier{font-weight:700;font-size:.72rem;letter-spacing:.08em;text-transform:uppercase;color:var(--ink-2)}
.aw-row .tier.gold{color:var(--blue)}

/* --------------------------------------------------------------- director --- */
/* ---------------------------------------------------------------- director --
   A personal credential, so it is built around the person: a circular
   portrait against the paper ground, the claim beside it at headline scale,
   then three brands he designed carried as small, quiet evidence. The
   visuals are deliberately modest — the sentence is the argument, the
   packaging just proves it is real. */
/* The ground outside the outlined panel is brand blue, running straight into
   the blue Approach section below so the two read as one field. Everything
   INSIDE .dirbox is unchanged — the box carries the paper it used to inherit
   from the section (see .dirbox), so the portrait, the claim and the white
   .bbox look exactly as they did on warm paper.
   The top padding is back: it was zeroed only because Services and this
   section used to share the same paper and their facing paddings stacked into
   one dead ~317px gap. Different grounds now, so the boundary needs its space. */
.director-section{background:var(--blue)}

/* no leading hairline on the director's eyebrow — it reads as a job title,
   not a section label */
.dir .eyebrow{gap:0}
.dir .eyebrow::before{display:none}

.dir{
  display:grid;grid-template-columns:auto 1fr;
  gap:clamp(1.6rem,4vw,3.5rem);align-items:center;
  margin-bottom:clamp(3rem,6vw,5rem);
}
.dir__photo{
  width:clamp(112px,13vw,180px);aspect-ratio:1;flex:none;
  border-radius:50%;overflow:hidden;position:relative;
  background:var(--ink);
}
.dir__photo::after{
  content:"";position:absolute;inset:0;border-radius:50%;
  border:1px solid rgba(10,0,255,.22);
}
.dir__photo img{width:100%;height:100%;object-fit:cover;display:block}
.dir__h{font-size:clamp(1.75rem,4.4vw,3.4rem);letter-spacing:-.03em;line-height:1.04;max-width:19ch;text-wrap:balance}
.dir__p{color:var(--mute);font-size:clamp(.94rem,1.05vw,1.06rem);max-width:56ch;margin:1.1rem 0 0}
.dir__sign{margin-top:1.5rem;display:flex;flex-wrap:wrap;align-items:baseline;gap:.3rem .9rem}
.dir__sign .sig{font-weight:800;font-size:1rem}
.dir__sign .role{font-size:.78rem;color:var(--mute)}
/* The place is separated by the row's own gap, like the name and the link
   before it — a drawn "·" here sat in the middle of that gap and read as a
   stray mark, and it would have hung off the line start whenever the row
   wrapped on a phone. */
.dir__sign .loc{font-size:.78rem;color:var(--mute)}
.dir__sign a{font-weight:700;font-size:.78rem;color:var(--blue)}

/* the three brands — small by design */
/* One outlined panel around the whole director credential — portrait, title
   and signature at the top, the brand record beneath. The frame is drawn in
   brand blue and left transparent so the section's warm paper shows through;
   the inner .bbox stays white, which is what separates the two tiers instead
   of a second heavy border. */
/* ---- homepage section: industrial & structural design ----------------------
   The discipline the rest of the page under-argues, given its own boxed
   section. Drawn as a bordered panel rather than a full-bleed band because
   the subject is containers — the frame is part of the argument. The award
   badge is deliberately the loudest element in it: it is the point of the
   section that these are JURIED structural wins, not artwork prizes. The
   awards table further down carries the same Greyder record; keep them in
   step. */
/* Sits directly ABOVE the services list and shares its ground, so the two read
   as one band: this section gives up its bottom padding and the services
   section's own top padding is the gap between them. */
.gfeat{background:var(--paper-2);padding-bottom:0}
.gbox{
  border:1px solid var(--blue);background:var(--paper);
  padding:clamp(1.4rem,3.2vw,2.8rem);
  display:flex;flex-direction:column;align-items:flex-start;
}
.gbox__head{max-width:62ch;margin-bottom:clamp(1.8rem,3.6vw,2.8rem)}
.gbox__h{font-size:clamp(1.7rem,3.4vw,2.9rem);letter-spacing:-.03em;line-height:1.04;text-wrap:balance;margin:0}
.gbox__h em{font-style:normal;color:var(--blue)}
.gbox__h a{color:inherit}
.gbox__p{color:var(--ink-2);margin:1rem 0 0;max-width:64ch;font-size:clamp(.95rem,1.1vw,1.06rem)}

/* the two projects */
.gprj{display:grid;grid-template-columns:1fr 1fr;gap:clamp(1.5rem,3.4vw,3rem);width:100%}
.gprj__item{display:flex;flex-direction:column;align-items:flex-start}
/* `contain`, not `cover`. These are objects, and an industrial-design section
   that crops the trigger head off the bottle to fill a rectangle is arguing
   against itself. Both renders sit on light grounds, so the pale field they
   letterbox into reads as a spec plate rather than as a gap. */
.gprj__media{
  display:grid;place-items:center;width:100%;aspect-ratio:16/10;overflow:hidden;
  background:var(--paper-2);margin-bottom:1.2rem;padding:clamp(.6rem,1.4vw,1.1rem);
}
.gprj__media img{width:100%;height:100%;object-fit:contain;display:block;transition:transform 1.1s var(--expo)}
.gprj__item:hover .gprj__media img{transform:scale(1.04)}
.gprj__h{font-size:clamp(1.1rem,1.7vw,1.4rem);letter-spacing:-.02em;line-height:1.15;margin:.9rem 0 0;text-wrap:balance}
.gprj__p{color:var(--ink-2);margin:.7rem 0 0;font-size:.95rem;line-height:1.6}

/* the badge — solid brand blue, set as a credential rather than a sticker */
.gbox__badge{
  display:inline-flex;align-items:center;gap:.5rem;
  background:var(--blue);color:#fff;
  font-weight:800;font-size:.68rem;letter-spacing:.16em;text-transform:uppercase;
  padding:.5rem .8rem;
}
.gbox__badge svg{width:12px;height:12px;flex:none;fill:currentColor}
/* the same chip, drawn quiet: it labels a discipline, it does not claim a jury */
.gbox__badge--quiet{background:transparent;color:var(--ink-2);border:1px solid var(--line);font-weight:700}
.gbox__awards{
  list-style:none;margin:1.1rem 0 0;padding:1rem 0 0;border-top:1px solid var(--line);
  display:flex;flex-wrap:wrap;gap:.35rem 1.2rem;width:100%;
}
.gbox__awards li{font-weight:600;font-size:.68rem;letter-spacing:.09em;text-transform:uppercase;color:var(--mute)}
.gbox__awards b{color:var(--blue);font-weight:800}
.gbox__foot{
  margin:clamp(1.8rem,3.4vw,2.6rem) 0 0;padding-top:clamp(1.2rem,2.4vw,1.8rem);
  border-top:1px solid var(--line);width:100%;
  color:var(--mute);font-size:.88rem;line-height:1.65;max-width:82ch;
}
.gbox__foot a{color:var(--blue);font-weight:700}
.gbox .btn{margin-top:1.5rem}
@media(max-width:900px){
  .gprj{grid-template-columns:1fr;gap:2.2rem}
  .gprj__media{aspect-ratio:16/10}
}

.dirbox{
  /* the panel now carries the warm paper itself, since the section around it
     is blue — this is what keeps the inside of the box identical */
  background:var(--paper-2);
  border:1px solid var(--blue);
  padding:clamp(1.4rem,3.2vw,2.8rem);
}

/* ---- the director's own credential, boxed ---------------------------------
   The three brands are Akin's personal creative-direction credits, not
   Tasarist studio projects. On a page that also carries the studio's award
   record, adjacency alone would blur the two — so they sit inside a drawn
   panel on white, lifted off the section's warm paper, with a heading that
   names him. The box IS the attribution. */
.bbox{
  background:var(--paper);border:0;
  padding:clamp(1.5rem,3.4vw,3rem);
  margin-top:clamp(2.4rem,5vw,4rem);
}
.bbox__head{margin-bottom:clamp(1.5rem,3vw,2.4rem)}
/* no leading rule here — this eyebrow runs long (it carries the award credit)
   and the hairline made it read as a list item rather than a credential */
.bbox__head .eyebrow{gap:0;align-items:baseline;line-height:1.5;max-width:52ch}
.bbox__head .eyebrow::before{display:none}
/* the Red Dot column is the taller of the two and sets the row height, so the
   claim centres against it rather than hanging from the top edge */
.bbox__h{
  margin:0;align-self:center;position:relative;top:10px;font-size:clamp(1.3rem,2.6vw,2rem);
  letter-spacing:-.03em;line-height:1.08;max-width:24ch;text-wrap:balance;
}
.bbox__h em{font-style:normal;color:var(--blue)}
/* claim left, Red Dot credit right */
.bbox__headrow{
  display:grid;grid-template-columns:1fr auto;
  gap:clamp(1.2rem,3vw,2.6rem);align-items:start;
  /* both columns start 15px below the panel's inner edge: .bbox's own padding
     is subtracted back out, as a calc so it holds when the clamp scales down */
  margin-top:calc(15px - clamp(1.5rem,3.4vw,3rem));
}
/* Sits 15px below the panel's top edge and keeps 20px under the caption.
   The figure itself carried no padding — the space came from .bbox's own
   padding above it, so the top offset is that padding subtracted back out
   and stays correct as the clamp scales with the viewport. */
.reddot{
  margin:0;
  display:flex;flex-direction:column;align-items:flex-start;gap:.7rem;max-width:17rem;
}
.reddot img{width:clamp(56px,6vw,76px);height:auto;flex:none;display:block}
.reddot figcaption{
  font-size:.72rem;line-height:1.5;color:var(--mute);
}
.reddot figcaption b{color:var(--ink-2);font-weight:700}
/* four credentials under the claim, in the same figure-over-label voice the
   hero proof points and the 50+ award figure already use */
.bbox__pts{
  list-style:none;margin:20px 0 0;padding:0;
  display:grid;grid-template-columns:repeat(4,1fr);gap:clamp(1rem,2.2vw,2rem);
  border-top:1px solid var(--line);padding-top:clamp(1.1rem,2vw,1.5rem);
}
.bbox__pts b{
  display:block;font-weight:800;letter-spacing:-.03em;line-height:1;
  font-size:clamp(1.3rem,2.2vw,1.85rem);color:var(--blue);
}
.bbox__pts span{
  display:block;margin-top:.5rem;font-weight:600;font-size:.66rem;
  letter-spacing:.1em;text-transform:uppercase;color:var(--mute);line-height:1.45;
}
.bcards{display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(1.2rem,2.6vw,2.4rem)}
/* .bcard, NOT .brand — the header's logo link owns .brand, and naming these
   cards the same stacked the wordmark above "Canada" and drew a rule across
   the header. */
.bcard{
  display:flex;flex-direction:column;
  border-top:1px solid var(--line);padding-top:1.1rem;
}
/* Logo and both product shots share ONE equal-column row, so every brand
   presents three tiles of identical width instead of a small logo stranded
   above a pair of photos. The logo keeps its own aspect inside its tile
   (object-fit:contain on white); the photographs fill theirs (cover). */
.bcard__row{display:grid;grid-template-columns:repeat(3,1fr);gap:6px;margin-bottom:1rem}
.bcard__row img{
  width:100%;aspect-ratio:4/3;display:block;
  background:var(--line);border-radius:2px;
  transition:transform .9s var(--expo);
}
.bcard__shot{object-fit:cover}
.bcard__row img.bcard__logo{object-fit:contain;background:#fff;border:0;padding:0;
  /* no frame and no inset: the wordmark scales to the full tile so it reads
     at the same weight as the two product shots beside it */
  transform-origin:center}
.bcard:hover .bcard__row img{transform:scale(1.03)}
/* which agency produced the work, and how far the pack travels. Akin's credit
   is constant across all three; the studio behind it and the reach are not. */
.bcard__meta{
  display:flex;flex-direction:column;gap:.25rem;margin-bottom:.8rem;
  font-weight:700;font-size:.63rem;letter-spacing:.13em;text-transform:uppercase;
}
.bcard__agency{color:var(--blue)}
.bcard__reach{color:var(--ink-2)}
.bcard__fig{margin:0 0 .6rem;font-size:.86rem;line-height:1.55;color:var(--ink-2)}
.bcard__fig b{font-weight:800;color:var(--blue)}
.bcard__src{
  margin-top:auto;font-size:.63rem;font-weight:700;letter-spacing:.12em;
  text-transform:uppercase;color:var(--mute);
}

/* ----------------------------------------------------------------- reach ---- */
/* oriental line-work — 8-pointed star + octagon lattice, an Istanbul nod in
   brand blue. overflow:clip lets the bg layer pin (sticky) without becoming a
   scroll container; the fade keeps the copy the priority. */
.reach{position:relative;overflow:clip;background:var(--paper)}
.reach-bg{
  position:sticky;top:0;height:100vh;
  /* pull up over the section's top padding so the pattern starts at the very
     top edge; the bottom margin compensates so content flow is unchanged. */
  margin-top:calc(-1 * clamp(5rem,11vw,10rem));
   margin-bottom:calc(clamp(5rem,11vw,10rem) - 100vh); 
  pointer-events:none;z-index:0;
  background-image:url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='120'%20height='120'%20viewBox='0%200%20120%20120'%3E%3Cg%20fill='none'%20stroke='%230a00ff'%20stroke-width='0.6'%3E%3Cpolygon%20points='32,60%2060,32%2088,60%2060,88'/%3E%3Cpolygon%20points='40,40%2080,40%2080,80%2040,80'/%3E%3Cpath%20d='M40,40%20L0,0%20M80,40%20L120,0%20M80,80%20L120,120%20M40,80%20L0,120'/%3E%3Cpolygon%20points='0,-14%2014,0%200,14%20-14,0'/%3E%3Cpolygon%20points='120,-14%20134,0%20120,14%20106,0'/%3E%3Cpolygon%20points='0,106%2014,120%200,134%20-14,120'/%3E%3Cpolygon%20points='120,106%20134,120%20120,134%20106,120'/%3E%3C/g%3E%3C/svg%3E");
  background-size:132px 132px;
  opacity:1;
  /* soft fade-in at the very top so the headline stays clean; the rest is even */
  -webkit-mask-image:linear-gradient(to bottom, transparent 0, #000 15%);
  mask-image:linear-gradient(to bottom, transparent 0, #000 15%);
}
/* White gradient anchored to the SECTION's bottom edge, not the viewport's.
   As a sticky element it released before the section ended, so the lattice
   came back at full strength across the ~158px of bottom padding and hard-cut
   into the next section. Absolute/bottom:0 guarantees the pattern is always
   fully faded out by the time the section closes. Tall enough to clear that
   padding at every viewport. */
.reach-fade{
  position:absolute;left:0;right:0;bottom:0;
  height:clamp(220px,36vh,460px);
  pointer-events:none;z-index:1;
  background:linear-gradient(to bottom, transparent 0, var(--paper) 82%);
}
.reach .wrap{position:relative;z-index:10}
.fluency-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(1.5rem,4vw,3.5rem)}
.fluency{padding-top:0}
.fluency{padding-bottom:20px}
/* +25%: 44-56px -> 55-70px */
.fl-ico{display:block;width:clamp(55px,5.75vw,70px);height:auto;margin:0 0 1.2rem}
.fluency .fl-k{display:block;border-top:2px solid var(--blue);padding-top:1.1rem;font-weight:700;font-size:.62rem;letter-spacing:.2em;text-transform:uppercase;color:var(--blue);margin-bottom:.55rem}
.fluency h3{font-size:clamp(1.15rem,1.7vw,1.5rem);letter-spacing:-.02em;line-height:1.12}
.fluency p{color:var(--mute);margin:.85rem 0 0;font-size:.92rem;line-height:1.55}

/* --------------------------------------------------------------- contact ---- */
.contact{position:relative;background:var(--ink);color:#fff;overflow:hidden;padding-block:clamp(5.5rem,12vw,11rem)}
.contact__inner{position:relative;z-index:2;text-align:center}
.contact .eyebrow{color:#fff;justify-content:center}
.contact .eyebrow::before{background:#fff}
.contact__head{color:#fff;font-size:clamp(2.6rem,8vw,7rem);letter-spacing:-.045em;line-height:.92}
.contact__head .u{color:#fff;background:var(--blue);padding:0 .1em}
.contact__mail{
  display:inline-block;margin-top:2.2rem;font-weight:700;
  font-size:clamp(1.1rem,3vw,2rem);letter-spacing:-.01em;color:#fff;
  border-bottom:2px solid rgba(255,255,255,.35);padding-bottom:.2rem;
  transition:border-color .5s var(--expo),color .5s var(--expo);
}
.contact__mail:hover{border-color:var(--blue);color:#fff}
.contact__meta{display:flex;justify-content:center;gap:2rem;flex-wrap:wrap;margin-top:2.6rem;font-size:.8rem;color:rgba(255,255,255,.6)}
.contact__meta a{color:#fff;border-bottom:1px solid rgba(255,255,255,.3)}

/* ----------------------------------------------------------------- footer --- */
.foot{background:#050507;color:#fff;padding:1.6rem var(--gutter)}
.foot__row{display:flex;justify-content:space-between;align-items:center;gap:1.5rem;flex-wrap:wrap}
.foot__id{display:flex;align-items:center;gap:.9rem;flex-wrap:wrap}
.foot__id .logo{height:20px;width:auto}
.foot__co{font-weight:700;font-size:.8rem}
.foot__cp{font-size:.74rem;color:rgba(255,255,255,.5)}
.foot__links{display:flex;align-items:center;gap:1.2rem}
.foot__label{font-size:.66rem;letter-spacing:.16em;text-transform:uppercase;color:rgba(255,255,255,.45)}
.foot__links a{font-weight:600;font-size:.8rem;color:rgba(255,255,255,.85)}
.foot__links a:hover{color:#fff}

/* ------------------------------------------------------------ print marks --- */
.printfield{position:absolute;inset:0;z-index:1;pointer-events:none;display:grid;place-items:center;opacity:.9}
.printfield svg{width:min(78%,900px);height:auto}
.pm{fill:none;stroke:var(--pm,rgba(10,0,255,.16));stroke-width:1.4;vector-effect:non-scaling-stroke}
.pm-bleed,.pm-safe{stroke-dasharray:6 7}
.pm-fold{stroke-dasharray:2 8}
.pm-trim{stroke-dasharray:1;stroke-dashoffset:1;animation:draw 3s var(--expo) forwards}
.pm-dim{stroke-dasharray:1;stroke-dashoffset:1;animation:draw 3s .3s var(--expo) forwards}
.pm-reg{transform-origin:center;animation:spin 26s linear infinite}
.pm-reg--b{animation-duration:34s;animation-direction:reverse}
@keyframes draw{to{stroke-dashoffset:0}}
@keyframes spin{to{transform:rotate(360deg)}}

/* ------------------------------------------------------------ reveal util --- */
.reveal{opacity:0;transform:translateY(26px);transition:opacity .9s var(--expo),transform .9s var(--expo)}
.reveal.in{opacity:1;transform:none}
.reveal.d1{transition-delay:.08s}
.reveal.d2{transition-delay:.16s}
.reveal.d3{transition-delay:.24s}
.reveal.d4{transition-delay:.32s}

/* choreographed hero load */
.hero-load{opacity:0;transform:translateY(20px)}
.loaded .hero-load{opacity:1;transform:none;transition:opacity 1s var(--expo),transform 1s var(--expo)}
.loaded .hero-load.l1{transition-delay:.15s}
.loaded .hero-load.l2{transition-delay:.30s}
.loaded .hero-load.l3{transition-delay:.45s}
.loaded .hero-load.l4{transition-delay:.60s}
.loaded .hero-load.l5{transition-delay:.75s}
/* tile cascade */
.tile{opacity:0;transform:scale(1.04);transition:opacity .9s var(--expo),transform 1.1s var(--expo)}
.loaded .tile{opacity:1;transform:none}

/* --------------------------------------------------------------- responsive - */
@media(max-width:1024px){
  .why-grid{grid-template-columns:1fr}
  .ap-split{grid-template-columns:1fr;gap:clamp(1.5rem,3vh,2.4rem)}
  .ap-split--flip{grid-template-columns:1fr}
  .cbp-triad{max-width:min(52vw,420px)}
  .section-head{grid-template-columns:1fr;align-items:start}
  /* the endorsement drops below the heading instead of beside it */
  .svc-top{grid-template-columns:1fr;gap:clamp(1.8rem,4vw,2.6rem)}
  .awards__top{grid-template-columns:1fr}
}
/* ===== MOBILE MENU · "the press sheet" ====================================
   A packaging studio's menu should look like something coming off a press.
   The sheet drops from the top in electric blue, the registration marks sit
   under it as the house watermark, and the five destinations are set as
   monumental Montserrat with blush index numerals and hairline rules — the
   same typographic voice as the page it covers. Items stagger up on a custom
   expo curve; the burger draws itself into a cross. No slide-in drawer, no
   grey scrim, nothing that could belong to another brand.
   ========================================================================= */
@media(max-width:760px){
  .nav{
    position:fixed;inset:0;width:100%;z-index:70;
    flex-direction:column;align-items:stretch;justify-content:center;gap:0;
    background:var(--blue);
    padding:5.5rem var(--gutter) 1.6rem;
    overflow-y:auto;overscroll-behavior:contain;
    transform:translateY(-100%);
    transition:transform .8s var(--expo-io),visibility 0s linear .8s;
    visibility:hidden;
  }
  .nav.open{transform:none;visibility:visible;transition:transform .8s var(--expo-io),visibility 0s}
  /* No backdrop blur on the header under 760px. `backdrop-filter` makes an
     element the containing block for its fixed-position descendants, and the
     press-sheet menu lives INSIDE .site-header — so the blur trapped a
     position:fixed;inset:0 panel inside the 114px-tall bar and the menu opened
     as a sliver. It broke on every sub-page (.site-header--solid is always
     blurred) and on the homepage as soon as the header picked up .scrolled.
     A near-opaque white reads the same on a phone and costs nothing. */
  /* .site-header--solid is declared LATER in the file (the portfolio-page
     block), so this needs the extra class to outrank it rather than relying
     on source order inside the media query. */
  .site-header.scrolled,.site-header.site-header--solid{
    backdrop-filter:none;-webkit-backdrop-filter:none;
    background:rgba(255,255,255,.97);
  }

  /* registration-mark watermark, the house texture */
  .nav__mark{display:grid;position:absolute;inset:0;place-items:center;pointer-events:none;opacity:.5}
  .nav__foot{display:flex}
  .nav__mark svg{width:150%;height:auto}
  /* <use> builds a shadow tree, so ".nav__mark .pm" never matches inside it.
     Set the inherited custom property the marks already read instead — the
     same trick .printfield uses elsewhere on the page. */
  .nav__mark{--pm:rgba(255,255,255,.3)}

  .nav > a:not(.btn){
    position:relative;z-index:2;
    display:flex;align-items:baseline;gap:.85rem;
    padding:.5rem 0;
    border-top:1px solid rgba(255,255,255,.26);
    color:#fff;font-weight:800;letter-spacing:-.035em;line-height:1.04;
    font-size:clamp(1.9rem,10vw,2.9rem);
    opacity:0;transform:translateY(28px);
    transition:opacity .7s var(--expo),transform .85s var(--expo),color .4s var(--expo);
  }
  .nav > a:not(.btn)::before{
    content:attr(data-n);flex:0 0 auto;
    font-size:.66rem;font-weight:700;letter-spacing:.16em;color:var(--blush);
  }
  .nav > a:not(.btn):active{color:var(--blush)}
  .nav.open > a:not(.btn){opacity:1;transform:none}
  .nav.open > a:nth-of-type(1){transition-delay:.20s}
  .nav.open > a:nth-of-type(2){transition-delay:.27s}
  .nav.open > a:nth-of-type(3){transition-delay:.34s}
  .nav.open > a:nth-of-type(4){transition-delay:.41s}
  .nav.open > a:nth-of-type(5){transition-delay:.48s}

  .nav .btn{
    position:relative;z-index:2;justify-content:center;
    margin-top:1.5rem;--bg:#fff;--fg:var(--blue);border-color:#fff;
    padding:1.05rem 1.4rem;font-size:.8rem;
    opacity:0;transform:translateY(28px);
    transition:opacity .7s var(--expo) .55s,transform .85s var(--expo) .55s;
  }
  .nav.open .btn{opacity:1;transform:none}
  /* in the menu sheet the switch is a white outlined box under the links */
  .nav > a.lang{
    align-self:flex-start;margin-top:1.4rem;
    padding:1.05rem 1.4rem;border:1px solid #fff;
    font-size:.8rem;font-weight:700;letter-spacing:.04em;line-height:inherit;
    transition-delay:.52s;
  }
  .nav > a.lang::before{display:none}

  .nav__foot{
    position:relative;z-index:2;margin-top:1.9rem;
    display:flex;flex-direction:column;gap:.5rem;
    opacity:0;transform:translateY(20px);
    transition:opacity .7s var(--expo) .64s,transform .8s var(--expo) .64s;
  }
  .nav.open .nav__foot{opacity:1;transform:none}
  .nav__mail{font-size:1rem;font-weight:700;color:#fff;letter-spacing:-.01em;
    border-bottom:1px solid rgba(255,255,255,.45);align-self:flex-start;padding-bottom:2px}
  .nav__meta{font-size:.68rem;font-weight:600;letter-spacing:.11em;text-transform:uppercase;color:rgba(255,255,255,.62)}
  .nav__meta a{color:#fff}
  .nav__dot{color:var(--blush)}

  /* The burger used to be bare white bars, which vanished against any light
     section and depended entirely on the .scrolled class landing in time.
     It is now a solid brand-blue tile with white bars: legible on the dark
     hero, on white sections and on the blue Approach panel alike, with no
     contrast guesswork. position:relative so its z-index actually applies —
     as a static element it was being painted under .nav (fixed, z-index 70).
     When the sheet is open the tile drops away, leaving a white cross. */
  /* Solid brand-blue tile with white SVG strokes: legible on the dark hero, on
     white sections and on the blue Approach panel alike, with no contrast
     guesswork and no dependence on flexbox `gap`. position:relative so the
     z-index actually applies — as a static element it painted under .nav.
     Open state drops the tile and shows the cross. */
  .nav-toggle{
    position:relative;z-index:80;
    display:grid;place-items:center;
    width:44px;height:44px;padding:0;border:0;cursor:pointer;
    background:var(--blue);border-radius:2px;
    transition:background .4s var(--expo);
  }
  .nav-toggle__i{
    grid-area:1/1;width:24px;height:24px;
    fill:none;stroke:#fff;stroke-width:2;stroke-linecap:round;
    transition:opacity .3s var(--expo),transform .45s var(--expo);
  }
  .nav-toggle__i--close{opacity:0;transform:rotate(-45deg) scale(.7)}
  /* Before the first scroll the header carries no background at all, so a
     solid blue tile floating on the hero read as a stray UI chip. While the
     header is bare the tile goes bare too — white strokes alone on the dark
     hero. The moment .scrolled paints the white bar behind it, the tile
     returns and the contrast guesswork above stays solved. */
  .site-header:not(.scrolled) .nav-toggle{background:transparent}
  .nav-toggle[aria-expanded="true"]{background:transparent}
  .nav-toggle[aria-expanded="true"] .nav-toggle__i--menu{opacity:0;transform:rotate(45deg) scale(.7)}
  .nav-toggle[aria-expanded="true"] .nav-toggle__i--close{opacity:1;transform:none}
  .scroll-cue{display:none}
  /* Three proof points, one row — always. As a wrapping flexbox the third
     item (EN·FR) dropped to its own line and read as an afterthought rather
     than as the third leg of the claim. A fixed 3-column grid keeps them
     abreast; the number and label ladders come down to pay for it. */
  .hero-meta{
    display:grid;grid-template-columns:repeat(3,1fr);
    gap:.75rem;margin-top:2rem;
  }
  .hero-meta .n{font-size:clamp(1.05rem,5vw,1.45rem)}
  .hero-meta .l{font-size:.52rem;letter-spacing:.07em;margin-top:.4rem;max-width:none}
  .feat__hero{aspect-ratio:4/3}
  .mosaic{grid-template-columns:repeat(2,1fr);grid-auto-rows:clamp(140px,32vw,200px)}
  .tile.big{grid-column:span 2;grid-row:span 1}
  .tile.wide{grid-column:span 2}
  .tile.tall{grid-row:span 1}
  /* The featured Shabby Chic project leads the section on a phone. Stacked,
     the two why-cards run long enough that the project images landed far
     below the fold; the work should be the first thing under the heading. */
  .why-grid .feat{order:-1}
  .svc{grid-template-columns:1fr;gap:.8rem}
  .svc__no{padding-top:0}
  .fluency-grid{grid-template-columns:1fr}
  /* director: portrait stacks above the claim, brands become one column */
  .dir{grid-template-columns:1fr;gap:1.4rem;text-align:left}
  .bcards{grid-template-columns:1fr;gap:1.6rem}
  /* four credentials go two-up rather than shrinking to unreadable columns */
  .bbox__pts{grid-template-columns:repeat(2,1fr);gap:1.1rem}
  /* Red Dot credit drops under the claim rather than squeezing beside it */
  .bbox__headrow{grid-template-columns:1fr;gap:1.2rem}
  .reddot{max-width:none}
  /* One line, always. The string is fixed-length, so size is driven off the
     viewport rather than a fixed rem: at 390px it needs ~10px to fit the 350px
     of usable width. The rem cap stops it ballooning near 760px. */
  /* centred on a phone; the desktop layout keeps it flush right */
  .work-cap{justify-content:center}
  .work-cap__note{white-space:nowrap;font-size:min(2.3vw,.8rem)}
  .ap-rail__mark{display:none}
  .ap-chap span{display:none}
  /* Rail to the TOP of the stage. The stage already starts at var(--hdr), so
     top:0 parks the icons and the progress bar directly under the fixed
     header and the spread's content begins beneath them — read the chapter
     you're on before the copy, not after it. The clearance vars flip with it
     so the panels gain the room at the top and give it back at the bottom. */
  .approach{--ap-clear-t:2.6rem;--ap-clear-b:0rem}
  .ap-rail{top:0;bottom:auto;padding:.8rem clamp(1.6rem,3.4vw,4.5rem) .65rem}
  /* Phones get the SAME treatment as desktop: the hero copy pins and the work
     scrolls behind it. This used to switch the pin off and stack the copy as a
     flat dark block above the grid, so the tiles only started moving after the
     hero had scrolled away — the one moment the page is built around never
     happened on a phone.
     The wash has to change with it. On desktop it runs horizontally (copy left,
     tiles breathing on the right), which does nothing for a full-width phone
     column, so here it becomes a vertical scrim: opaque through the middle
     where the type sits, clearing at both ends so the tiles read as they
     travel in and out. */
  .hero-overlay{
    /* A circle anchored at the bottom-left corner, opening toward the top
       right: the type sits in the dense part of it and the work clears as the
       field opens, so the corner the eye leaves from is the one that shows the
       packaging. The second, flat layer is not decoration — it is the floor
       that keeps the headline and the proof points legible where the circle
       has already thinned out. */
    background:
      radial-gradient(135% 100% at 0% 100%,
        rgba(6,6,10,.97) 0%,
        rgba(6,6,10,.93) 38%,
        rgba(6,6,10,.74) 62%,
        rgba(6,6,10,.34) 82%,
        rgba(6,6,10,0) 100%),
      linear-gradient(180deg,
        rgba(6,6,10,0) 0%,
        rgba(6,6,10,.44) 13%,
        rgba(6,6,10,.62) 28%,
        rgba(6,6,10,.62) 84%,
        rgba(6,6,10,.26) 95%,
        rgba(6,6,10,0) 100%);
  }
  /* Black air above the work. With the mosaic starting flush, the first tiles
     sat under the transparent header at rest and read as images bleeding
     behind the UI. Starting them a header-and-a-bit down opens a band of the
     showcase's own ink at the top, so the packaging enters from clean black as
     you scroll rather than already being there. */
  .mosaic{padding-top:calc(var(--hdr) + 4.5rem)}
}

/* Short phones, and any phone held in landscape. The pinned hero has exactly
   one screen for the kicker, headline, lead, both buttons and the three proof
   points; at 640px tall that stack measures ~636px against ~512px of usable
   height, so the pin would cut it. Nothing is hidden — the ladder is
   compressed until it fits, and only at this height: an 844px-tall phone keeps
   the generous scale above. */
@media(max-width:760px) and (max-height:700px){
  .hero-overlay{padding-top:4.7rem;padding-bottom:1.1rem}
  .hero-kicker{margin-bottom:.8rem;letter-spacing:.2em}
  .hero-h1{font-size:clamp(2.15rem,9.5vw,2.7rem)}
  .hero-lead{margin-top:1rem;font-size:.93rem;line-height:1.5}
  .hero-cta{margin-top:1.3rem;gap:.65rem}
  .hero-meta{margin-top:1.3rem}
}

/* ------------------------------------------------------ reduced motion ------ */
@media(prefers-reduced-motion:reduce){
  *{animation-duration:.001ms!important;animation-iteration-count:1!important;transition-duration:.001ms!important}
  .reveal,.hero-load,.tile,.ap-panel .r{opacity:1!important;transform:none!important}
  .pm-trim,.pm-dim,.cbp .draw{stroke-dashoffset:0}
  .ap-swipe i::after{display:none}
  .scroll-cue::after{display:none}
  html{scroll-behavior:auto}
}

/* ============================================================================
   PORTFOLIO PAGE (portfolio.html) — sector-filterable packaging index
   ============================================================================ */
.site-header--solid{background:rgba(255,255,255,.9);backdrop-filter:blur(14px);box-shadow:0 1px 0 var(--line)}
.site-header--solid .brand .logo--dark{display:block}
.site-header--solid .brand .logo--light{display:none}
.site-header--solid .brand .locale{color:var(--ink)}
.site-header--solid .nav > a:not(.btn){color:var(--ink)}

.pf-hero{padding:clamp(7rem,14vh,10rem) var(--gutter) clamp(2.5rem,5vw,4rem);max-width:var(--maxw);margin-inline:auto}
.pf-hero h1{font-size:clamp(2.6rem,7vw,5.5rem);letter-spacing:-.04em;line-height:.95;max-width:14ch}
.pf-hero .pf-lead{margin-top:1.4rem;max-width:56ch;color:var(--mute);font-size:clamp(1rem,1.3vw,1.2rem)}

.pf-filters{
  position:sticky;top:60px;z-index:40;background:rgba(255,255,255,.9);backdrop-filter:blur(12px);
  display:flex;flex-wrap:wrap;gap:.6rem;align-items:center;
  padding:1rem var(--gutter);border-block:1px solid var(--line);max-width:100%;
}
.pf-chip{
  font-family:var(--font);font-weight:600;font-size:.82rem;letter-spacing:.01em;
  color:var(--ink-2);background:var(--paper);border:1px solid var(--line);border-radius:2px;
  padding:.6rem 1rem;cursor:pointer;transition:background .3s var(--expo),color .3s var(--expo),border-color .3s var(--expo);
}
.pf-chip:hover{border-color:var(--ink)}
.pf-chip .n{font-weight:700;color:var(--mute);margin-left:.4rem;font-size:.78rem}
.pf-chip.is-active{background:var(--blue);border-color:var(--blue);color:#fff}
.pf-chip.is-active .n{color:rgba(255,255,255,.75)}

.pf-grid{
  max-width:var(--maxw);margin-inline:auto;padding:clamp(2rem,4vw,3.5rem) var(--gutter) clamp(4rem,8vw,7rem);
  display:grid;grid-template-columns:repeat(3,1fr);
  gap:clamp(16px,1.8vw,26px);   /* equal vertical + horizontal spacing */
}
.pf-item{opacity:1;transition:opacity .4s var(--expo),transform .5s var(--expo)}
.pf-item[hidden]{display:none}
.pf-thumb{position:relative;overflow:hidden;background:var(--paper-2);aspect-ratio:4/3;border:1px solid var(--line)}
.pf-thumb img{width:100%;height:100%;object-fit:cover;transition:transform 1s var(--expo)}
.pf-item:hover .pf-thumb img{transform:scale(1.05)}
/* A card that has a case study behind it becomes one link. The "view" line is
   held back until hover or keyboard focus so the grid stays a wall of work
   rather than a wall of calls to action — but it is always in the DOM, so it
   is announced and reachable without a pointer. */
.pf-open{display:block;color:inherit;text-decoration:none}
/* Award tag. Sits on the thumbnail, always visible — unlike .pf-more it is not
   a call to action, it is a fact about the project, and a fact you have to
   hover to discover is not doing its job. Only on cards where the awarded item
   IS the pictured project; see the note at the top of portfolio.html. */
.pf-thumb{position:relative}
.pf-award{
  position:absolute;top:0;left:0;z-index:2;
  display:inline-flex;align-items:center;gap:.4rem;
  background:var(--blue);color:#fff;
  font-weight:800;font-size:.6rem;letter-spacing:.14em;text-transform:uppercase;
  padding:.45rem .65rem;
}
.pf-award svg{width:10px;height:10px;flex:none;fill:currentColor}
.pf-more{
  display:block;margin-top:.55rem;font-weight:700;font-size:.68rem;
  letter-spacing:.12em;text-transform:uppercase;color:var(--blue);
  opacity:0;transform:translateY(4px);
  transition:opacity .45s var(--expo),transform .45s var(--expo);
}
.pf-more i{font-style:normal}
.pf-open:hover .pf-more,.pf-open:focus-visible .pf-more{opacity:1;transform:none}
@media(hover:none){.pf-more{opacity:1;transform:none}}
.pf-meta{padding:1rem .2rem 0}
.pf-meta h3{font-size:1.15rem;letter-spacing:-.02em}
.pf-meta span{display:block;margin-top:.35rem;font-weight:600;font-size:.72rem;letter-spacing:.1em;text-transform:uppercase;color:var(--mute)}
/* scale line — only some tiles carry one; the figure is a labelled estimate */
.pf-note{margin:.6rem 0 0;font-size:.82rem;line-height:1.5;color:var(--ink-2);max-width:44ch}
.pf-note b{font-weight:700;color:var(--blue)}
.pf-empty{max-width:var(--maxw);margin:0 auto;padding:0 var(--gutter) 6rem;color:var(--mute)}

@media(max-width:1024px){.pf-grid{grid-template-columns:repeat(2,1fr)}}
@media(max-width:600px){.pf-grid{grid-template-columns:1fr}.pf-filters{top:52px}}

/* ============================================================================
   PROJECT PAGE (shabby-chic.html) — single case study
   ============================================================================ */
.proj-back{display:inline-flex;align-items:center;gap:.5rem;font-weight:600;font-size:.76rem;letter-spacing:.06em;text-transform:uppercase;color:var(--mute);margin-bottom:1.4rem;transition:gap .4s var(--expo),color .3s var(--expo)}
.proj-back:hover{gap:.85rem;color:var(--ink)}
.proj-hero{padding:clamp(7rem,13vh,9.5rem) var(--gutter) clamp(2rem,4vw,3rem);max-width:var(--maxw);margin-inline:auto}
.proj-hero h1{font-size:clamp(2.6rem,7vw,5.5rem);letter-spacing:-.04em;line-height:.95}
.proj-hero .sub{margin-top:1.2rem;max-width:54ch;color:var(--mute);font-size:clamp(1rem,1.3vw,1.2rem)}
.proj-lead{max-width:var(--maxw);margin:0 auto clamp(2.5rem,5vw,4rem);padding-inline:var(--gutter)}
.proj-lead figure{aspect-ratio:16/9;overflow:hidden;background:var(--paper-2);border:1px solid var(--line)}
.proj-lead img{width:100%;height:100%;object-fit:cover}
/* ---- the brief -------------------------------------------------------------
   Every case study states the brief it was answering, in the client's terms,
   before any of the studio's own narrative. The point is credibility: a
   visitor who has never heard of Bingo or Greyder should be able to see that
   somebody commissioned this and what they asked for. Set as a quotation
   because that is what it is — the words are the studio's published record of
   the ask, not copy written for this site — and the .proj-brief__src line
   names where they come from. Where a brief was never published, say so in
   that line rather than inventing one. */
.proj-brief{
  max-width:var(--maxw);margin:0 auto;
  padding:0 var(--gutter) clamp(2.5rem,5vw,4rem);
}
.proj-brief__in{border-left:2px solid var(--blue);padding-left:clamp(1.1rem,2.4vw,2rem)}
.proj-brief__k{
  display:block;font-weight:700;font-size:.66rem;letter-spacing:.22em;
  text-transform:uppercase;color:var(--blue);margin-bottom:.9rem;
}
.proj-brief blockquote{margin:0}
.proj-brief blockquote p{
  margin:0;font-weight:700;color:var(--ink);text-wrap:balance;
  font-size:clamp(1.15rem,2.1vw,1.7rem);line-height:1.3;letter-spacing:-.02em;
  max-width:44ch;
}
.proj-brief blockquote p::before{content:"\201C"}
.proj-brief blockquote p::after{content:"\201D"}
.proj-brief__src{margin:1rem 0 0;font-size:.72rem;line-height:1.6;color:var(--mute);max-width:72ch}
.proj-brief__src b{color:var(--ink-2);font-weight:700}

.proj-intro{max-width:var(--maxw);margin:0 auto;padding:0 var(--gutter) clamp(3rem,6vw,5rem);display:grid;grid-template-columns:1fr 1.5fr;gap:clamp(1.5rem,4vw,4.5rem);align-items:start}
.proj-intro h2{font-size:clamp(1.7rem,3.2vw,2.6rem);letter-spacing:-.03em;max-width:15ch}
.proj-intro .body{display:flex;flex-direction:column;gap:1.1rem;color:var(--ink-2);font-size:1.02rem;max-width:62ch}
/* The column spaces its children with `gap`; paragraphs kept their default
   margins on top of it, so every break measured ~50px instead of the ~18px
   intended and the copy read as disconnected blocks. Gap alone owns the rhythm. */
.proj-intro .body > p{margin:0}
.proj-intro .body b{color:var(--ink);font-weight:700}
.proj-facts{display:flex;flex-wrap:wrap;gap:.5rem;margin-top:.5rem}
.proj-facts span{font-weight:600;font-size:.72rem;letter-spacing:.02em;color:var(--ink-2);border:1px solid var(--line);padding:.4rem .7rem;border-radius:2px}
/* ---- sourced credential band, directly under a case-study title ------------
   Every case study opens with what the brand or its owner demonstrably IS —
   parent company, reach, category position — in the same figure-over-label
   voice the hero proof points and the director's .bbox__pts already use, so
   the site states a credential one way.
   HONESTY, non-negotiable (repo CLAUDE.md + BRAND.md): every figure here is
   externally sourced and the .proj-cred__src line names where it came from.
   Nothing in this band may be estimated to sound impressive; a derived number
   is written as an estimate and its basis is stated, the way the Pasta Veneta
   card on portfolio.html does it. A figure with no source does not belong. */
.proj-cred{max-width:var(--maxw);margin:0 auto;padding:0 var(--gutter) clamp(2.5rem,5vw,4rem)}
.proj-cred__pts{
  list-style:none;margin:0;padding:clamp(1.1rem,2vw,1.5rem) 0 0;
  display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));
  gap:clamp(1rem,2.2vw,2rem);border-top:1px solid var(--ink);
}
.proj-cred__pts b{
  display:block;font-weight:800;letter-spacing:-.03em;line-height:1;
  font-size:clamp(1.3rem,2.2vw,1.85rem);color:var(--blue);
}
.proj-cred__pts span{
  display:block;margin-top:.5rem;font-weight:600;font-size:.66rem;
  letter-spacing:.1em;text-transform:uppercase;color:var(--mute);line-height:1.45;
}
.proj-cred__src{margin:clamp(1.1rem,2vw,1.5rem) 0 0;font-size:.72rem;line-height:1.6;color:var(--mute);max-width:88ch}
.proj-cred__src b{color:var(--ink-2);font-weight:700}

.proj-gallery{max-width:var(--maxw);margin:0 auto;padding:0 var(--gutter) clamp(2rem,4vw,3rem);display:grid;grid-template-columns:repeat(2,1fr);gap:clamp(14px,1.6vw,22px)}
.proj-gallery figure{overflow:hidden;background:var(--paper-2);border:1px solid var(--line);aspect-ratio:4/3}
.proj-gallery figure.wide{grid-column:span 2;aspect-ratio:16/9}
.proj-gallery img{width:100%;height:100%;object-fit:cover;transition:transform 1s var(--expo)}
.proj-gallery figure:hover img{transform:scale(1.04)}
/* ---- motion row on a case study -------------------------------------------
   Square product films sit in the same grid rhythm as the gallery. They are
   decoration for the pack, not narrative, so they autoplay muted, loop and
   carry no controls — and each one still ships a poster frame, so the row
   composes correctly before a single byte of video has loaded and on any
   connection that never loads them. */
.proj-films{
  max-width:var(--maxw);margin:0 auto;
  padding:0 var(--gutter) clamp(2rem,4vw,3rem);
  display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(14px,1.6vw,22px);
}
.proj-films figure{margin:0;overflow:hidden;background:var(--paper-2);border:1px solid var(--line);aspect-ratio:1}
.proj-films video{width:100%;height:100%;object-fit:cover;display:block}
@media(max-width:800px){.proj-films{grid-template-columns:1fr}}

.proj-note{max-width:var(--maxw);margin:0 auto;padding:0 var(--gutter) clamp(4rem,8vw,6rem);color:var(--mute);font-size:.82rem;max-width:70ch}
@media(max-width:800px){.proj-intro{grid-template-columns:1fr}.proj-gallery{grid-template-columns:1fr}.proj-gallery figure,.proj-gallery figure.wide{grid-column:span 1;aspect-ratio:4/3}}
