
:root{
  --green:#00FFFF;          /* the new bright brand green */
  --deep:#07203A;           /* near-black green, the thumbnail base */
  --deeper:#04162A;
  --yellow:#FFD02B;         /* brand yellow, from the Descript caption config */
  --cream:#F1F1E6;
  --white:#fff;
  --ink:#04162A;
  --head:'Montserrat',system-ui,sans-serif;
  --body:'Lato',system-ui,sans-serif;
  --pad:clamp(1.25rem,5vw,6rem);
  --max:1440px;
  --arrow:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M13.1 4.3 20.8 12l-7.7 7.7-1.9-1.9 4.5-4.5H3.2v-2.6h12.5l-4.5-4.5z'/%3E%3C/svg%3E");
}
*,*::before,*::after{box-sizing:border-box}
html{scroll-behavior:smooth;-webkit-text-size-adjust:100%}
body{margin:0;background:var(--deep);color:var(--white);font-family:var(--body);overflow-x:hidden;-webkit-font-smoothing:antialiased}
.wrap{max-width:var(--max);margin-inline:auto;padding-inline:var(--pad)}
h1,h2,h3{font-family:var(--head);margin:0;line-height:1;letter-spacing:-.02em}
.hl{color:var(--yellow)}
.section{position:relative;padding:clamp(4rem,9vw,8rem) 0}
/* diagonal split, the device from the reference template */
.slant{clip-path:polygon(0 0,100% 3.5vw,100% 100%,0 calc(100% - 3.5vw))}
/* The top edge here must be the SAME LINE as .slant's bottom edge, and the
   section must be pulled up by the same 3.5vw so the two coincide. It used to
   slope the opposite way with no negative margin, which left a wedge of page
   background — 134px tall at the left edge on a 1920 screen — showing between
   the two sections as a third colour. The extra 2px is a deliberate hairline
   overlap so sub-pixel rounding cannot reopen a seam along the diagonal. */
.slant-t{margin-top:calc(-3.5vw - 2px);clip-path:polygon(0 0,100% 3.5vw,100% 100%,0 100%)}

/* ---------- nav ---------- */
.nav{position:sticky;top:0;z-index:60;background:rgba(7,32,58,.86);backdrop-filter:blur(10px);border-bottom:1px solid rgba(0,255,255,.18)}
/* The nav is sticky, so anything scrolled to lands UNDERNEATH it unless the
   target reserves a nav's worth of clearance. Without this the section label
   is hidden behind the bar every single time. */
section[id],span[id]{scroll-margin-top:6rem}
.nav__in{display:flex;align-items:center;justify-content:space-between;gap:1rem;padding-block:1rem}
.logo{font-family:var(--head);font-weight:900;font-size:1.4rem;letter-spacing:-.03em}
.logo span{color:var(--green)}
.nav__links{display:none;gap:2rem;font-weight:700;font-size:.9rem;text-transform:uppercase;letter-spacing:.08em}
.nav__links a{color:var(--white);text-decoration:none;opacity:.8}
.nav__links a:hover{opacity:1;color:var(--green)}
/* START gets a hand-drawn yellow circle, like someone went over the menu with
   a marker. The ellipse is a single inline SVG data URI — two slightly uneven
   arcs whose tail overshoots the start, which is what sells "drawn by hand";
   a clean <ellipse> just looks like a border. Sits on a pseudo-element so the
   markup stays a plain link, tilted 4 degrees for the same reason, and
   pointer-events:none so the circle never steals the click. Full opacity: the
   .8 the other links run at makes the yellow look dusty. */
.nav__start{position:relative;opacity:1}
.nav__start::after{content:"";position:absolute;inset:-.85em -1.25em;
  background:url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20viewBox%3D%220%200%20140%2056%22%20fill%3D%22none%22%3E%3Cpath%20d%3D%22M69%208C34%205%2010%2015%209%2027c-1%2013%2024%2022%2060%2021%2036-1%2062-10%2062-22C131%2014%20104%205%2063%208c-8%20.6-16%202-22%204%22%20stroke%3D%22%23FFD02B%22%20stroke-width%3D%224.5%22%20stroke-linecap%3D%22round%22/%3E%3C/svg%3E") center/100% 100% no-repeat;
  transform:rotate(-4deg);pointer-events:none}
@media(min-width:900px){.nav__links{display:flex}}

/* ---------- buttons ---------- */
.btn{display:inline-flex;flex-direction:column;align-items:center;gap:.25rem;text-decoration:none;
  padding:1.05rem 2.25rem;background:var(--green);color:var(--ink);
  font-family:var(--head);font-weight:900;text-transform:uppercase;letter-spacing:.03em;
  transform:skewX(-9deg);transition:.18s ease;position:relative}
.btn>*{transform:skewX(9deg)}
.btn__main{font-size:clamp(1.05rem,1.8vw,1.3rem);line-height:1.05}
.btn__sub{font-family:var(--body);font-weight:700;text-transform:none;letter-spacing:0;font-size:.85rem;opacity:.78}
/* Arrow before every button label. It was a pointing-hand emoji, which renders
   yellow and all but vanished against the green. This is a mask filled with
   currentColor rather than a coloured image, so it always matches the label —
   black on the green buttons, and correct automatically if a dark variant is
   ever used. A pseudo-element rather than markup so it applies to all six
   buttons at once, and so the submit button's "Sending…" textContent swap
   cannot wipe it out. */
.btn__main::before{content:"";display:inline-block;width:.78em;height:.78em;
  margin-right:.5em;vertical-align:-.04em;background:currentColor;
  -webkit-mask:var(--arrow) center/contain no-repeat;mask:var(--arrow) center/contain no-repeat}
/* Separation, depth and attention — on every button, at every width.
   RING: brand green measured 1.51:1 against the exhaust flame and 1.08:1
   against the falling invoices behind the hero CTA. A CTA wants 6-8:1. The
   near-black ring scores 7.4:1 and 10.3:1 against those same areas, so the
   button reads as an object rather than as part of whatever is behind it.
   SHADOWS: layered, not single — one blurred shadow reads as cheap; depth
   needs a tight shadow anchoring the button plus softer ambient ones. */
.btn{box-shadow:0 0 0 3px var(--deeper),
  0 2px 3px rgba(2,10,22,.42),0 8px 16px rgba(2,10,22,.5),0 20px 44px rgba(2,10,22,.42)}
.btn:hover,.btn:focus-visible{transform:skewX(-9deg) translateY(-3px);
  box-shadow:0 0 0 3px var(--deeper),
    0 3px 5px rgba(2,10,22,.45),0 12px 24px rgba(2,10,22,.52),0 26px 56px rgba(2,10,22,.45)}
.btn:focus-visible{outline:3px solid var(--yellow);outline-offset:4px}
/* A slow beacon: one ring expanding out of the button and fading. 2.6s, not
   the 150-250ms used for interaction feedback — a long duration reads as a
   calm glow, a short one reads as a notification badge nagging you. A
   pseudo-element so the ring can grow past the button without dragging the
   layered shadows along with it.
   Deliberately NOT gated behind prefers-reduced-motion: Janez has that setting
   on, and the same call was already made for the gear machine. Logged in
   Project Boss as a trade-off, not an oversight. */
.btn::after{content:"";position:absolute;inset:0;pointer-events:none;
  animation:ctaBeacon 2.6s cubic-bezier(.22,.61,.36,1) infinite}
@keyframes ctaBeacon{
  0%   {box-shadow:0 0 0 0 rgba(0,255,255,.5)}
  70%  {box-shadow:0 0 0 20px rgba(0,255,255,0)}
  100% {box-shadow:0 0 0 0 rgba(0,255,255,0)}
}
/* For use ON the bright green band, where a green button is the same colour as
   its background and reads as a shadow rather than a button. Near-black with a
   green ring, so it is unmistakably an object sitting on the green. */
.btn--dark{background:var(--deeper);color:var(--white);
  box-shadow:0 0 0 3px rgba(0,255,255,.55),
    0 2px 3px rgba(2,10,22,.3),0 8px 16px rgba(2,10,22,.35),0 20px 44px rgba(2,10,22,.3)}
.btn--dark:hover,.btn--dark:focus-visible{
  box-shadow:0 0 0 3px rgba(0,255,255,.85),
    0 3px 5px rgba(2,10,22,.35),0 12px 24px rgba(2,10,22,.4),0 26px 56px rgba(2,10,22,.35)}
/* The beacon is green on green here, so give it a dark ripple instead. */
.btn--dark::after{animation-name:ctaBeaconDark}
/* The X-Ray CTA. Deep azure — picked from a 20-option line-up. NOT green:
   every Free Roadmap button is green, and two different offers in one colour
   read as the same button. Azure is the only saturated colour on the page from
   a different temperature family entirely, which is exactly why it stops the
   eye. White text: azure is the one bright fill here that fails with ink. */
.btn--xray{background:#0077FF;color:#fff;
/* Grows to half again its size and back, forever. The keyframes carry the
   skew: .btn's identity transform is skewX(-9deg), and an animation REPLACES
   the transform property rather than composing with it — pulse without the
   skew and the button visibly straightens on the first frame.
   Hover kills the animation so the button holds still under the cursor —
   nobody wants to click a moving target — which also hands the transform back
   to the normal hover lift. */
  animation:xrayPulse 1.8s ease-in-out infinite}
.btn--xray:hover,.btn--xray:focus-visible{animation:none}
@keyframes xrayPulse{
  0%,100%{transform:skewX(-9deg) scale(1)}
  50%    {transform:skewX(-9deg) scale(1.5)}
}
/* On a phone the button is already most of the viewport wide, so half again
   its size pushes past the screen edge and adds sideways scroll. The pulse
   stays, the amplitude drops to 8% -- keyframes cannot be overridden inside a
   media query, so the phone swaps to its own animation. */
@media(max-width:640px){
  .btn--xray{animation-name:xrayPulseSm}
  @keyframes xrayPulseSm{
    0%,100%{transform:skewX(-9deg) scale(1)}
    50%    {transform:skewX(-9deg) scale(1.08)}
  }
}
.btn--xray::after{animation-name:ctaBeaconAzure}
@keyframes ctaBeaconAzure{
  0%   {box-shadow:0 0 0 0 rgba(0,119,255,.55)}
  70%  {box-shadow:0 0 0 20px rgba(0,119,255,0)}
  100% {box-shadow:0 0 0 0 rgba(0,119,255,0)}
}

@keyframes ctaBeaconDark{
  0%   {box-shadow:0 0 0 0 rgba(4,22,42,.55)}
  70%  {box-shadow:0 0 0 20px rgba(4,22,42,0)}
  100% {box-shadow:0 0 0 0 rgba(4,22,42,0)}
}

.hero__machine{position:absolute;inset:0;z-index:0;pointer-events:none;display:flex;align-items:center;justify-content:center}
.hero::after{content:"";position:absolute;inset:0;z-index:0;pointer-events:none;background:linear-gradient(100deg,var(--deep) 8%,rgba(7,32,58,.82) 38%,rgba(7,32,58,.25) 62%,transparent 85%)}
.hero__machine svg{width:118%;max-width:none;height:auto}

/* ---------- hero ---------- */
.hero{position:relative;isolation:isolate;padding:clamp(3rem,7vw,6rem) 0 clamp(5rem,10vw,9rem);
  background:radial-gradient(120% 90% at 78% 28%,rgba(0,255,255,.22),transparent 58%),var(--deep)}
/* The phone needs the rocket BETWEEN the headline and the button, so copy and
   CTA have to be separate grid items there. .hero__text is display:contents on
   small screens, which dissolves it and lets both become grid items in their
   own right; from 980px up it turns back into a real block and holds them in
   one column cell, which is the original markup exactly.
   Do not give the art its own row span on desktop instead — an item spanning
   two auto rows inflates them, which pushed the CTA 89px down the page. */
.hero__grid{position:relative;z-index:1;display:grid;gap:clamp(2.5rem,5vw,4rem);align-items:center;
  grid-template-areas:"copy" "art" "cta"}
.hero__text{display:contents}
.hero__copy{grid-area:copy}
.hero__cta{grid-area:cta}
.hero__art{grid-area:art}
/* Proportional, not fixed. The columns used to be `52rem 1fr`, so narrowing the
   window took every pixel off the image and none off the headline — the rocket
   collapsed to a stamp around 1100px while the copy did not move. 2.36fr:1fr is
   the same 832:352 split the fixed version produced at full width, so the wide
   view is unchanged, but now both sides give ground together. Breakpoints are
   for the structural switch to one column; sizing is fluid. */
@media(min-width:980px){.hero__grid{grid-template-columns:minmax(0,2.36fr) minmax(0,1fr);
    grid-template-areas:"text art"}
  .hero__text{display:block;grid-area:text}}
/* The rocket sits on top of the gear machine with no plate behind it — the png
   is already cut out, so anything drawn under it would show as a box. */
.hero__art{display:flex;justify-content:center;align-items:center}
/* --art-h is the one height every cut-out illustration on the page is sized
   by, so the hero rocket and the Chief-Everything-Officer atlas always match.
   It is redefined for the stacked and small layouts at the end of the sheet. */
:root{--art-h:min(80vh,52rem)}
.hero__art img{display:block;width:auto;max-width:100%;height:auto;max-height:var(--art-h)}
/* The headline column stays a full 52rem, which leaves the art track narrow.
   On wide screens let the art bleed into the empty page margin instead of
   taking width off the headline — shrinking the column rewraps h1 to 5 lines.
   Bounded so the bleed is always smaller than the margin: no sideways scroll. */
@media(min-width:1400px){.hero__art{margin-right:-2rem}}
@media(min-width:1600px){.hero__art{margin-right:-4rem}}
@media(min-width:1800px){.hero__art{margin-right:-8rem}}
.eyebrow{font-weight:900;font-size:.82rem;letter-spacing:.19em;text-transform:uppercase;color:var(--green);margin:0 0 1.1rem}
.hero h1{font-size:clamp(2.6rem,6.4vw,5.8rem);font-weight:900;text-wrap:balance;margin-bottom:1.4rem}
/* In the two-column layout the headline is sized against its OWN column, not
   the viewport, so it shrinks in step with the column as the window narrows.
   11.15cqw of the 832px column is 92.8px — identical to the old 5.8rem cap at
   full width. Only inside the media query: once stacked, the copy is full-width
   and a column-relative size would be far too large. */
.hero__copy{container-type:inline-size}
@media(min-width:980px){.hero h1{font-size:clamp(2.6rem,11.15cqw,5.8rem)}}
.hero p.lede{font-size:clamp(1.05rem,1.6vw,1.35rem);line-height:1.55;opacity:.9;max-width:54ch;margin:0 0 2.2rem}
/* The hero CTA runs ~30% larger than the shared .btn. Scoped to .hero so the
   header nav button and the popup's submit button keep their original size. */
.hero .btn{gap:.33rem;padding:1.37rem 2.93rem}
.hero .btn__main{font-size:clamp(1.37rem,2.34vw,1.69rem)}
.hero .btn__sub{font-size:1.1rem}
/* Social proof under the CTA: the cream pill of real client faces, lifted from
   nobsbusinesscoach.com with its baked-in green knocked out. Capped rather than
   full-width — at the copy column's full 52rem the faces get bigger than the
   headline's supporting role warrants. */
.proof{margin-top:2rem}
.proof img{display:block;width:100%;max-width:32rem;height:auto}

/* image slot */
.shot{position:relative;aspect-ratio:4/5;border:2px solid rgba(0,255,255,.45);background:
  repeating-linear-gradient(-45deg,rgba(0,255,255,.05) 0 12px,transparent 12px 24px),rgba(255,255,255,.03);
  display:grid;place-items:center;padding:1.5rem;text-align:center}
.shot::after{content:'';position:absolute;inset:-2px;border:2px solid var(--green);opacity:.25;transform:translate(12px,12px);pointer-events:none}
.shot__label{font-family:var(--head);font-weight:800;font-size:.72rem;letter-spacing:.14em;text-transform:uppercase;color:var(--green);opacity:.95}
.shot__note{font-size:.82rem;opacity:.62;margin-top:.6rem;line-height:1.45;max-width:30ch}

/* The assembly cube that used to sit here has been replaced by the GONE
   FISHING desk image. Its stage CSS, its loader and both JS files (the cube and
   its copy of three.js, 636 kB between them) are gone with it — all recoverable
   from git if it ever comes back. */

/* ---------- generic section heads ---------- */
.sechead{text-align:center;max-width:52rem;margin:0 auto clamp(2.5rem,5vw,4rem)}
.sechead h2{font-size:clamp(1.9rem,4.2vw,3.4rem);font-weight:900;text-wrap:balance;margin-bottom:1rem}
.sechead p{font-size:1.05rem;line-height:1.55;opacity:.82;margin:0}

/* ---------- bright band ---------- */
/* margin-BOTTOM only. This was margin-block, which set a -2px top margin that
   overrode .slant-t's pull-up and reopened the wedge. */
.band{background:var(--green);color:var(--ink);margin-bottom:-2px}
.band h2,.band h3{color:var(--ink)}
.band .sechead p{opacity:.78}

/* The AI-Powered vs Old Way comparison boxes were removed with the solution
   section rebuild; their .versus / .col styles went with them. The bullets
   survived for a while as a .wins list, which has now gone too — Janez cut the
   solution copy back to two paragraphs. Old markup is in git.
   .tick and .cross STAY — the Hustler vs Architect section still uses them. */
.tick,.cross{flex:none;width:1.4rem;height:1.4rem;display:grid;place-items:center;font-weight:900;font-size:.85rem;margin-top:.1rem}
.tick{background:var(--green);color:var(--ink)}
.cross{background:rgba(255,255,255,.14);color:rgba(255,255,255,.6)}

/* ---------- ladder ---------- */
/* ---------- Chief Everything Officer ----------
   Reads as the hero continuing rather than a new flat panel: it opens on the
   same --deep the hero ends on and darkens to --deeper, so there is no seam
   where one stops and the other starts. The green wash at the top carries the
   hero's glow down into it.
   Alternating background colour between sections is what gives a long page its
   rhythm; a gradient is worth using here — where it joins two sections — and
   not on the bright green band below, which is high-contrast by design. */
.ceo{position:relative;background:
  radial-gradient(120% 70% at 50% 0%,rgba(0,255,255,.13),transparent 62%),
  linear-gradient(180deg,var(--deep) 0%,var(--deeper) 72%)}
/* Faint engineering grid, echoing the hero's machine without competing with the
   illustration. Masked so it fades out before the section ends, which is what
   makes the darkening read as depth rather than as a flat second colour. */
.ceo::before{content:"";position:absolute;inset:0;pointer-events:none;
  background-image:
    repeating-linear-gradient(0deg,rgba(0,255,255,.05) 0 1px,transparent 1px 92px),
    repeating-linear-gradient(90deg,rgba(0,255,255,.05) 0 1px,transparent 1px 92px);
  -webkit-mask-image:linear-gradient(180deg,#000,transparent 76%);
          mask-image:linear-gradient(180deg,#000,transparent 76%)}
/* ::before is positioned, so without this the grid would paint over the copy. */
.ceo>.wrap{position:relative;z-index:1}

/* Art left, copy right on desktop — the mirror of the hero, which is the
   conventional alternating rhythm for stacked sections. The markup keeps the
   copy first so the stacked order is heading, paragraph, then image; grid
   areas do the swap, not source order. */
/* Label, headline and body stay together in one column. A full-width header
   spanning both columns was tried and reverted: it bought the headline two
   lines but detached it from the copy it belongs to, and it ran across the
   space the illustration occupies. Line count is not worth that. */
.ceo__grid{display:grid;gap:clamp(2rem,5vw,4rem);align-items:center;
  grid-template-areas:"head" "art" "body"}
/* STACKED ORDER IS HEADLINE, IMAGE, COPY — Janez's mobile order, matching the
   hero. The copy block dissolves (display:contents) so its two wrappers can
   take separate grid rows with the art between them; on desktop it becomes a
   normal single column again. The wrappers re-state .sechead's centring
   because display:contents throws the .sechead box away — inheritable
   text-align survives, but max-width and margin:auto do not. */
.ceo__copy{display:contents}
.ceo__head{grid-area:head}
.ceo__body{grid-area:body}
.ceo__head,.ceo__body{text-align:center;max-width:52rem;margin-inline:auto;width:100%}
/* .sechead carries a bottom margin for the centred layout; in a grid the gap
   already does that job, so it would double up. */
.ceo__copy{grid-area:copy;margin-bottom:0}
/* .sechead p has margin:0, which would run the two paragraphs together. */
.ceo__copy p+p{margin-top:1rem}
.ceo__cta{margin-top:1.9rem}
/* Section label — THE PROBLEM / THE SOLUTION.
   Janez asked for it BIGGER than the headline beneath it. Taken at face value
   that gives you two competing shouts and the headline stops being the
   headline, so it is bigger AND low-contrast: it reads as a printed marker
   behind the headline rather than as a second one. currentColor means it works
   on the dark section and the bright green band without a second rule. */
/* .sechead p already sets font-size and opacity, and it is one class more
   specific than a bare .kicker — so this has to be .sechead .kicker or the
   label silently renders as body copy. */
/* Half the size it was, and kept to a single line — at the old scale it
   competed with the headline instead of labelling it. */
.kicker{font-family:var(--head);font-weight:900;text-transform:uppercase;
  font-size:clamp(1.3rem,3.2vw,2.7rem);line-height:1;letter-spacing:-.02em;white-space:nowrap;
  color:currentColor;opacity:.28;margin:0 0 .55em}
/* Repeated at this specificity on purpose. .sechead p sets its own font-size
   and opacity and beats a bare .kicker, so inside a section head the label
   would silently render as body copy without this. Only the two properties
   that actually clash need repeating. */
.sechead p.kicker{font-size:clamp(1.3rem,3.2vw,2.7rem);opacity:.28}
/* The caps-and-yellow emphasis. box-decoration-break keeps the block intact
   when the phrase wraps across two lines. */
/* Painted as a sized background rather than a plain background colour. A plain
   one fills the whole inline box, which is TALLER than the line box — so on a
   headline that wraps, the yellow blocks on consecutive lines overlap by a few
   pixels and look like one solid slab. Sizing the gradient to 1.02em leaves a
   clean gap between them without needing huge leading. */
.mark{color:var(--ink);padding:0 .24em;
  background-image:linear-gradient(var(--yellow),var(--yellow));
  background-repeat:no-repeat;background-size:100% 1.02em;background-position:0 .13em;
  -webkit-box-decoration-break:clone;box-decoration-break:clone}
/* h1,h2,h3 run at line-height 1, which is far too tight once a headline is
   carrying highlight blocks. Size stays at the .sechead default — enlarging it
   inside a column just adds lines. 1.24 was too airy next to the hero, which
   effectively runs at 1; 1.1 leaves just enough room that the yellow blocks on
   consecutive lines sit apart without the headline looking double-spaced. */
.ceo__copy h2{line-height:1.1;
/* MUST be wrap — the plain greedy default. Neither of the other two values
   fills the line, and both were tried here:
     balance  evens out line lengths on purpose. Wrong by definition.
     pretty   is not "balance-lite". Chrome runs it as a paragraph-level
              optimiser that reduces raggedness, so it ALSO breaks early and
              leaves a hole at the right — which is what Janez spotted: "You're
              Still" and "The "Chief" both stopped with room for another word,
              turning a 3-line headline into 4.
   Only wrap fills each line to the edge before breaking. Set it explicitly:
   .sechead h2 sets balance, so leaving this out inherits the wrong value. */
  text-wrap:wrap}
/* Trademark mark: small, raised, and with the line-height zeroed so it cannot
   push the line it sits on. */
.tm{font-size:.5em;vertical-align:super;line-height:0;margin-left:.06em;font-weight:800}
/* The methodology name, wherever it appears in body copy. */
.mark--name{font-family:var(--head);font-weight:900;text-transform:uppercase;
  letter-spacing:.01em;color:var(--ink)}
/* Mirror of the problem section: copy left, cube right.
   Doubled-up class on purpose — a bare .ceo__grid--flip ties with .ceo__grid
   on specificity and loses on source order, so the flip silently did nothing. */
@media(min-width:980px){
  /* Art gets the wider share here, not the copy. The cube is square, so column
     width is the only thing that sets how big it can be. */
  .ceo__grid.ceo__grid--flip{grid-template-columns:minmax(0,1fr) minmax(0,1.15fr);
    grid-template-areas:"copy art"}
}
.ceoart{grid-area:art;display:flex;justify-content:center}
.ceoart img{display:block;width:auto;max-width:min(100%,90vw);height:auto;max-height:var(--art-h)}
@media(min-width:980px){
  .ceo__grid{grid-template-columns:minmax(0,1.15fr) minmax(0,1fr);
    grid-template-areas:"art copy"}
  .ceo__copy{display:block;grid-area:copy;text-align:left;max-width:none;margin:0}
  .ceo__head,.ceo__body{text-align:left;max-width:none;margin-inline:0}
  /* The grid gap used to separate headline from copy when they were separate
     rows; inside one column that job needs a real margin again. */
  .ceo__body{margin-top:1rem}
}

/* ---------- archetypes ---------- */
.arch{display:grid;gap:1.25rem}
@media(min-width:820px){.arch{grid-template-columns:1fr 1fr}}
.card{padding:clamp(1.5rem,3vw,2.4rem);background:var(--deep);color:var(--white);border-top:6px solid var(--green)}
.card--muted{border-top-color:rgba(255,255,255,.25);opacity:.92}
.card h3{font-size:1.35rem;font-weight:900;text-transform:uppercase;margin-bottom:1.1rem}
.card ul{list-style:none;margin:0;padding:0;display:grid;gap:.7rem;font-size:1rem;line-height:1.4}
.card li{display:flex;gap:.7rem}

/* ---------- proof ---------- */
.stats{display:grid;gap:1.25rem;text-align:center}
@media(min-width:700px){.stats{grid-template-columns:repeat(3,1fr)}}
.stat{padding:2rem 1rem;border:2px solid rgba(0,255,255,.3);background:rgba(0,255,255,.05)}
.stat b{display:block;font-family:var(--head);font-weight:900;font-size:clamp(2.4rem,5vw,3.6rem);color:var(--yellow);line-height:1}
.stat span{font-size:.9rem;text-transform:uppercase;letter-spacing:.1em;opacity:.8;font-weight:700}

/* ---------- testimonial coverflow ----------
   Cards are self-hosted posters, so the page loads no third-party video code
   at all. Voomly's player is fetched only when someone actually clicks play,
   and mounted into the lightbox. Deliberately no autoplay: the guidance is
   that testimonial carousels read better when each one stays put until the
   visitor moves it, and it sidesteps the WCAG rule about auto-moving content. */
/* The cards are absolutely positioned from the centre and spread outwards, so
   the outer ones run past the text column. This wrapper takes the section out
   to the full wrap width and clips there — which both stops them adding 69px
   of horizontal scroll (body's overflow-x:hidden is not reliable on iOS) and
   gives the side cards the run-off-the-edge look. The clip is a separate
   element from .cf on purpose: overflow and perspective on the same box is
   where 3D rendering gets flaky. */
.cf__clip{overflow:hidden;margin-inline:calc(var(--pad) * -1)}
/* Geometry and timing below are lifted verbatim from the Option A mockup —
   perspective, card width, the .55s cubic-bezier, the border and active
   shadow. Do not "tidy" these numbers; the motion was signed off as-is. */
.cf{position:relative;height:clamp(340px,46vw,540px);perspective:1400px}
.cf:focus-visible{outline:3px solid var(--yellow);outline-offset:6px}
.cf__stage{position:absolute;inset:0;transform-style:preserve-3d}
/* Flat and stacked until the script fans them out. The players measure
   themselves on mount, and a card rotated in 3D reports its PROJECTED width —
   far narrower than its real one — so a player that mounts while its card is
   already turned lays itself out tiny and stays that way. Mounting them square
   on is the whole fix. */
.cf{transition:opacity .45s ease}
.cf__card{position:absolute;top:50%;left:50%;margin:0;width:clamp(190px,22vw,280px);aspect-ratio:4/5;
  transform:translate(-50%,-50%);
  transform-origin:50% 50%;transition:transform .55s cubic-bezier(.22,.61,.36,1),opacity .55s,filter .55s;
  background:var(--deeper);border:2px solid rgba(0,255,255,.25);overflow:hidden;
  display:grid;place-items:center;will-change:transform}
/* Voomly's own player fills the card — its thumbnail, its blue play button,
   its controls. No poster and no play button of ours: the video plays right
   there in the carousel rather than opening anything. */
.cf__card .voomly-embed{width:100%}
.cf__card--active{border-color:var(--green);box-shadow:0 0 0 3px var(--deeper),0 30px 70px rgba(0,0,0,.6)}
/* Only the card in front is interactive. Without this, a click meant for a
   card at the side would hit the player rotated away behind it and start a
   video nobody can see — and the side players would swallow drags. */
.cf__card:not(.cf__card--active) .voomly-embed{pointer-events:none}
.cf__ctrls{display:flex;gap:.6rem;justify-content:center;align-items:center;margin-top:clamp(1.25rem,3vw,2rem)}
.cf__ctrl{width:54px;height:54px;display:grid;place-items:center;cursor:pointer;color:#fff;
  background:rgba(255,255,255,.06);border:2px solid rgba(0,255,255,.35);
  font-family:var(--head);font-weight:900;font-size:1.2rem;transition:.18s ease}
.cf__ctrl:hover{background:var(--green);color:var(--ink);border-color:var(--green)}
.cf__ctrl:focus-visible{outline:3px solid var(--yellow);outline-offset:3px}
.cf__dots{display:flex;gap:.45rem;margin:0 .7rem}
.cf__dot{width:9px;height:9px;padding:0;border:0;cursor:pointer;background:rgba(255,255,255,.25);transition:.18s ease}
.cf__dot[aria-current="true"]{background:var(--green);transform:scale(1.35)}
@media(max-width:640px){
  .cf{height:clamp(330px,88vw,430px)}
  .cf__card{width:clamp(180px,52vw,240px)}
}

/* ---------- about ---------- */
/* Stacked: headline, photo, copy — the same order as every other section —
   and centred. The copy wrapper dissolves so its head and body take separate
   grid rows with the photo between them; desktop puts the column back. */
.about{display:grid;gap:clamp(2rem,5vw,4rem);align-items:center;
  grid-template-areas:"head" "art" "body"}
.about__copy{display:contents}
.about__head{grid-area:head;text-align:center}
.about__body{grid-area:body;text-align:center}
.about .frame{grid-area:art}
@media(min-width:980px){
  .about{grid-template-columns:.85fr 1.15fr;grid-template-areas:"copy art"}
  .about__copy{display:block;grid-area:copy}
  .about__head,.about__body{text-align:left}
}
.about p{font-size:1.08rem;line-height:1.6;opacity:.88}
.about__body p+p{margin-top:1rem}
/* Photo frame. Borrows the offset green outline from .shot further up so it is
   the same device the page already uses, rather than a second frame style.
   The outline is a pseudo-element so it can sit OUTSIDE the picture without a
   wrapper and without eating into it. */
.frame{position:relative;margin:0}
.frame img{display:block;width:100%;height:auto;border:2px solid rgba(0,255,255,.45)}
.frame::after{content:'';position:absolute;inset:0;border:2px solid var(--green);
  opacity:.25;transform:translate(14px,14px);pointer-events:none}
/* Stacked, the offset frame would push against the section edge, and the photo
   comes after the copy in source order — which is the right reading order but
   puts a big image between the text and its button. Above the fold of the
   column layout neither applies. */
@media(max-width:979px){.frame::after{display:none}}

/* ---------- final cta ---------- */
.final{text-align:center;background:radial-gradient(90% 120% at 50% 0%,rgba(0,255,255,.2),transparent 60%),var(--deeper)}
.final h2{font-size:clamp(2.1rem,5.2vw,4rem);font-weight:900;margin-bottom:1.2rem;text-wrap:balance}
/* The lead magnet itself, shown above the button so the offer is a THING
   before it is a promise. Capped at 560px because that is the widest it is
   ever drawn — the file is 1139px, which is exactly 2x that for retina and
   not a pixel more. */
.lmshot{display:block;width:100%;max-width:560px;height:auto;margin:0 auto 2.2rem}

/* ---------- footer ---------- */
footer{background:var(--deeper);padding:3rem 0 2rem;font-size:.88rem}
.foot{display:flex;flex-wrap:wrap;gap:1.5rem 3rem;justify-content:space-between;align-items:center;opacity:.6}
.foot a{color:var(--white);text-decoration:none;margin-right:1.25rem}
.foot a:hover{color:var(--green)}
@media(prefers-reduced-motion:reduce){*{transition:none!important}
  /* The carousel's glide is the whole point of the pattern Janez signed off —
     with the blanket rule above it snaps between cards instead. He has this OS
     setting turned ON, so the rule would have taken the smooth movement away
     on the exact machine it was approved on. Same call the gear machine
     already made: this site does not honour reduced-motion for its signature
     animation. Logged in Project Boss. */
  .cf__card{transition:transform .55s cubic-bezier(.22,.61,.36,1),opacity .55s,filter .55s!important}}

/* ---------- opt-in popup ---------- */
/* WHY THE POPUP TEXT WAS BLACK ON DARK GREEN. Not a missing colour on our
   side — <dialog> is one of the few elements the browser gives its OWN colour
   (CanvasText, i.e. black), and that beats the white inherited from body. Only
   the bits with an explicit colour survived: .hl is yellow, the field labels
   are green, the inputs are #fff. Everything else went black on near-black.
   Setting colour on the dialog fixes the whole subtree at once. */
dialog#optinModal{border:0;padding:0;background:transparent;max-width:min(92vw,560px);color:var(--white)}
dialog#optinModal::backdrop{background:rgba(3,16,32,.84);backdrop-filter:blur(6px)}
.om{background:var(--deep);border:2px solid var(--green);padding:clamp(1.6rem,4vw,2.3rem);position:relative;box-shadow:0 30px 90px rgba(0,0,0,.65)}
.om h3{font-family:var(--head);font-size:clamp(1.4rem,3.4vw,1.85rem);font-weight:900;line-height:1.1;margin:0 0 1.6rem;text-wrap:balance;text-align:center}
/* The lead magnet replaces the sub-paragraph — showing it beats describing it.
   Never drawn wider than ~466px here (560 dialog less its padding), so the
   file is 900px: 2x for retina, and a separate smaller file from the one in
   the page so the popup is not made to carry the big one's bytes. */
.om__shot{display:block;width:100%;height:auto;margin:0 0 1.3rem}
.of{display:block;margin-bottom:.9rem}
.of span{display:block;font-size:.7rem;font-weight:900;letter-spacing:.14em;text-transform:uppercase;color:var(--green);margin-bottom:.35rem}
.of input{width:100%;padding:.85rem .95rem;background:rgba(255,255,255,.06);border:2px solid rgba(255,255,255,.15);color:#fff;font-family:var(--body);font-size:1rem}
.of input:focus{outline:0;border-color:var(--green);background:rgba(0,255,255,.07)}
.om button[type=submit]{width:100%;margin-top:.4rem}
.ox{position:absolute;top:.5rem;right:.7rem;background:0;border:0;color:#fff;opacity:.5;font-size:1.6rem;cursor:pointer;line-height:1}
.ox:hover{opacity:1;color:var(--green)}
/* Cream rather than white-at-45%: on the near-black panel a dimmed white goes
   grey and dead, where a warm off-white stays legible while still sitting
   behind the button in the hierarchy. */
.ofine{font-size:.76rem;color:var(--cream);opacity:.72;margin:.9rem 0 0;text-align:center}
.oerr{color:#ff8f7a;font-size:.86rem;margin:.5rem 0 0;min-height:1.1em}
.ohp{position:absolute;left:-9999px;width:1px;height:1px;opacity:0}

/* ---------- stacked hero ----------
   These two blocks live at the very END of the stylesheet on purpose. The hero
   rules above them have the same specificity, so anywhere earlier and they win:
   placing them next to .hero__art silently lost the h1 font-size while keeping
   its line-height, which is a confusing half-applied result.

   They are split by WHY, not by size. This first block is everything that is
   true because the layout has STACKED — it therefore starts at the same 979px
   the columns collapse at. Getting these two thresholds out of step is exactly
   what left 641–979px stacked but still left-aligned with the button stranded
   below the image. If a rule answers "the art is now above the copy", it
   belongs here; if it answers "the screen is small", it belongs below. */
@media(max-width:979px){
  :root{--art-h:56vh}
  .hero{--hero-gap:clamp(2.5rem,5vw,4rem)}
  .hero__grid{row-gap:var(--hero-gap)}
  .hero__art img{max-height:var(--art-h)}

  /* Centred because the rocket is no longer beside the copy but above it, and
     centred copy is the convention once the visual sits over rather than next
     to the text. The two-column layout stays left-aligned. */
  .hero__copy{text-align:center}
  .proof img{margin-inline:auto}

  /* The CTA rides up over the bottom 24% of the illustration. Measured, not
     guessed: the rocket body and figure end at 64% of the image height and the
     flames at 84%, so a 24% overlap covers every invoice, the keyboard and the
     lower flames while leaving the flame roots reading as thrust. The negative
     margin has to absorb the grid row-gap as well as the overlap itself. */
  .hero__cta{display:flex;flex-direction:column;align-items:center;
    position:relative;z-index:2;margin-top:calc(-0.24 * var(--art-h) - var(--hero-gap))}

}

/* ---------- small screens ----------
   Everything here exists to buy vertical space so the eyebrow, headline,
   rocket and button all clear the phone fold: a half-height logo with no nav
   button, smaller type, and the lede paragraph dropped (the same argument is
   made again in the sections further down the page). Nothing here is about
   the layout having stacked — that is the block above. */
@media(max-width:640px){
  .nav__in{padding-block:.5rem}
  .logo{font-size:.92rem}
  .nav .btn{display:none}
  :root{--art-h:min(46vh,28rem)}
  .hero{padding-top:2rem;padding-bottom:2.5rem;--hero-gap:1.5rem}
  /* The gears read as noise behind a cut-out illustration at this size, and
     they cannot be anchored to the art without hard-coding pixel offsets. */
  .hero__machine{display:none}
  .eyebrow{font-size:.66rem;letter-spacing:.12em;margin-bottom:1.1rem}
  .hero h1{font-size:2.2rem;line-height:1.06;margin-bottom:0}
  .hero p.lede{display:none}
  .hero__art img{max-width:72vw}
  .proof{margin-top:1.2rem}
  .hero .btn{padding:.85rem 1.8rem}
  .hero .btn__main{font-size:1.02rem}
  .hero .btn__sub{display:none}
  /* No CTA in the PROBLEM section on phones — it is already a full screen
     there and the hero CTA is one scroll away. Scoped to .ceo on purpose: the
     solution section reuses .ceo__cta and its button should stay, since that
     is the point of the section. */
  .ceo .ceo__cta{display:none}
}

/* ---------- Business X-Ray teaser (homepage) ----------
   Three facts in a row: length, price, cap. Deliberately the same shape as the
   facts strip on /business-xray so the page and the section read as one offer
   rather than two. */
/* Inherits the body --deep on purpose. The green band sits above and the
   --deeper testimonials below; giving this --deeper too would merge it with
   the testimonials into one flat dark slab. */
.xray{background:var(--deep)}
/* Down to TWO cells (the 5-a-week box was cut), so the columns must be two as
   well — a repeat(3) grid with two children leaves an empty third track showing
   the border colour as a dead cell. */
.xray__row{display:grid;gap:1px;background:none;border:2px dashed rgba(0,255,255,.5);
  grid-template-columns:1fr;max-width:34rem;margin:2rem auto 0}
@media(min-width:560px){.xray__row{grid-template-columns:repeat(2,1fr)}}
/* The session photo, centred under the headline like the roadmap image in the
   final section — same 560px cap, so the two read as one device. */
/* Tight above, and half the old gap below. Most of what read as "space above
   the image" was 156px of flat green baked INSIDE the file by the render's
   framing margins — cropped out now — so these margins are the real spacing.
   The section head's default bottom margin is far too generous once the image
   is the very next thing. */
.xray .sechead{margin-bottom:clamp(.7rem,1.2vw,1rem)}
.xrayshot{display:block;width:100%;max-width:560px;height:auto;margin:0 auto clamp(1rem,2vw,1.4rem)}
.xray__copy{max-width:46rem;margin:0 auto;text-align:center;font-size:1.06rem;line-height:1.6;opacity:.87}
.xray__copy p+p{margin-top:1rem}
.xray__fact{background:var(--deeper);padding:1.3rem 1rem;text-align:center}
.xray__fact b{display:block;font-family:var(--head);font-weight:900;font-size:1.6rem;color:var(--green);line-height:1}
.xray__fact span{display:block;font-size:.85rem;opacity:.75;margin-top:.4rem}

/* ---------- THE VIDEO SECTION ----------
   The card is pulled up out of its own section by --bridge so it overlaps the
   blue band above: top half on blue, bottom half on dark. Three things make
   that work rather than look like a mistake:
     1. the Solution band grows its bottom padding by the SAME --bridge, so the
        desk illustration never collides with the video (Janez's note: "this is
        too high, it's almost touching the table");
     2. the card is LIT — see .vidstage::before — and carries layered shadows,
        which is what sells "floating above two sections" rather than "clipped
        by one". A flat rectangle on a seam just looks like a mistake;
     3. --bridge is a clamp, so on a phone the overlap shrinks and the card
        stops trying to span a seam only a few hundred px wide.
   z-index is explicit: .band and .slant-t both create stacking contexts, and
   without it the card can end up UNDER the blue instead of over it. */
/* Bigger than it looks like it needs to be, on purpose. rotateX(4deg) tips the
   frame's top edge away from the viewer and perspective foreshortens it, so the
   frame's VISUAL top lands roughly 50px below its layout top — at the old
   value the card sat entirely inside the dark section and the bridge the whole
   idea depends on simply was not visible. */
/* The film's own height, derived rather than guessed: 16:9 of the stage width
   plus the black border above and below it. Everything about the seam is
   measured from this, so the geometry holds at every viewport instead of only
   at the width it was eyeballed on. */
:root{
  --vidw:min(960px,100vw - (2 * var(--pad)));
  --vidh:calc(var(--vidw) * 0.5625 + 52px);
  /* How much of the section's foot is dark. Two thirds of the film plus the
     padding under it — which puts the colour change one third of the way down
     the film, where Janez asked for it: crossing the picture, nearer the top
     than the middle. */
  --darkrun:calc((var(--vidh) * 0.67) + clamp(3rem,6vw,5rem));
}
#new{position:relative;padding-bottom:clamp(3rem,6vw,5rem)}
/* The dark ground, drawn INSIDE the blue section along its bottom edge. This
   is the "second section" the film straddles — except it is the same section,
   so the join cannot drift. It is also why the film no longer needs a negative
   margin at all. */
#new::after{content:"";position:absolute;left:0;right:0;bottom:0;z-index:0;
  height:var(--darkrun);background:var(--b3)}
#new > .wrap{position:relative;z-index:2}
.vidhold{margin-top:clamp(2.5rem,6vw,5rem)}
.vidstage{position:relative;z-index:3;max-width:var(--vidw);
  margin:0 auto;perspective:1700px}
/* NO filter on this element. filter forces transform-style:flat on an
   element's children, which would collapse every segment below back onto one
   plane and destroy the curve — the same rule that broke the plate/video
   stacking earlier. The shadow therefore lives on .vidstage::after, which is
   outside the 3D context. */
.vidtilt{position:relative;transform:rotateY(-11deg) rotateX(3deg);transform-style:preserve-3d}
.vidstage::after{content:"";position:absolute;left:6%;right:6%;bottom:-14px;height:44px;
  background:rgba(0,0,0,.5);filter:blur(26px);z-index:-1;pointer-events:none}
.vidcard{display:block;width:100%;padding:0;border:0;cursor:pointer;background:none;
  position:relative;height:var(--vidh);transform-style:preserve-3d}
.vidcard:focus-visible{outline:3px solid var(--yellow);outline-offset:10px}
/* The two segment strips, stacked in the same 3D space. */
.film,.fplate{position:absolute;inset:0;display:flex;transform-style:preserve-3d}
.fplate{transform:translate(26px,26px) translateZ(-40px)}
.fs,.ps{position:relative;flex:0 0 auto;height:100%;
  /* Each slice is exactly one Nth of the film WIDE, plus a bleed that is
     pulled back out again with a negative margin, so the row still totals
     exactly --vidw. The bleed has to beat the worst-case gap: a slice turned
     by ANGLE projects cos(ANGLE) as wide as it lays out, losing about 7% at
     22 degrees — on a 36px slice that is ~2.6px, which a 2px bleed did not
     cover, and the aqua plate showed through as hairlines at the steepest
     slices. 6px clears it with room to spare. Over-bleeding costs nothing now
     that the background is addressed in absolute pixels: the extra is real
     adjacent picture, not a magnified copy. */
  width:calc((var(--vidw) / 26) + 6px);margin-right:-6px;
  transform:translateZ(var(--z)) rotateY(var(--ry))}
/* The slice addresses the poster in ABSOLUTE pixels, and this is the whole
   difference between a curve that looks right and the one that did not.
   The previous attempt closed the gaps with scaleX(1.16). But background-size
   was a percentage OF THE ELEMENT, so scaling the element magnified its
   background too: every slice showed ~16% of its neighbour's picture, blown up
   by 16%. That is exactly what Janez saw — the shirt and arm repeating at the
   joins, and soft, resampled edges.
   Here background-size is the FULL film width in px and the position is a
   negative px offset, so a slice shows precisely its own sixteenth of the
   poster at 1:1 — no magnification, nothing resampled, nothing repeated. The
   only overlap is the 2px bleed above, which is real adjacent picture. */
.fs{background-image:url(img/video-poster.webp);
  background-size:var(--vidw) 100%;background-repeat:no-repeat;
  background-position:calc(-1 * var(--i) * var(--vidw) / 26) center;
  border-top:26px solid #080d15;border-bottom:26px solid #080d15}
.ps{background:var(--btn)}
/* One sprocket hole per segment, sitting IN that segment's own black border —
   so a hole is part of the curved surface and travels with it. */
.fs::before,.fs::after{content:"";position:absolute;left:50%;translate:-50% 0;
  width:64%;max-width:22px;height:13px;border-radius:3px;background:#e8ecf2;
  box-shadow:inset 0 1px 2px rgba(0,0,0,.4)}
.fs::before{top:-19px}
.fs::after{bottom:-19px}
/* The glow has to be its own element: putting a box-shadow on the segments
   would draw eighteen separate glows, one per slice. */
.vidstage::before{content:"";position:absolute;inset:-8% -5%;z-index:-1;pointer-events:none;
  background:radial-gradient(56% 52% at 52% 52%,var(--btnglow),transparent 72%);
  filter:blur(30px)}
/* Pushed well forward so it rides above the deepest part of the curve, and
   turned with the right-hand edge so it sits ON the surface rather than
   floating flat in front of it. */
.vidtag{position:absolute;right:-4px;top:-20px;background:var(--yellow);color:var(--ink);
  font-family:var(--head);font-weight:900;font-size:.68rem;letter-spacing:.18em;
  text-transform:uppercase;padding:.45em .95em;
  transform:translateZ(30px) rotateY(-14deg);
  box-shadow:0 8px 18px rgba(0,0,0,.45)}
/* ---- the play control ----
   left is 53.5%, not 50%: under rotateY(-14deg) the near edge is magnified and
   the far edge compressed, so the frame's OPTICAL centre sits right of its
   geometric centre. At a true 50% the control reads as off to the left.
   The motion is a conic-gradient sweep travelling around the pill's rim. It is
   a rotating BACKGROUND behind an opaque face rather than an animated border,
   because border-image cannot be animated and a spinning pseudo-element at a
   negative z-index would paint above its parent's own background. */
.vidplay{position:absolute;left:53.5%;top:50%;
  transform:translate(-50%,-50%) translateZ(60px);
  padding:4px;border-radius:999px;overflow:hidden;line-height:1;
  box-shadow:0 16px 38px rgba(0,0,0,.5);transition:transform .25s ease}
.vidplay::before{content:"";position:absolute;inset:-60%;
  background:conic-gradient(from 0turn,transparent 0 58%,rgba(255,255,255,.95) 76%,transparent 90%);
  animation:vidSweep 2.6s linear infinite}
@keyframes vidSweep{to{transform:rotate(1turn)}}
.vidplay__face{position:relative;display:flex;align-items:center;gap:.6rem;
  border-radius:999px;background:var(--btn);color:var(--ink);
  padding:.85rem 1.5rem .85rem 1.15rem;
  font-family:var(--head);font-weight:900;font-size:.92rem;letter-spacing:.1em;
  text-transform:uppercase}
.vidplay__face svg{width:19px;height:19px;flex:none}
.vidplay__face i{font-style:normal;font-weight:800;opacity:.62;letter-spacing:.04em}
.vidcard:hover .vidplay,.vidcard:focus-visible .vidplay{transform:translate(-50%,-50%) translateZ(60px) scale(1.06)}
/* The caption sits on the dark ground under the card, small and quiet — the
   card is the whole point of the section, so nothing here competes with it. */
.vidcap{margin:2.6rem auto 0;text-align:center;font-size:.95rem;opacity:.6}
.ocavid{display:block;width:100%;aspect-ratio:16/9;height:auto;background:#000}
/* ---------- THE PLAYER DIALOG ----------
   Flat, deliberately: the film keeps its curve and its turn on the page, and
   the dialog is where the video actually has to be watchable. Same film strip
   so it reads as the same object opening up, but nothing tilted, nothing
   clipped, nothing for the picture to fight. */
.vmodal{border:0;padding:0;background:transparent;max-width:min(1100px,92vw);width:100%;
  color:#fff;overflow:visible}
.vmodal::backdrop{background:rgba(3,14,28,.86);backdrop-filter:blur(6px)}
.vmodal__reel{position:relative;background:#080d15;padding:0 12px;
  box-shadow:0 0 0 3px var(--btn),0 0 80px var(--btnglow),0 40px 90px rgba(0,0,0,.7)}
/* The dialog's sprocket strips. These are their own rules rather than shared
   with the inline film: the inline one is 26 curved segments each carrying a
   single hole, which has no meaning on a flat player. The classes were shared
   at first and the holes silently vanished from the popup the moment the
   inline frame was rebuilt — same markup, styling deleted from under it. */
.vmodal__reel .vidperf{display:flex;height:26px;align-items:center;
  justify-content:space-between;padding:0 2px}
.vmodal__reel .vidperf i{flex:0 0 20px;height:13px;border-radius:3px;background:#e8ecf2;
  box-shadow:inset 0 1px 2px rgba(0,0,0,.4)}
@media(max-width:640px){
  .vmodal__reel .vidperf{height:18px}
  .vmodal__reel .vidperf i{flex-basis:13px;height:9px}
}
.vmodal__screen{position:relative;background:#000;aspect-ratio:16/9}
.vmodal__screen video{position:absolute;inset:0;width:100%;height:100%}
.vmodal__x{position:absolute;top:-46px;right:0;width:38px;height:38px;line-height:1;
  border:0;cursor:pointer;background:var(--btn);color:var(--ink);
  font-size:1.5rem;font-weight:900;font-family:var(--head)}
.vmodal__x:hover{transform:scale(1.08)}
@media(max-width:640px){.vmodal__reel{padding:16px 8px}.vmodal__x{top:-42px}}
@media(max-width:760px){
  /* The turn costs picture width, which a phone cannot spare — and a 14° twist
     on a 340px-wide frame reads as a rendering fault rather than as depth. */
  .vidtilt{transform:none}
  .vidplate{transform:translate(14px,14px)}
  .vidplay{left:50%}
  .vidplay__face{font-size:.78rem;padding:.7rem 1.1rem .7rem .85rem}
  .vidcard{padding:18px 8px}
  .vidperf{height:18px}.vidperf i{flex-basis:13px;height:9px}
}

/* ---------- OCA: the clickable layer ----------
   --btn is the one colour on this page that means "press me". --btnglow is the
   same colour at low alpha, used behind the video card. */
:root{--btn:#00FFFF;--btnglow:rgba(0,255,255,.5);--blue:#0072EF}
.btn{background:var(--btn);color:var(--ink)}
/* ---------- the bright bands take the LOGO blue, not the accent ----------
   And their text flips to white, which is a contrast call rather than a taste
   one: #0072EF sits at 0.180 relative luminance, so the near-black ink the
   band inherited scores 4.02:1 against it — under the 4.5:1 floor for body
   text. White scores 4.56:1 and passes. The yellow .mark highlights keep dark
   ink because they sit on yellow, not on the blue. */
.band{background:var(--blue);color:var(--white)}
.band .mark{color:var(--ink)}
/* The beacon ring must be the BUTTON's colour, not the brand's — the base
   stylesheet hard-codes the brand into these keyframes, so it has to be
   restated or the ring pulses in a colour the button no longer is. */
@keyframes ctaBeacon{
  0%   {box-shadow:0 0 0 0 rgba(0,255,255,.5)}
  70%  {box-shadow:0 0 0 20px rgba(0,255,255,0)}
  100% {box-shadow:0 0 0 0 rgba(0,255,255,0)}
}
/* .btn--dark is the variant used ON the bright band, where a button in the
   button colour would vanish into its own background. Its ring follows --btn
   for the same reason the beacon does. */
.btn--dark{background:var(--deeper);color:var(--white);
  box-shadow:0 0 0 3px var(--btn),
    0 2px 3px rgba(2,10,22,.42),0 8px 16px rgba(2,10,22,.5),0 20px 44px rgba(2,10,22,.42)}
.btn--dark:hover,.btn--dark:focus-visible{
  box-shadow:0 0 0 3px var(--btn),
    0 3px 5px rgba(2,10,22,.45),0 12px 24px rgba(2,10,22,.52),0 26px 56px rgba(2,10,22,.45)}
/* The X-Ray CTA keeps Upscalum's exact azure and its white text — azure is the
   one bright fill on either site that fails against dark ink. */
.btn--xray{background:#0077FF;color:#fff}

/* ---------- OCA: the drawn logo replaces the type wordmark ---------- */
.logo{display:flex;align-items:center;line-height:0}
.logo img{display:block;height:46px;width:auto}
.logo--foot img{height:56px}
@media(max-width:640px){.logo img{height:38px}}

/* ---------- the blue scale ---------- */
:root{
  --b1:#1B4E86;  /* lifted navy — top of a dark section */
  --b2:#123C68;  /* mid */
  --b3:#0C2A4B;  /* base dark; the body colour, so slant reveals match it */
  --b4:#071C33;  /* deepest */
}
/* ---- THE SEAM RULE ----
   Every gradient below starts AND ends on --b3, and the body is --b3 too. That
   is not a stylistic choice, it is what makes the diagonal seams work.
   .slant clips a triangle out of each section's top-right and bottom-left
   corners, and what shows through the cut is the BODY. While every dark
   section was one flat colour identical to the body, that reveal was
   invisible. The first version of this gradient ran --b1 → --b3 top to bottom,
   so a section's edges no longer matched the body — and a 48px stripe of body
   colour (3.5vw, exactly the slant's depth) appeared along every seam.
   Pinning both ends of the ramp to the body colour makes the cut reveal the
   same value the section already had there, so the wedge cannot exist. The
   light now peaks in the MIDDLE of each section rather than at its top, which
   reads as a soft spotlight per section and keeps the seams clean.
   Same reason the radial glows are held away from the edges: anything bright
   touching 0% or 100% would reintroduce the mismatch it is there to avoid. */
body{background:var(--b3)}
.section{
  background-color:var(--b3);
  background-image:
    radial-gradient(rgba(255,255,255,.055) 1px,transparent 1px),
    radial-gradient(78% 34% at 50% 44%,rgba(0,255,255,.10),transparent 72%),
    radial-gradient(62% 30% at 86% 34%,rgba(0,114,239,.32),transparent 74%),
    linear-gradient(180deg,var(--b3) 0 6%,var(--b1) 34%,var(--b2) 68%,var(--b3) 96% 100%);
  background-size:28px 28px,auto,auto,auto;
  background-repeat:repeat,no-repeat,no-repeat,no-repeat}
/* The bright band keeps the logo blue as its anchor but stops being flat:
   a lighter blue at the top-left falling to a deeper one bottom-right, so it
   has the same sense of a light source as the dark sections do. */
.band{background-color:var(--blue);
  background-image:
    radial-gradient(rgba(255,255,255,.07) 1px,transparent 1px),
    radial-gradient(75% 60% at 12% 0%,rgba(255,255,255,.22),transparent 66%),
    linear-gradient(158deg,#2E9BFF 0%,var(--blue) 52%,#005CC9 100%);
  background-size:28px 28px,auto,auto;
  background-repeat:repeat,no-repeat,no-repeat}
/* The hero keeps its own gear machine, so it only gets the lift and the glow —
   a dot grid on top of the gears would be two textures fighting. */
.hero{background-color:var(--b3);
  background-image:
    radial-gradient(72% 42% at 78% 40%,rgba(0,114,239,.34),transparent 74%),
    radial-gradient(60% 34% at 10% 72%,rgba(0,255,255,.10),transparent 74%),
    linear-gradient(180deg,var(--b3) 0 5%,var(--b1) 36%,var(--b2) 70%,var(--b3) 96% 100%)}
/* The video section is a continuation of the band above it, not a new slab —
   it starts where the band's gradient ended so the seam reads as one fall of
   light rather than two unrelated colours meeting. */
.vidsec{background-image:
  radial-gradient(rgba(255,255,255,.055) 1px,transparent 1px),
  radial-gradient(66% 40% at 50% 34%,rgba(0,255,255,.14),transparent 72%),
  linear-gradient(180deg,var(--b3) 0 5%,var(--b2) 34%,var(--b3) 96% 100%);
  background-size:28px 28px,auto,auto}
/* NO background on .foot. It looks like a section and is not: .foot is the
   flex ROW of links inside the footer, and it carries opacity:.6. Painting a
   background on it drew a lighter slab the width of the wrap's max-width,
   inset from both page edges — the "random buffer" around the footer. The
   footer's ground comes from the section that contains it, as on Upscalum. */

/* ---------- THE TOP TWO SECTIONS + TESTIMONIALS ----------
   Copied off the four-scheme build, because those three are the ones Janez
   picked out of it. Measured from that render rather than from the CSS I
   thought I wrote — the hero read #072342 and the section under it a flat
   #093B75, and that flatness is the point: the reverted build's #problem ramps
   down to #0C2A4B at both ends, which is what made it merge with its
   neighbours.
   #problem also switches to the slant-t mechanism. Its .slant clip reveals the
   BODY, so with a colour of its own it would show a stripe of body colour
   along the join — the wedge again. slant-t pulls it up over the hero and
   clips its own top edge instead, so the diagonal reveals the HERO. One hard
   line between two different colours, which is the border he asked to match. */
#problem{
  margin-top:calc(-3.5vw - 2px);
  clip-path:polygon(0 0,100% 3.5vw,100% 100%,0 100%);
  background:linear-gradient(176deg,#0B4383 0%,#093B75 55%,#08356A 100%)}
#proof{background:linear-gradient(168deg,#3593FF 0%,#0072EF 52%,#0059BC 100%) !important}
/* Every remaining join moves to the slant-t mechanism too.
   .slant clips BOTH the top-right and the bottom-left, and both cuts reveal
   the BODY. So the moment a section has a colour of its own, its bottom cut
   shows a stripe of body colour before the next section starts — which is the
   wedge under the testimonials. slant-t clips only the top and pulls the
   section up over its predecessor, so the cut reveals the SECTION ABOVE and
   nothing can leak through. Applied to the whole run, the body is never
   visible at any boundary. */
#proof,.xray,#about,.final{
  margin-top:calc(-3.5vw - 2px);
  clip-path:polygon(0 0,100% 3.5vw,100% 100%,0 100%);
  position:relative}
/* About and the closing section must not match, the way Upscalum alternates
   them: measured there, About sits on the deeper ground (#041B0F) and the
   closer on the lighter one (#06251A). Same relationship here — About drops
   back, the closer steps forward — so the page does not end on two identical
   slabs. */
#about{background:linear-gradient(174deg,#0A2440 0%,var(--b4) 62%)}
.final{background:linear-gradient(170deg,#14477C 0%,#0F3A66 55%,#0C2E52 100%)}
.vidcap{display:none}
/* ---------- the Red / Yellow / Green legend ----------
   These three are SEMANTIC, not brand. .score .g was written as
   var(--green) — correct on Upscalum, where the brand colour happens to be
   green, and wrong the moment the token is remapped: on OCA the word "Green"
   came out aqua and on EI it came out orange, which destroys the only thing
   the legend is for. Pinned to literal traffic-light values in both forks so
   no future palette change can break the meaning again. */
.score .r{border-color:#FF5C47 !important} .score .r b{color:#FF8F7A !important}
.score .y{border-color:#FFC400 !important} .score .y b{color:#FFD84D !important}
.score .g{border-color:#22C55E !important} .score .g b{color:#4ADE80 !important}

/* ---------- THE X-RAY PAGE: MIMIC UPSCALUM ----------
   Checked rather than assumed: Upscalum's business-xray page contains ZERO
   linear-gradients of its own. It is a flat --deep body with exactly three
   sections pinned to --deeper, and the diagonals come from .slant / .slant-t.
   That is the whole design.
   The OCA fork shares ONE stylesheet with the homepage, so every gradient,
   texture and re-toned section built for the homepage landed on this page too
   — which is the "too much gradient compared to Upscalum" Janez is seeing. It
   was never a decision about this page; it was spill.
   So the page is scoped out of all of it via a body class and handed back the
   flat treatment, one-for-one with Upscalum, blue where it was green. The one
   deliberate departure he asked for stays: The Solution is bright — but FLAT
   bright, because Upscalum uses no gradient here and he asked for faithful. */
body.xr{background:var(--deep)}
body.xr .section{background-color:transparent;background-image:none;
  margin-top:0;clip-path:none}
/* the two slant shapes put back exactly as Upscalum defines them */
body.xr .section.slant{clip-path:polygon(0 0,100% 3.5vw,100% 100%,0 calc(100% - 3.5vw))}
body.xr .section.slant-t{margin-top:calc(-3.5vw - 2px);
  clip-path:polygon(0 0,100% 3.5vw,100% 100%,0 100%)}
body.xr .band{background:var(--blue);color:var(--white)}
/* The Solution section is NOT bright. Measured on Upscalum: at the equivalent
   scroll position its ground is #04170F — --deeper, one of the dark pair. I
   had made it bright on an earlier instruction and then kept it through the
   "mimic faithfully" pass, which contradicted the instruction. Faithful wins. */
body.xr .xsol{background:var(--deeper)}
/* The hero. Upscalum's .xhero is a 16% brand-colour glow over --deeper, and it
   lands on #041A0F — a lift of THREE points over the flat colour, so the hero
   reads slightly darker than the --deep section beneath it. The palette remap
   turned that glow aqua, and aqua at the same 16% over navy lands on #04475E:
   a fifty-point lift, a visible cyan wash, and — because it brightened the
   hero to roughly the tone of the section under it — the two top sections
   merged into one block. That is the "no sections, just one colour" Janez saw.
   The glow goes back to the brand blue, which reproduces Upscalum's small lift
   instead of overwhelming it. */
body.xr .xhero{background:
  radial-gradient(90% 120% at 50% 0%,rgba(0,114,239,.16),transparent 60%),
  var(--deeper) !important}

.vidhold{margin-top:clamp(2rem,4.5vw,3.5rem)}
#new{padding-bottom:clamp(1.5rem,3vw,2.75rem)}

/* highlight marks: blue fill needs white type, where yellow needed ink */
.mark{background:#0072EF !important;color:#fff !important}
.mark--name{background:none !important;color:#0072EF !important}
.hl{color:#0072EF !important}
/* every Free Roadmap button */
.btn{background:#0072EF !important;color:#fff !important}
.btn__main::before{background:#fff !important}
@keyframes ctaBeacon{
  0%   {box-shadow:0 0 0 0 rgba(0,114,239,.5)}
  70%  {box-shadow:0 0 0 20px rgba(0,114,239,0)}
  100% {box-shadow:0 0 0 0 rgba(0,114,239,0)}
}
/* the dark variant's ring moves off teal onto the same blue */
.btn--dark{background:var(--deeper) !important;color:#fff !important;
  box-shadow:0 0 0 3px #0072EF,0 2px 3px rgba(2,10,22,.42),0 8px 16px rgba(2,10,22,.5),0 20px 44px rgba(2,10,22,.42) !important}
/* Hire Us keeps AQUA, so it matches the 90-min and $250 figures it sits under */
.btn--xray{background:#00FFFF !important;color:var(--ink) !important}
.btn--xray .btn__main::before{background:var(--ink) !important}
/* the circled HIRE US in the nav */
.nav__start{color:#0072EF !important}
.nav__start::after{filter:hue-rotate(190deg) saturate(2.2) brightness(.85)}
/* the film keeps its aqua entirely — control, ring and backing plate */
.vidplay__face{background:var(--btn) !important;color:var(--ink) !important}
/* ---- narrow white outline on the blue type ----
   Blue emphasis on a blue ground has almost no luminance gap to work with, so
   the words were sinking. A hairline white stroke gives every letter its own
   edge without changing the colour. -webkit-text-stroke centres the stroke on
   the glyph outline, so it eats into the fill — hence 1px rather than more,
   which keeps the letterforms intact at these weights. */
.hl,.kicker{-webkit-text-stroke:1px #fff;paint-order:stroke fill}
/* SIMPLE SCALING SYSTEM was blue type on the blue band and vanished. It becomes
   a blue FILL with white letters instead, which is what the highlight marks
   already do elsewhere. */
/* Two classes deep, because the base sheet styles it as .mark.mark--name and a
   single class loses the specificity race even with !important on one side. */
.mark.mark--name,span.mark--name{background:#0072EF !important;color:#fff !important;
  padding:.08em .32em;-webkit-text-stroke:0;border-radius:0}
.mark.mark--name .tm,span.mark--name .tm{color:#fff !important}
.mark{color:#fff !important;-webkit-text-stroke:0}
/* the eyebrow stops being aqua */
.kicker{color:#0072EF !important}
/* nav: white letters, aqua circle */
.nav__start{color:#fff !important;-webkit-text-stroke:0}
.nav__start::after{filter:hue-rotate(150deg) saturate(3) brightness(1.35)}

/* the small-card mask scales the embed; never let it spill the card */
.cf__card{overflow:hidden}

/* ── COLOUR SWAP (Janez 2026-07-30): Roadmap buttons take the AQUA, Hire Us /
   Book buttons take the logo BLUE — the reverse of before. One accent per
   offer, same rule as ever, just traded places. */
.btn{background:#00FFFF !important;color:#04162A !important}
.btn .btn__main::before{background:#04162A !important}
.btn--dark{background:#00FFFF !important;color:#04162A !important;
  box-shadow:0 0 0 3px var(--deeper),0 8px 20px rgba(2,10,22,.45) !important}
@keyframes ctaBeacon{
  0%{box-shadow:0 0 0 0 rgba(0,255,255,.5)}
  70%{box-shadow:0 0 0 20px rgba(0,255,255,0)}
  100%{box-shadow:0 0 0 0 rgba(0,255,255,0)}}
.btn--xray{background:#0072EF !important;color:#fff !important}
.btn--xray .btn__main::before{background:#fff !important}
/* on the bright BOOK IT band a blue button vanishes into its own ground —
   dark version there, per Janez */
#buy .btn--xray{background:var(--deeper) !important;color:#fff !important;
  box-shadow:0 0 0 3px rgba(255,255,255,.25),0 8px 20px rgba(2,10,22,.5) !important}
/* the hand-drawn circle around HIRE US follows its button to blue:
   the artwork is brand-yellow (hue ~45), +167 lands on ~212 = the logo blue */
.nav__start::after{filter:hue-rotate(167deg) saturate(3) brightness(1.05) !important}
/* the $250 is a Johnson box, not a filled panel — dashed, no fill, like EI */
.pricebox{border:2px dashed #00FFFF !important;background:none !important}
