
/* Coordinated with the film, but pulled back toward the drama.

   The first pass sampled the clip honestly and followed it everywhere: the
   picture is one hue (211-220 degrees, #003A78 through #BBCBEA over
   near-black), so every neutral went blue. It was faithful and it was flat --
   a page tinted to match a picture loses the contrast that made it dramatic.

   This keeps what the sampling was RIGHT about and drops what it cost:
     - the ground goes DEEPER than it ever was, and carries the film's own
       hue in the darks (#050B14, 215 degrees) so the page and the water read
       as one place. Only the GROUNDS are tinted -- the ink and the accents
       stay at full strength, because tinting those is what made the first
       attempt flat. Drama
       comes from the distance between the darkest and lightest thing on the
       page, and that gap is now wider than before the film existed.
     - one degree of blue undertone in the darks, so the page and the water
       belong together. Not enough to read as a blue page.
     - the ink returns to near-white and the accents to full strength. A pale
       sampled blue was accurate to the film and weak on the page.
     - --info is the film's DEEP blue lifted for contrast (#1F60AB family),
       not its pale one -- the dramatic half of that ramp, not the misty half.
     - --live is untouched. It is the only non-blue thing here, which is
       exactly why it works. */
:root{
  --g0:#050B14; --g1:#0A1320; --g2:#121E2E;
  --ink:#ECEEF1; --muted:#8E97A2; --dim:#79838F;
  --hair:rgba(236,238,241,.12); --hair-2:rgba(236,238,241,.22);
  --live:#C0FF00; --info:#4A93E8; --warm:#FF7A45; --on-live:#050B14;
}
/* NO LIGHT MODE. This carried one, and it outlived its reason.

   The rest of the site is dark unconditionally -- v3-dark.css redefines the
   old sheet's tokens on a bare :root, and the dashboard does the same -- so on
   a machine set to light these two pages went pale while every other page
   stayed dark. The seam showed at the top of the landing: a pale sticky nav
   above a hero that forces the dark tokens for the film behind it. Measured
   with the OS in light: nav and body #EDF0F4, hero dark.

   Nothing ever set data-theme, so the light palette was never a choice anyone
   could make -- only something that happened to them. The film, the lime and
   the grain were all designed on the dark ground; there is one palette now.

   (.film-hero and body.has-page-film still restate the dark tokens. With one
   palette they are belt and braces rather than load-bearing.) */

*{box-sizing:border-box;margin:0;padding:0}
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth}
@media (prefers-reduced-motion:reduce){html{scroll-behavior:auto}}
body{
  background:var(--g0);color:var(--ink);
  font-family:'JetBrains Mono',ui-monospace,SFMono-Regular,Menlo,monospace;
  font-size:14.5px;line-height:1.62;font-variant-numeric:tabular-nums;
  -webkit-font-smoothing:antialiased;overflow-x:hidden;
}
img{max-width:100%;display:block}
a{color:inherit}
a:focus-visible,button:focus-visible,input:focus-visible{outline:2px solid var(--live);outline-offset:3px}

.dsp{
  font-family:'Jost',Futura,'Century Gothic',system-ui,sans-serif;
  font-weight:700;text-transform:uppercase;
  letter-spacing:-.035em;line-height:.96;text-wrap:balance;
}
h1{font-size:clamp(32px,5.4vw,68px)}
h2{font-size:clamp(21px,2.5vw,31px)}
h3{font-size:clamp(15px,1.5vw,18px)}
.lbl{font-size:11px;letter-spacing:.15em;text-transform:uppercase;color:var(--muted);font-weight:500}
.lbl.live{color:var(--live)}
.muted{color:var(--muted)}
.wrap{max-width:1180px;margin:0 auto;padding:0 clamp(16px,4vw,40px)}
section{border-top:1px solid var(--hair)}
.pad{padding:clamp(34px,4.6vw,68px) 0}

/* masthead */
.top{position:sticky;top:0;z-index:50;background:var(--g0);border-bottom:1px solid var(--hair)}
.top .wrap{display:flex;align-items:center;justify-content:space-between;gap:1rem;padding:.7rem clamp(16px,4vw,40px)}
.brand{display:block;text-decoration:none;flex:none}
.logo-h{display:block;width:clamp(104px,13vw,132px);height:auto;aspect-ratio:1641.1/304.44;
        --lg-word:var(--ink);--lg-mark:var(--live)}
.brand:hover .logo-h{--lg-mark:var(--ink)}
.topnav{display:none;gap:1.5rem}
@media(min-width:880px){.topnav{display:flex}}
.topnav a{font-size:11px;letter-spacing:.14em;text-transform:uppercase;color:var(--muted);text-decoration:none}
.topnav a:hover,.topnav a[aria-current]{color:var(--live)}
.top .cta{font-size:11px;letter-spacing:.14em;text-transform:uppercase;text-decoration:none;
  background:var(--live);color:var(--on-live);padding:.6rem .9rem;font-weight:700}

/* ── the film: full screen, the whole first view ──────────────────────────
   Layer 0 is the clip. Layer 1 is a flat wash so the type holds whatever
   the footage does -- a solid rgba, not a gradient. Layer 2 is the words
   and the micro-labels at the frame edges (Impronta's device). With no
   clip present the hero is simply a dark field, which is the composition
   In My World and Lando Norris both win on, so nothing looks broken while
   the film is being made. */
.film-hero{position:relative;min-height:100svh;display:grid;grid-template-rows:1fr auto;overflow:hidden;border-top:0}
.film-hero picture{position:absolute;inset:0;z-index:0;display:block}
.film{position:absolute;inset:0;z-index:0;width:100%;height:100%;object-fit:cover;object-position:60% center;background:var(--g0)}
.film-wash{position:absolute;inset:0;z-index:1;background:rgba(3,9,17,.46);pointer-events:none}
/* The wash is set from the clip's own measured brightness where the headline
   sits, not by taste. installfilm.py records that number; a bright frame gets
   more darkness, a dark one gets less and lets the picture through. */
.film-hero.has-film .film-wash{background:rgba(3,9,17,.50)}
/* the hero carries the dark palette in BOTH themes, so the picture is never
   washed pale and the white headline is always white */
.film-hero{
  --ink:#ECEEF1;--muted:#C2CAD3;--dim:#7E8792;
  --hair:rgba(236,238,241,.16);--hair-2:rgba(236,238,241,.30);
  --live:#C0FF00;--on-live:#050B14;
}
.film-body{position:relative;z-index:2;align-self:center;padding:clamp(70px,12vh,130px) 0 clamp(30px,5vh,54px)}
.film-body h1{margin:1rem 0 1.2rem;max-width:15ch}
.film-body .say{font-size:15px;line-height:1.65;color:var(--muted);max-width:46ch}
.film-edge{position:relative;z-index:2;border-top:1px solid var(--hair)}
.film-edge .wrap{display:flex;align-items:center;justify-content:space-between;gap:1rem;flex-wrap:wrap;padding-top:.75rem;padding-bottom:.75rem}

/* ── grain ──────────────────────────────────────────────────
   Both lifted off db-longbow.webflow.io, which is where the atmosphere on
   that site actually comes from. Read off its live DOM:

     .noise   position:absolute, a tiled texture at background-size:50px,
              opacity .2, pointer-events:none, sized past the viewport on
              every edge (inset -144px/-256px) so no seam can show.
     2 elements at mix-blend-mode:difference.

   Ours is the same idea with no asset to load: an SVG feTurbulence tile as
   a data URI, a few hundred bytes, stitched so it repeats seamlessly. One
   fixed layer over the whole page instead of one per section.

   --grain is the only knob. Longbow sits at .2 over a mid-grey ground;
   over near-black that reads milky, so we start at .13. Raise it until it
   is felt rather than seen.

   Longbow's difference blend was tried on the headline and dropped: over
   this frame it turned white into a warm off-white, and would have gone
   magenta anywhere the type crossed the lime band. Solid white with a
   sub-pixel dark edge does the job it was meant to do, predictably. */
.grain{
  position:fixed;inset:-160px;z-index:60;pointer-events:none;
  opacity:var(--grain,.13);
  background-repeat:repeat;background-size:190px 190px;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='190' height='190'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.78' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='190' height='190' filter='url(%23n)'/%3E%3C/svg%3E");
}
@media (prefers-reduced-motion:reduce){.grain{opacity:calc(var(--grain,.13) * .7)}}

.film-body h1{color:#fff}

/* A hairline edge, so the white lifts off a busy picture instead of sitting
   in it. paint-order draws the stroke first and the fill over it, so the
   stroke is an edge OUTSIDE the glyph rather than a thinning of it -- at
   .011em it is under a pixel at most sizes, felt rather than seen.
   Falls back to plain white wherever text-stroke is unsupported. */
.film-body h1.out{
  -webkit-text-stroke:.011em rgba(2,7,14,.66);
  paint-order:stroke fill;
}

/* numbers */
.figs{display:grid;grid-template-columns:repeat(2,1fr);border-top:1px solid var(--hair-2);margin-top:clamp(20px,2.6vw,30px)}
@media(min-width:820px){.figs{grid-template-columns:repeat(4,1fr)}}
.fig{padding:1.15rem 1.2rem 1.3rem 0;border-bottom:1px solid var(--hair);display:flex;flex-direction:column;gap:.4rem}
@media(min-width:820px){.fig+.fig{padding-left:1.4rem;border-left:1px solid var(--hair)}}
.fig .n{font-family:'Jost',Futura,'Century Gothic',system-ui,sans-serif;font-weight:700;
  font-size:clamp(34px,4.6vw,56px);line-height:.9;letter-spacing:-.035em}
.fig.a .n{color:var(--live)} .fig.b .n{color:var(--info)}
.fig.c .n{color:var(--warm)} .fig.d .n{color:var(--ink)}

/* ── the landing's picture, held behind the whole sheet ──────────────────
   Dimming the proofs was not enough on its own: eleven white screenshots on
   a flat ground still read as a light grid, because the ground had nothing
   in it. So the portfolio sits on the same frame the landing opens with,
   fixed so it does not scroll, under a heavy wash that turns it from a
   picture into a ground. The proofs are then lit rectangles on a dark field
   rather than the only thing in the frame.
   ───────────────────────────────────────────────────────────────────── */
.page-film{
  position:fixed;inset:0;z-index:0;pointer-events:none;
  background:var(--g0) center/cover no-repeat;
}
.page-film::after{
  content:"";position:absolute;inset:0;background:rgba(5,11,20,.87);
}
/* The backdrop is dark in BOTH themes -- it is a photograph under an .87
   wash, not a themed surface. So the page must carry the dark token set in
   both themes too. Without this, a viewer whose OS is in light mode got
   near-black ink (#0D1116) sitting on a near-black picture: the headline
   measured 2.9:1 and the page was effectively unreadable. Same reasoning as
   .film-hero on the landing. */
body.has-page-film{
  --g0:#050B14; --g1:#0A1320; --g2:#121E2E;
  --ink:#ECEEF1; --muted:#9AA4B0; --dim:#7F8A97;
  --hair:rgba(236,238,241,.12); --hair-2:rgba(236,238,241,.22);
  --live:#C0FF00; --info:#4A93E8; --warm:#FF7A45; --on-live:#050B14;
}
body.has-page-film .top,
body.has-page-film main,
body.has-page-film footer{position:relative;z-index:1}
body.has-page-film footer{background:color-mix(in srgb,var(--g1) 88%,transparent)}

/* ── contact sheet ───────────────────────────────────────────────────── */
.sheet-head{display:flex;justify-content:space-between;gap:1rem;flex-wrap:wrap;
  border-top:1px solid var(--hair-2);border-bottom:1px solid var(--hair);padding:.7rem 0;margin-top:clamp(16px,2.2vw,26px)}
.sheet{display:grid;gap:clamp(26px,4vw,52px) clamp(18px,2.6vw,32px);grid-template-columns:repeat(2,1fr);padding-top:clamp(26px,3.4vw,44px)}
/* Two columns, not three. The captures are 1100px wide; at three across
   they render ~390px and the layout of each site is unreadable. At two
   they run ~560px, which is where a landing page starts to be legible
   as a landing page rather than as a swatch. */
@media(min-width:820px){.sheet{grid-template-columns:repeat(2,1fr)}}
.sheet.teaser{grid-template-columns:repeat(3,1fr)}
.plate{text-decoration:none;color:inherit;display:flex;flex-direction:column;gap:.75rem}
/* 3:2 -- the shape of a 35mm negative, so the frames are the shape a real
   contact sheet's are, and the shape that suits a screen capture. A square
   crop threw away most of every layout. */
.frame{position:relative;aspect-ratio:3/2;background:var(--g2);overflow:hidden}
.frame img{
  width:100%;height:100%;object-fit:cover;object-position:top center;display:block;
  clip-path:inset(0 100% 0 0);
  /* Eleven website screenshots are eleven bright rectangles, and on a
     near-black page they become the only thing you see -- the sheet reads as
     a light grid on dark rather than as anything mysterious. So the proofs
     rest UNDER-DEVELOPED: dimmed and drained of colour, the way a contact
     sheet actually looks, and they come up to full only for the one you go
     to. Filters, not gradients; the page still has none. */
  filter:brightness(.34) saturate(.5) contrast(1.08);
  transition:clip-path .82s cubic-bezier(.24,.72,.2,1),
             filter .5s cubic-bezier(.2,.8,.25,1),
             transform .7s cubic-bezier(.2,.8,.25,1);
  transform:scale(1.02);
}
.plate.in .frame img{clip-path:inset(0 0 0 0)}
.plate:hover .frame img,.plate:focus-visible .frame img{
  filter:brightness(1) saturate(1) contrast(1);
  transform:scale(1);
}
/* ── the live layer ────────────────────────────────────────────────────
   Sits between the capture and the frame furniture: under the corner ticks
   and the name plate, over the still. Transparent, and only ever opaque
   while the plate is hovered -- so the sheet at rest is still eleven
   under-developed proofs rather than eleven bright rectangles, and a site
   that refuses or stalls shows its still instead of a blank.
   pointer-events:none is load-bearing: the whole plate is one link, and a
   frame that took the click would swallow it. */
.frame .lv{position:absolute;top:0;left:0;z-index:1;opacity:0;
  transform-origin:top left;pointer-events:none;background:transparent;
  transition:opacity .55s ease}
.plate:hover .frame .lv.on,.plate:focus-visible .frame .lv.on{opacity:1}
.frame .lv iframe{border:0;display:block;background:transparent}

/* a flat wash in the page's own shadow, so the dimming is coloured rather
   than merely grey -- same colour the film sits under on the landing */
.frame::after{
  content:"";position:absolute;inset:0;pointer-events:none;z-index:1;
  background:rgba(5,11,20,.5);transition:opacity .5s;
}
.plate:hover .frame::after,.plate:focus-visible .frame::after{opacity:0}
.frame i,.frame .over{z-index:2}
.frame i{position:absolute;width:16px;height:16px;pointer-events:none;transition:width .35s,height .35s}
.frame i::before,.frame i::after{content:"";position:absolute;background:var(--hair-2);transition:background .35s}
.frame i::before{left:0;top:0;width:100%;height:1px}
.frame i::after{left:0;top:0;width:1px;height:100%}
.frame i:nth-child(1){top:8px;left:8px}
.frame i:nth-child(2){top:8px;right:8px;transform:scaleX(-1)}
.frame i:nth-child(3){bottom:8px;left:8px;transform:scaleY(-1)}
.frame i:nth-child(4){bottom:8px;right:8px;transform:scale(-1)}
.plate:hover .frame i,.plate:focus-visible .frame i{width:30px;height:30px}
.plate:hover .frame i::before,.plate:hover .frame i::after,
.plate:focus-visible .frame i::before,.plate:focus-visible .frame i::after{background:var(--live)}
.frame .over{position:absolute;inset:auto 0 0 0;padding:.9rem .95rem;
  background:rgba(5,11,20,.86);color:#E9E7E1;
  font-family:'Jost',Futura,'Century Gothic',system-ui,sans-serif;font-weight:700;
  text-transform:uppercase;letter-spacing:-.025em;line-height:1;font-size:clamp(14px,1.6vw,20px);
  transform:translateY(101%);transition:transform .42s cubic-bezier(.2,.8,.25,1)}
.plate:hover .frame .over,.plate:focus-visible .frame .over{transform:none}
.pmeta{display:grid;grid-template-columns:2.4rem 1fr;gap:.15rem .7rem;align-items:baseline}
.pmeta .fno{color:var(--dim);font-size:11px;letter-spacing:.12em}
.plate:hover .pmeta .fno{color:var(--live)}
.pmeta .pname{font-family:'Jost',Futura,'Century Gothic',system-ui,sans-serif;font-weight:600;font-size:15px;letter-spacing:-.01em}
.pmeta .pwhat{grid-column:2;color:var(--muted);font-size:12.5px;line-height:1.45}
.pmeta .pdom{grid-column:2;color:var(--dim);font-size:10.5px;letter-spacing:.11em;text-transform:uppercase;margin-top:.25rem}
.plate:hover .pmeta .pdom{color:var(--live)}
@media (prefers-reduced-motion:reduce){
  .frame img{clip-path:none;transition:none}
  .frame .over,.frame i{transition:none}
}
.foot-row{display:flex;justify-content:space-between;gap:1rem;flex-wrap:wrap;
  border-top:1px solid var(--hair);padding-top:1rem;margin-top:clamp(22px,3vw,38px)}
.foot-row a{color:var(--live);text-decoration:none}

/* modules, steps, prices, about, close */
.mods{display:grid;gap:1px;background:var(--hair);border:1px solid var(--hair);margin-top:clamp(18px,2.4vw,28px)}
@media(min-width:720px){.mods{grid-template-columns:repeat(2,1fr)}}
@media(min-width:1080px){.mods{grid-template-columns:repeat(4,1fr)}}
.mod{background:var(--g1);padding:1.3rem 1.25rem 1.5rem;display:flex;flex-direction:column;gap:.65rem}
.mod .k{font-size:11px;letter-spacing:.14em;text-transform:uppercase;color:var(--live)}
.mod p{font-size:13.5px;line-height:1.55;color:var(--muted)}
.steps{border-top:1px solid var(--hair-2);margin-top:clamp(18px,2.4vw,28px)}
.step{display:grid;grid-template-columns:1fr;gap:.3rem 1.4rem;padding:1.1rem 0;border-bottom:1px solid var(--hair)}
@media(min-width:760px){.step{grid-template-columns:2.6rem 14rem 1fr;align-items:baseline}}
.step .k{color:var(--live);font-size:12px;letter-spacing:.1em}
.step p{font-size:13.5px;line-height:1.55;color:var(--muted);max-width:56ch}
.tw{overflow-x:auto;border-top:1px solid var(--hair-2);margin-top:clamp(18px,2.4vw,28px)}
table{border-collapse:collapse;width:100%;min-width:600px}
th,td{text-align:left;padding:.95rem 1.3rem .95rem 0;border-bottom:1px solid var(--hair);vertical-align:baseline}
th{font-size:10.5px;letter-spacing:.15em;text-transform:uppercase;color:var(--muted);font-weight:500}
td.k{font-family:'Jost',Futura,'Century Gothic',system-ui,sans-serif;font-size:16px;font-weight:600;white-space:nowrap}
td.d{font-size:13.5px;color:var(--muted);line-height:1.5}
td.p{font-size:16px;white-space:nowrap;text-align:right;padding-right:0;color:var(--live)}
tbody tr:hover{background:var(--g1)}
.about{background:var(--g1)}
.abg{display:grid;gap:clamp(20px,3vw,44px);grid-template-columns:1fr;margin-top:clamp(18px,2.4vw,28px)}
@media(min-width:900px){.abg{grid-template-columns:1.15fr .85fr;align-items:start}}
.abg p{font-size:14.5px;line-height:1.68;color:var(--muted);max-width:60ch}
.abg p+p{margin-top:.9rem}
.abg p b{color:var(--ink);font-weight:500}
.facts{border-top:1px solid var(--hair-2)}
.facts div{display:flex;justify-content:space-between;gap:1.2rem;padding:.75rem 0;border-bottom:1px solid var(--hair)}
.facts .l{font-size:11px;letter-spacing:.13em;text-transform:uppercase;color:var(--dim)}
.facts .v{font-size:13.5px;text-align:right}
.row2{display:flex;gap:.8rem;flex-wrap:wrap;margin-top:1.6rem}
.btn{display:inline-flex;align-items:center;text-decoration:none;font-size:11.5px;letter-spacing:.14em;
  text-transform:uppercase;font-weight:700;padding:.95rem 1.5rem;background:var(--live);color:var(--on-live)}
.btn.ghost{background:transparent;color:var(--ink);border:1px solid var(--hair-2);font-weight:500}
.btn.ghost:hover{border-color:var(--live);color:var(--live)}
.check{display:flex;flex-wrap:wrap;border:1px solid var(--hair-2);max-width:560px;margin-top:1.4rem}
.check label{flex:1 1 190px;display:flex;flex-direction:column;justify-content:center;padding:.7rem .9rem;gap:.15rem;min-width:0}
.check input{border:0;background:transparent;color:var(--ink);font-family:inherit;font-size:14.5px;width:100%}
.check input::placeholder{color:var(--dim);opacity:1}
.check button{border:0;background:var(--live);color:var(--on-live);cursor:pointer;font-family:inherit;
  font-size:11.5px;font-weight:700;letter-spacing:.14em;text-transform:uppercase;padding:.9rem 1.4rem}
footer{background:var(--g1);border-top:1px solid var(--hair-2)}
.foot-logo{display:block;width:clamp(170px,28vw,300px);height:auto;aspect-ratio:1685/838;
  margin-bottom:clamp(22px,3vw,40px);--lg-word:var(--ink);--lg-mark:var(--live)}
.fg{display:grid;gap:1.5rem 2rem;grid-template-columns:1fr;border-top:1px solid var(--hair);padding-top:1.5rem}
@media(min-width:720px){.fg{grid-template-columns:repeat(4,1fr)}}
.fg h4{margin-bottom:.6rem}
.fg ul{list-style:none;display:flex;flex-direction:column;gap:.35rem;font-size:13.5px}
.fg a{text-decoration:none;color:var(--muted)}
.fg a:hover{color:var(--live)}
.frule{margin-top:2rem;padding-top:1rem;border-top:1px solid var(--hair);display:flex;flex-wrap:wrap;gap:1rem;justify-content:space-between}
