/* ==========================================================================
   Flockfactor — site styles
   Ported from "Flockfactor Site v4.dc.html" (Claude Design canvas).
   Inline design-canvas styles are consolidated here; `style-hover` attributes
   became real :hover rules; template loops were expanded into markup.
   ========================================================================== */

:root {
  /* Ink & paper */
  --ink:        #0A0A0B;
  --ink-room:   #0C0C0E;
  --ink-chrome: #1A1A1D;
  --ink-well:   #050505;
  /* Warm, not white. #FCFCFB is a cold near-white and it read as "default page
     background" — the buyer here is a restaurant owner, not a developer, and
     the whole first screen now rests on this. It doubles as light-on-dark text,
     so the ink sections warm with it and the palette stays one family. */
  --paper:      #F6F3EC;
  --cream:      #EDEAE3;
  /* Recessed warm surface — the well a faded "before" capture sits in. */
  --paper-sink: #EBE7DC;

  /* Accent */
  --lime:       #BEF264;
  --lime-ink:   #2E3618;
  --lime-mute:  #3F4A22;
  --red:        #D2382A;

  /* Text on dark */
  --d-1: #EDEAE3;
  --d-2: #B4B0AA;
  --d-3: #A8A8A1;
  --d-4: #A8A5A0;
  --d-5: #8F8B85;
  --d-6: #8A8A84;
  --d-7: #9A9A93;

  /* Text on light */
  --l-1: #0A0A0B;
  --l-2: #5F5F5A;
  --l-3: #6E6E68;

  /* Rules */
  --rule-dark:  #2A2A2C;
  --rule-dark2: #26262A;
  --rule-light: #E1DCD0;
  --rule-bone:  #CFC8B7;

  /* Shadow bases, as channel triples so the alpha varies at the use site.
     Depth on this page still means one thing only — a real, shipped client
     site — but it now happens on two grounds. On ink the shadow is neutral
     black: the plate is an object lit in a dark room. On bone a neutral black
     shadow goes grey and dead, so the hero's plates cast a warm one tinted
     toward the ground, and the fold reads as one light source rather than a
     photo pasted onto paper. */
  --shadow-ink:  0 0 0;
  --shadow-warm: 40 34 22;

  /* The only white in the system, and it is a material rather than a colour:
     the 1px diagonal rule of the hatch a gallery well shows while its embed
     loads. Held as a triple so the alpha stays at the use site, and kept
     neutral because the hatch only ever appears on ink. Nothing else on this
     page is allowed to be white — text on dark takes a legibility step. */
  --hatch-line: 255 255 255;
  --rule-soft:  #55524D;
  --rule-chip:  #3A3A3E;

  /* Type */
  --display: 'Cabinet Grotesk', 'Satoshi', system-ui, sans-serif;
  --sans:    'Switzer', system-ui, sans-serif;
  --ui:      'Satoshi', 'Switzer', system-ui, sans-serif;
  --mono:    'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace;

  /* Rhythm */
  --shell:  1600px;
  /* The fold gets a wider container than the document. 1600 is right for
     reading — 36-44ch measures, a gallery, a price table — but on a 2560
     monitor it left 480px of empty bone either side of a poster whose whole
     job is to look expensive, and capped the plate at 784px. Below a 1600
     viewport the two are identical, so this only ever adds room where room
     exists. */
  --fold-shell: min(2240px, 100%);

  /* The one radius on a rectangle in this system, and it is not a style choice:
     a real browser window has rounded corners, so the plate that depicts one
     gets them too. The radius belongs to the object being depicted, not to the
     design system's cards — see The No Radius Rule, which is otherwise intact.
     Buttons, panels, chips and the paper print all stay square. */
  --plate-radius: clamp(6px, .7vw, 14px);
  --gutter: clamp(20px, 4.2vw, 72px);
  --block:  clamp(72px, 9vw, 140px);
  --ease:   cubic-bezier(.16, 1, .3, 1);
}

/* --- Reset ---------------------------------------------------------------- */

/* NEVER set scroll-behavior:smooth here. Lenis drives smooth scrolling from
   its own rAF loop, and the native smooth-scroll engine eases the same gesture
   at the same time — the two compound and the page crawls. Anchor links are
   routed through Lenis in site.js instead. */
html { -webkit-text-size-adjust: 100%; }

/* overflow-x:clip, never hidden — hidden makes <body> a scroll container and
   the fixed header/pinned gallery can then never engage. */
html, body { height: auto; min-height: 100%; overflow-x: clip; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
  -webkit-font-smoothing: antialiased;
  overflow-x: clip;
}

*, *::before, *::after { box-sizing: border-box; }
h1, h2, h3, p, ul, li, figure, figcaption { margin: 0; padding: 0; }
ul { list-style: none; }
img { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }
svg { display: block; }

::selection { background: var(--lime); color: var(--ink); }
:focus-visible { outline: 2px solid currentColor; outline-offset: 4px; }

@keyframes ff-marquee { from { transform: translateX(0); } to { transform: translateX(-50%); } }

.skip {
  position: fixed; left: 12px; top: -60px; z-index: 100;
  background: var(--ink); color: var(--lime);
  font-family: var(--mono); font-size: 12px; letter-spacing: .12em; text-transform: uppercase;
  padding: 12px 18px; transition: top .2s ease;
}
.skip:focus { top: 12px; }

/* --- Page furniture ------------------------------------------------------- */

.grain {
  position: fixed; inset: 0; z-index: 90;
  pointer-events: none; opacity: .045; mix-blend-mode: multiply;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='240'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='240' height='240' filter='url(%23n)'/%3E%3C/svg%3E");
}

.cursor {
  position: fixed; left: 0; top: 0; z-index: 95;
  pointer-events: none; opacity: 0;
  transform: translate(-50%, -50%) scale(.7);
  transition: opacity .25s ease, transform .3s var(--ease);
  display: flex; align-items: center; gap: .5em;
  background: var(--lime); color: var(--ink);
  font-family: var(--mono); font-size: 11px; font-weight: 500;
  letter-spacing: .14em; text-transform: uppercase;
  padding: 11px 15px; border-radius: 999px; white-space: nowrap;
  box-shadow: 0 8px 24px -10px rgba(0, 0, 0, .7);
}
.cursor.is-on { opacity: 1; transform: translate(-50%, -50%) scale(1); }

/* --- Shared primitives ---------------------------------------------------- */

.h2 {
  font-family: var(--display); font-weight: 900;
  font-size: clamp(2.1rem, 4.6vw, 4.25rem);
  line-height: .88; letter-spacing: -.04em;
  text-wrap: balance;
}

.mask { overflow: hidden; }
.mask--line { display: block; padding-bottom: .03em; }

/* The flock mark standing in for the CTA arrow. Dots lift on hover, wired in JS. */
.flight {
  width: .72em; height: 1.05em; flex: 0 0 auto; overflow: visible;
  transform: translateY(-.11em) rotate(-29deg);
  --dot: currentColor;
  --dot-mid: var(--paper);
}
.flight circle { fill: var(--dot); }
.flight .flight__mid { fill: var(--dot-mid); }
.flight--inverse { --dot: var(--paper); --dot-mid: var(--lime); }

.btn {
  display: inline-flex; align-items: center; gap: .7em;
  font-family: var(--ui); font-weight: 700; line-height: 1;
  letter-spacing: -.01em; white-space: nowrap;
  font-size: clamp(15px, 1.2vw, 17px);
  padding: clamp(17px, 1.5vw, 21px) clamp(24px, 2.1vw, 30px);
  transition: background-color .4s var(--ease), color .4s var(--ease);
}
.btn--primary { background: var(--ink); color: var(--paper); }
.btn--primary:hover, .btn--primary:focus-visible { background: var(--paper); color: var(--ink); }

/* The fold's only saturated element on the paper side, balancing the one live
   tile across the split. */
.btn--lime { background: var(--lime); color: var(--ink); }
.btn--lime:hover, .btn--lime:focus-visible { background: var(--ink); color: var(--lime); }

.btn--onlime {
  background: var(--ink); color: var(--lime); gap: .65em;
  padding: clamp(15px, 1.35vw, 19px) clamp(22px, 1.9vw, 28px);
}
.btn--onlime:hover, .btn--onlime:focus-visible { background: var(--rule-dark); color: var(--lime); }

.link-rule {
  font-family: var(--mono);
  font-size: clamp(13px, 1.05vw, 15px);
  padding-bottom: 4px;
  border-bottom: 1.5px solid;
  transition: border-color .35s ease;
}
.link-rule--ink   { border-bottom-color: rgba(10, 10, 11, .32); }
.link-rule--ink:hover, .link-rule--ink:focus-visible { border-bottom-color: var(--ink); }
.link-rule--solid { border-bottom-color: var(--ink); padding-bottom: 3px; }
.link-rule--dark {
  display: inline-flex; align-items: center; gap: .6em;
  font-size: 11.5px; letter-spacing: .13em; text-transform: uppercase;
  color: var(--d-1); border-bottom: 1px solid var(--rule-soft); padding-bottom: 3px;
}
.link-rule--dark:hover, .link-rule--dark:focus-visible { border-bottom-color: var(--d-1); }

/* --- Header --------------------------------------------------------------- */

/* A solid bar from the first pixel. The fold is split paper/ink, so a
   transparent header would put the nav links over both grounds at once and
   fail contrast on the dark half. */
.nav {
  position: fixed; left: 0; right: 0; top: 0; z-index: 40;
  background: var(--ink); color: var(--paper);
}

/* The bar is deliberately shallow. It is fixed, so every pixel of it is a pixel
   the fold has to clear before the hero can start — and the fold below has to
   close on the trust ticker inside one screen. */
.nav__inner {
  max-width: var(--shell); margin-inline: auto;
  padding: clamp(10px, 1.05vw, 14px) var(--gutter);
  display: flex; align-items: center; justify-content: space-between;
  gap: clamp(16px, 3vw, 40px); flex-wrap: wrap;
}

.nav__logo { display: block; flex: 0 0 auto; height: clamp(15px, 1.3vw, 19px); }
.nav__logo-img { height: 100%; width: auto; }

.nav__links { display: flex; align-items: center; gap: clamp(14px, 1.8vw, 30px); }

.nav__link {
  font-family: var(--mono); font-size: clamp(10.5px, .8vw, 11.5px);
  letter-spacing: .13em; text-transform: uppercase;
  color: var(--d-7); transition: color .35s ease;
}
.nav__link:hover, .nav__link:focus-visible { color: var(--lime); }

/* The hero ends in its own CTA; the nav's copy appears once that has gone. */
.nav__cta {
  display: inline-flex; align-items: center; gap: .6em;
  background: var(--lime); color: var(--ink);
  font-family: var(--ui); font-size: clamp(12.5px, .95vw, 13.5px); font-weight: 700; line-height: 1;
  padding: clamp(9px, .85vw, 12px) clamp(14px, 1.4vw, 20px);
  opacity: 0; pointer-events: none; transform: translateY(-6px);
  transition: opacity .3s ease, transform .3s ease;
}
.nav.is-scrolled .nav__cta { opacity: 1; pointer-events: auto; transform: none; }
.nav__cta:hover, .nav__cta:focus-visible { opacity: .86; }

/* --- Hero ------------------------------------------------------------------
   Fifteen identical templates and one live client site. The argument the whole
   page makes is made here, before a word is read: the left plane says it, the
   right plane proves it. No eyebrow, no placeholder, no stock photography.
   -------------------------------------------------------------------------- */

/* The fold is one screen: hero + trust ticker, nothing spilling past the
   bottom edge. --fold-tail is the measured height of whatever bands remain
   below the hero (see fitFold) and --nav-h the measured height of the fixed bar (see fitNav),
   so the hero takes exactly what is left and the ticker always lands inside.
   Every vertical measure below therefore carries an svh term as well as a vw
   one: on a short laptop the type and the rhythm give ground before the fold
   does. */
/* ONE PLANE, not two. The paper/ink split put a ~20:1 edge down the full height
   of the viewport, which made the loudest thing in the fold a divider carrying
   no information — it out-contrasted both the headline and the lime action. It
   also gave the two halves equal authority, which contradicts the argument the
   fold makes: the offer leads and the proof supports it.
   The deeper problem was further down. Everything from the hero's ink half to
   the bottom of the Room was one unbroken near-black mass — hero-right, facts,
   trust and gallery, about 4,200px with no boundary anywhere in it. The Room is
   the centrepiece and it is meant to be ARRIVED at; you cannot arrive anywhere
   you have already been standing for three sections. So the dark leaves the
   hero entirely and the page alternates again: bone fold, ink plinth, dark
   gallery, bone, ink, lime.
   The two-column grid stays — it is the layout, not the colour scheme. */
/* Constrained to the shell like every other section, which it never was as a
   two-plane composition — the split was architectural and wanted the full
   bleed. As one plane it just looked broken on a wide monitor: at 2560 the
   headline sat on a 72px gutter while the price plinth below it started 472px
   in, because the plinth respects the shell and the hero did not. Nothing
   changes at or below 1600, and the bone still bleeds edge to edge because the
   body carries the same colour — only the content is bounded. */
.hero {
  max-width: var(--fold-shell); margin-inline: auto;
  display: grid;
  grid-template-columns: minmax(0, 44fr) minmax(0, 56fr);
  /* Full screen again. The cap existed because three plates plus a headline
     could not fill a tall viewport without a grotesque type size — with one
     plate the fold has a single object big enough to hold the space, so the
     hero goes back to taking exactly what is left above the plinth. */
  min-height: calc(100svh - var(--fold-tail, 190px));
  background: var(--paper); color: var(--ink);
}

/* One register. The baseline proof line and its hairline are gone, so the
   column has nothing to compose against its own bottom edge and the argument
   simply centres in the plane. The two-register grid existed to shape leftover
   space; a rule sitting under a headline for its own sake is exactly the
   busyness this pass removed. */
.hero__say {
  padding: calc(var(--nav-h, 66px) + clamp(18px, min(2.6vw, 3.4svh), 44px))
           clamp(28px, 3.4vw, 56px)
           clamp(24px, min(3.4vw, 4svh), 44px)
           var(--gutter);
  display: flex; flex-direction: column; justify-content: center;
}
.hero__block {
  display: flex; flex-direction: column; justify-content: center;
  /* Ceiling raised from 30px. On a tall monitor the argument column runs a
     couple of hundred pixels shorter than the plate beside it, and the fix is
     rhythm rather than a larger headline — the headline is already set to the
     full measure of its column. */
  gap: clamp(15px, min(2.2vw, 4.2svh), 54px);
}
/* Give the reveal masks room for descenders, then take the room back so the
   column's own rhythm is unchanged. */
.hero__say .mask {
  padding-bottom: clamp(10px, 1.4vw, 22px);
  margin-bottom: calc(0px - clamp(10px, 1.4vw, 22px));
}

/* Ceiling down from 5.25rem, not up. Once the hero took the shell the measure
   stopped growing with the monitor, so a bigger cap just bought a four-line
   headline — the type has to be sized to the column, not to the screen. At
   ~4.6rem it sets in three lines on a wide display and fills the plane, which
   is what the old cap failed to do. The svh term still governs on short
   screens: there the type gives ground before the fold does. */
.hero__h1 {
  font-family: var(--display); font-weight: 900;
  font-size: clamp(2.35rem, min(4.4vw, 8.3svh), 6.5rem);
  line-height: .88; letter-spacing: -.04em; text-wrap: balance;
}
.hero__h1 em { font-style: normal; color: var(--red); }

.hero__lede {
  font-family: var(--sans); font-size: clamp(1rem, min(1.35vw, 3.1svh), 1.75rem);
  line-height: 1.45; letter-spacing: -.015em; color: var(--l-2);
  max-width: 44ch; text-wrap: pretty;
}
/* The turn. Full ink against the lede's grey — the tone carries the structure,
   so the plane gains a type level without gaining a colour. */
.hero__turn {
  font-family: var(--sans); font-weight: 500;
  font-size: clamp(1.25rem, min(1.9vw, 4.1svh), 2.4rem);
  line-height: 1.2; letter-spacing: -.025em; color: var(--ink);
}
/* The two facts the price plinth used to carry, at the scale they deserve.
   Mono because they are measurements — the one thing mono is reserved for —
   and set as one line so the eye takes them as a single qualifier rather than
   as a table. The numerals go ink against the line's grey so the two figures
   read first without needing a size of their own. */
.hero__spec {
  font-family: var(--mono); font-size: clamp(11px, min(.86vw, 1.5svh), 13.5px);
  letter-spacing: .12em; text-transform: uppercase; color: var(--l-3);
}
.hero__spec b { font-weight: 500; color: var(--ink); }
.hero__spec span { padding: 0 .35em; color: var(--rule-bone); }

.hero__actions {
  display: flex; align-items: center; flex-wrap: wrap;
  gap: clamp(16px, 1.6vw, 24px);
}
/* Mono is reserved for URLs and measurements; this is a secondary action. */
.hero__actions .link-rule { font-family: var(--sans); }

.hero__wall {
  position: relative;
  /* Right edge on the shared gutter so the plates line up with the plinth's
     right edge below; left stays tighter — that is the internal column gap
     between the argument and the proof, not a page margin. */
  padding: calc(var(--nav-h, 66px) + clamp(14px, min(1.9vw, 2.6svh), 32px))
           var(--gutter)
           clamp(22px, min(3vw, 3.6svh), 44px)
           clamp(20px, 2.4vw, 40px);
  display: flex; flex-direction: column; gap: clamp(12px, min(1.4vw, 1.8svh), 20px);
}
/* ONE client, at the size one client deserves. The fold carried three pairs,
   then a feature plus two supporters; both were busy, and both made the visitor
   audit a grid instead of look at a website. A single object can hold a
   full-height plane on its own, and it is the only version where the plate is
   large enough that the claim in the headline is simply visible rather than
   argued. Bond St. and Capitoline lose nothing — the gallery below already
   shows all three live, bigger, and in their own colour.
   flex-basis 0, not auto: the pair is the one thing in the fold that gives
   ground. At auto its intrinsic height sets a floor taller than a short laptop
   allows, the hero grows past its min-height, and the trust ticker is pushed
   off the screen. At 0 it takes whatever the fold has left and the shot crops
   from the bottom, which is the part of a website fold nobody reads. */
.pair {
  flex: 1 1 0; min-height: 0;
  display: flex; flex-direction: column; justify-content: center;
  gap: clamp(8px, .8vw, 14px);
  /* Print geometry, in one place because the values are interdependent:
     --print-drop is both the print's overhang past the plate and the padding
     the stack reserves for it, so they cannot drift.
     The operative rule: the print may cover the plate's dead corner and nothing
     that carries the client's name. At 56% it took the "D" off a headline; the
     overlap frames the live site, it does not censor it. On a plate this size
     34% is a ~270px card — larger in absolute terms than the old three-up
     plates were — while covering less of the after than any version before it. */
  --print-w:     34%;
  --print-out:   clamp(14px, 1.6vw, 30px);
  --print-mount: clamp(5px, .5vw, 9px);
  --print-drop:  clamp(24px, 2.4vw, 40px);
}
/* A vertical stagger across the three columns was tried and removed. The client
   name travels with its pair, so offsetting the columns put the three captions
   at three different heights, and the field read as misalignment rather than as
   composition. Rhythm in this row has to come from the pair's internal
   asymmetry, not from breaking its baseline. */
/* The client name is gone from the fold. With one plate the chrome bar's
   hostname already names the business, and a mono caption repeating it was a
   second label doing no work — exactly the kind of element that made the old
   three-up field feel like a spec sheet. The gallery below still names all
   three clients in full. */

/* aspect-ratio sets the preferred size and flex-shrink allows it to be taken
   away. At any normal viewport the frames render at exactly the ratio the
   captures were taken at, so nothing is cropped sideways; only on a short
   screen do they compress and lose their lower edge. Sized purely by flex
   weight they stretched taller than 16:10 and `cover` ate the left and right
   of every screenshot — which is where the logotypes are. */
/* The stacking context for one client. The plate sits in normal flow and the
   print hangs off its bottom-left corner, so the box reserves the overhang as
   padding instead of letting an absolutely-positioned child escape the column
   and collide with the caption underneath. */
.pair__stack {
  position: relative; flex: 0 1 auto; min-height: 0;
  display: flex; flex-direction: column;
  padding-bottom: var(--print-drop);
}

/* The before as a PRINT, not a second frame. Stacked above the plate it was two
   rectangles the eye had to be told were related, and the fold spent real
   height saying so. Laid over the plate's corner in its own bone mount it is
   unarguably one object: depth does the grouping a caption was doing badly, the
   column gets ~90px of height back, and the pair finally has a focal point
   instead of two equal halves.
   The mount also settles the label. On bone, inside the print's own border, the
   tag needs no outline, sits on nothing, and covers none of the capture — which
   is what the previous two attempts were each half-solving. */
.pair__was {
  position: absolute; z-index: 2;
  left: calc(-1 * var(--print-out)); bottom: 0;
  width: var(--print-w);
  background: var(--paper);
  padding: var(--print-mount) var(--print-mount) 0;
  box-shadow: 0 14px 28px -12px rgb(var(--shadow-warm) / .5),
              0 2px 5px -2px rgb(var(--shadow-warm) / .3);
  transition: transform .7s var(--ease);
}
/* Drained of colour rather than deleted: it has to stay legible as a real
   website — you should be able to read the nav and see that all three share
   it — while never competing with the colour below.
   On ink this was darkened (brightness .72) so it would sink into the plane.
   On bone the same move produces a heavy black rectangle that outweighs the
   thing being sold, so the fade now runs the other way: fully desaturated,
   lifted and softened until it reads as sun-bleached. The old site should look
   like a photograph left in a window, not like a hole in the page. */
.pair__was img {
  display: block; width: 100%; height: auto;
  aspect-ratio: 16 / 10; object-fit: cover; object-position: top;
  background: var(--paper-sink);
  filter: saturate(0) contrast(.62) brightness(1.24) opacity(.78);
  mix-blend-mode: multiply;
}
/* The caption in the print's mount, the way a date is written under a photo.
   Three previous attempts each traded one problem for another: dark-on-dark and
   invisible at the frame's bottom edge; legible at the top-left but covering
   the old nav on all three captures; legible and harmless out in the negative
   space but floating away from what it labelled. In the mount it is attached,
   unobstructed and needs no border to be found. */
.pair__tag {
  display: block;
  padding: .62em .1em .5em;
  font-family: var(--mono); font-weight: 500;
  font-size: clamp(8px, .62vw, 9.5px);
  letter-spacing: .18em; text-transform: uppercase; white-space: nowrap;
  color: var(--l-3);
}

/* The star of the column: full width, full colour, wearing chrome, and the only
   thing in the pair you can open. Roughly 1.7x the before on the long edge, so
   the eye lands here first and the small grey frame above reads as the note it
   is. */
.pair__now {
  flex: 0 1 auto; min-height: 0; width: 100%;
  display: flex; flex-direction: column; position: relative;
  background: var(--ink-chrome); cursor: pointer;
  border-radius: var(--plate-radius); overflow: hidden;
  /* A resting shadow, which the ink version neither had nor needed. On bone the
     plate has to sit ON the page rather than be a hole cut in it — this is the
     whole reason the after now reads as a real browser window on a desk. */
  box-shadow: 0 10px 26px -14px rgb(var(--shadow-warm) / .45),
              0 2px 6px -3px rgb(var(--shadow-warm) / .22);
  transition: box-shadow .7s var(--ease), transform .7s var(--ease);
  /* Chrome measured against the frame, not the viewport, so the bar stays the
     same fraction of the window at every breakpoint. In px it reads as a
     hairline at one size and a slab at the next. */
  container-type: inline-size;
}
.pair__now:hover, .pair__now:focus-visible {
  transform: translateY(-3px);
  box-shadow: 0 26px 52px -20px rgb(var(--shadow-warm) / .5), 0 0 0 1.5px var(--lime);
}
/* Fixed at the ratio the captures were taken at. Letting the plate grow into
   the fold's spare height was tried and is wrong: `cover` responds to a taller
   frame by zooming, so the sides go first — and the sides are where every one
   of these sites puts its logotype. Spare bone is cheaper than a cropped
   logo. */
.pair__shot {
  display: block; flex: 0 1 auto; min-height: 0;
  width: 100%; aspect-ratio: 16 / 10; overflow: hidden;
}
/* NEVER cropped left or right — the visitor must see the client's full desktop
   width, because a site cut off at the edges is not evidence of a site.
   The invariant is structural rather than lucky. The capture is 960x600 (16:10)
   and the box is `aspect-ratio: 16/10`, so at rest the fit is exact. The box's
   only freedom is to SHRINK IN HEIGHT on a short screen, which can only make it
   *wider* in aspect; `cover` then scales by width, so the full width always
   fits and the trim is taken off the bottom, which is the part of a website
   fold nobody reads. Measured at box heights of 714 / 600 / 480 / 360: the
   horizontal crop is 0 at every one.
   The one thing that would break it is giving this box an aspect TALLER than
   16:10 — that makes `cover` scale by height and eat both sides, which is
   exactly where the logotype and the reservation button live. Don't. */
.pair__shot img { width: 100%; height: 100%; object-fit: cover; object-position: top; }

/* The counterpart to the BEFORE slab, and the reason the pair is legible as a
   pair: two labels on one axis state a sequence that one label can only imply.
   Lime and solid, because this is the half being sold. The arrow puts the
   affordance on the page — the follow-cursor says "open live site" but only
   once you are already on the plate, which is too late to be an invitation. */
/* Bottom-RIGHT, because the print now owns the bottom-left corner. The two
   labels still read as a matched pair — same size, same tracking — but they now
   sit at opposite ends of the plate's base, which states the sequence across
   the object rather than down it. */
.pair__live {
  position: absolute; right: 0; bottom: 0; z-index: 1;
  display: flex; align-items: baseline; gap: .5em;
  font-family: var(--mono); font-weight: 500;
  font-size: clamp(8.5px, .7vw, 10.5px);
  letter-spacing: .16em; text-transform: uppercase;
  color: var(--lime-ink); background: var(--lime);
  padding: .5em .75em .42em;
  transition: transform .5s var(--ease);
}
.pair__live-arrow { font-size: 1.05em; letter-spacing: 0; }
.pair__now:hover .pair__live, .pair__now:focus-visible .pair__live {
  transform: translateX(-2px);
}
/* The print settles as the plate lifts, so the pair moves as one object rather
   than one card sliding out from behind another. */
.pair__now:hover ~ .pair__was,
.pair__now:focus-visible ~ .pair__was { transform: translateY(3px); }

/* The case-study plates carry the same parts — three lights and a mono
   hostname — but they run 560px wide and the bar reads as chrome on its own.
   At a third of that width it reads as a dark stripe, so the hero's variant
   adds the one part that is unmistakably a browser and nothing else is: an
   address field with the URL sitting in it. Every measure is cqw, clamped at
   both ends so the hostname stays legible on a small tile and the bar never
   grows into a slab on a large one. */
.hero__chrome {
  flex: 0 0 auto; display: flex; align-items: center;
  gap: clamp(3.5px, 1.1cqw, 7px);
  padding: clamp(5px, 1.5cqw, 11px) clamp(7px, 2cqw, 15px);
  background: var(--ink-chrome);
  border-bottom: 1px solid var(--rule-dark);
}
.hero__light {
  flex: 0 0 auto; border-radius: 999px; background: var(--rule-chip);
  width: clamp(4px, 1.4cqw, 10px); height: clamp(4px, 1.4cqw, 10px);
}
/* The address field. Recessed rather than raised — a well cut into the bar, the
   way every browser draws it. */
.hero__omni {
  flex: 1 1 auto; min-width: 0; display: flex; align-items: center;
  margin-left: clamp(5px, 1.6cqw, 12px);
  height: clamp(13px, 3.6cqw, 26px);
  padding: 0 clamp(7px, 1.9cqw, 14px);
  background: var(--ink-well); border: 1px solid var(--rule-dark2);
  border-radius: 999px;
}
.hero__host {
  font-family: var(--mono); font-size: clamp(7px, 1.55cqw, 11.5px);
  letter-spacing: .05em; color: var(--d-5); line-height: 1;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}


@media (max-width: 1000px) {
  .hero { grid-template-columns: 1fr; min-height: 0; }
  .hero__say {
    padding: calc(var(--nav-h, 66px) + clamp(30px, 6vw, 52px)) var(--gutter) clamp(30px, 5vw, 44px);
  }
  .hero__wall { padding: 0 var(--gutter) clamp(30px, 5vw, 44px); }
  /* Stacked, the fold is no longer one screen, so the pair goes back to sizing
     itself from its own aspect rather than from what the fold has left. */
  .pair, .pair__stack, .pair__now { flex: 0 0 auto; }
  .pair__shot { aspect-ratio: 16 / 10; }
}
@media (max-width: 620px) {
  /* The print's overhang is a proportion of a column that is now the full
     measure, so it needs pulling in — at phone width the mount would otherwise
     hang most of the way into the gutter. */
  .pair { --print-out: clamp(8px, 2vw, 14px); --print-drop: clamp(16px, 4vw, 26px); }
}

/* --- Trust ticker --------------------------------------------------------- */

.trust { background: var(--ink); color: var(--cream); border-top: 1px solid var(--rule-dark2); }
/* The ticker is the fold's base now that the price plinth is gone, so it takes
   the fold's container rather than the document's — otherwise "BUILT FOR" sat
   320px inboard of the headline directly above it, which is the same
   misalignment the hero itself was fixed for. */
.trust__inner {
  max-width: var(--fold-shell); margin-inline: auto;
  padding: clamp(11px, 1.1vw, 15px) var(--gutter);
  display: flex; flex-wrap: wrap; align-items: center;
  gap: 10px clamp(20px, 2.4vw, 40px);
}
.trust__cap {
  flex: 0 0 auto; font-family: var(--mono); font-size: clamp(10px, .76vw, 11px);
  letter-spacing: .15em; text-transform: uppercase; color: var(--d-6);
}
.trust__ticker {
  flex: 1 1 320px; min-width: 0; overflow: hidden; white-space: nowrap;
  mask-image: linear-gradient(to right, transparent, #000 5%, #000 95%, transparent);
  -webkit-mask-image: linear-gradient(to right, transparent, #000 5%, #000 95%, transparent);
}
.trust__track { display: inline-flex; align-items: center; will-change: transform; }
.trust__ticker:hover .trust__track { animation-play-state: paused; }
.trust__item {
  display: inline-flex; align-items: center;
  gap: clamp(16px, 1.9vw, 30px); padding-right: clamp(16px, 1.9vw, 30px);
}
.trust__name {
  display: inline-flex; align-items: baseline; gap: 8px;
  font-family: var(--display); font-weight: 800;
  font-size: clamp(.9375rem, 1.05vw, 1.125rem);
  letter-spacing: .02em; text-transform: uppercase; line-height: 1;
}
.trust__tag {
  font-family: var(--mono); font-size: 10px; font-weight: 400;
  letter-spacing: .13em; text-transform: uppercase; color: var(--d-3);
}
.trust__dot { width: 5px; height: 5px; border-radius: 999px; background: var(--lime); flex: 0 0 auto; }

/* --- The room (gallery of live sites) ------------------------------------- */

.room { background: var(--ink-room); color: var(--cream); position: relative; overflow: hidden; }

.room__head {
  max-width: var(--shell); margin-inline: auto;
  padding: clamp(56px, 7vw, 104px) var(--gutter) clamp(20px, 2.2vw, 32px);
}
.room__head-inner {
  display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between;
  gap: clamp(20px, 3vw, 48px);
}
.room__h2 {
  font-family: var(--display); font-weight: 900;
  font-size: clamp(2.1rem, 5.4vw, 5rem); line-height: .88; letter-spacing: -.04em;
  max-width: 15ch; text-wrap: balance;
}
.room__lede {
  font-family: var(--sans); font-size: clamp(.9375rem, 1.15vw, 1.0625rem);
  line-height: 1.5; letter-spacing: -.01em; color: var(--d-4);
  max-width: 40ch; text-wrap: pretty;
}

.room__trackwrap { position: relative; }
.room__track {
  display: flex; flex-direction: column;
  gap: clamp(56px, 7vw, 104px);
  padding: clamp(40px, 5vw, 72px) var(--gutter) clamp(56px, 7vw, 104px);
}

.panel {
  position: relative; flex: 0 0 auto;
  display: flex; flex-wrap: wrap; gap: clamp(24px, 3vw, 52px);
  align-items: center; max-width: var(--shell); margin-inline: auto; width: 100%;
}
/* The only place a client's colour appears — as light, not paint. */
.panel__spill {
  position: absolute; left: -6%; top: -14%; width: 112%; height: 128%;
  background: radial-gradient(ellipse at 62% 50%, var(--tint) 0%, transparent 62%);
  filter: blur(90px); opacity: .42; pointer-events: none; z-index: 0;
}

.panel__meta { position: relative; z-index: 1; flex: 1 1 300px; min-width: 260px; max-width: 420px; }
.panel__kicker {
  display: flex; align-items: baseline; gap: 14px;
  font-family: var(--mono); font-size: clamp(10.5px, .8vw, 11.5px);
  letter-spacing: .15em; text-transform: uppercase; color: var(--d-5);
}
.panel__num { color: var(--label); }
.panel__name {
  display: flex; align-items: baseline; gap: .22em;
  font-family: var(--display); font-weight: 900;
  font-size: clamp(2.4rem, 5.4vw, 4.5rem); line-height: .9; letter-spacing: -.042em;
  padding-top: clamp(14px, 1.6vw, 22px);
}
.panel__arrow { width: .2em; height: .2em; color: var(--tint); flex: 0 0 auto; }
.panel__note {
  font-family: var(--sans); font-size: clamp(.9375rem, 1.15vw, 1.0625rem);
  line-height: 1.5; color: var(--d-2); padding-top: clamp(12px, 1.4vw, 18px); text-wrap: pretty;
}
.panel__runs {
  padding-top: clamp(18px, 2vw, 26px);
  border-top: 1px solid var(--rule-dark2);
  margin-top: clamp(18px, 2vw, 26px);
}
.panel__run {
  display: flex; align-items: baseline; gap: 12px; padding: 9px 0;
  font-family: var(--mono); font-size: clamp(10.5px, .8vw, 11.5px);
  letter-spacing: .1em; text-transform: uppercase; color: var(--d-2);
}
.panel__bullet { width: 6px; height: 6px; background: var(--tint); flex: 0 0 auto; transform: translateY(-2px); }
.panel__open { margin-top: clamp(20px, 2.2vw, 30px); }

.plate {
  position: relative; z-index: 1; flex: 1 1 560px; min-width: 280px; display: block;
  box-shadow: 0 50px 110px -40px rgba(0, 0, 0, .85);
  transform: translateZ(0); backface-visibility: hidden; contain: paint;
  cursor: pointer;
}
.plate__chrome { display: flex; align-items: center; gap: 8px; padding: 11px 14px; background: var(--ink-chrome); }
.plate__light { width: 9px; height: 9px; border-radius: 999px; background: var(--rule-chip); }
.plate__host {
  font-family: var(--mono); font-size: 10.5px; letter-spacing: .05em; color: var(--d-5);
  padding-left: 12px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.plate__well { position: relative; overflow: hidden; background: var(--ink-well); aspect-ratio: 16 / 10; }
.plate__hatch {
  position: absolute; inset: 0;
  background-image: repeating-linear-gradient(135deg, rgb(var(--hatch-line) / .07) 0 1px, transparent 1px 10px);
  display: flex; align-items: flex-end; padding: 18px;
}
/* Was a translucent white at 74%, which resolves to roughly #BDBDBD on the
   well — a cool grey invented for one line, three shades from an existing
   step, in a palette that otherwise contains no white at all. The Grey Is Not
   A Palette Rule exists for exactly this: use a legibility step, don't mint
   one. */
.plate__live {
  font-family: var(--mono); font-size: 10.5px; letter-spacing: .13em;
  text-transform: uppercase; color: var(--d-2);
}
/* Each embed renders at a true 1440px desktop viewport and is scaled by width
   alone (see fitEmbed) so the site is never horizontally cropped. */
.plate__frame {
  position: absolute; left: 0; top: 0; width: 1440px; height: 900px;
  border: 0; transform-origin: 0 0; pointer-events: none;
  opacity: 0; transition: opacity .9s ease;
}
.plate__frame.is-loaded { opacity: 1; }

.progress {
  position: absolute; left: var(--gutter); right: var(--gutter);
  bottom: clamp(22px, 2.4vw, 34px);
  display: none; align-items: center; gap: 18px;
}
.progress.is-active { display: flex; }
.progress__count { font-family: var(--mono); font-size: 11px; letter-spacing: .14em; color: var(--d-5); }
.progress__rail { flex: 1; height: 1px; background: var(--rule-dark2); position: relative; overflow: hidden; }
.progress__bar { position: absolute; left: 0; top: 0; bottom: 0; width: 0%; background: var(--d-1); }
.progress__name {
  font-family: var(--mono); font-size: 11px; letter-spacing: .14em;
  text-transform: uppercase; color: var(--d-1);
}

/* --- System --------------------------------------------------------------- */

.system { max-width: var(--shell); margin-inline: auto; padding: var(--block) var(--gutter) 0; }
.system__grid { display: flex; flex-wrap: wrap; gap: clamp(36px, 5vw, 80px); align-items: flex-start; }
.system__intro { flex: 1 1 340px; min-width: 0; }
.system__intro .h2 { max-width: 15ch; }
.system__lede {
  font-family: var(--sans); font-size: clamp(.9375rem, 1.15vw, 1.0625rem);
  line-height: 1.5; letter-spacing: -.01em; color: var(--l-2);
  padding-top: clamp(14px, 1.4vw, 20px); max-width: 36ch; text-wrap: pretty;
}
.system__list { flex: 1 1 480px; min-width: 0; border-top: 1.5px solid var(--ink); }
.system__item {
  display: flex; align-items: baseline; gap: clamp(14px, 1.4vw, 20px);
  border-bottom: 1px solid var(--rule-light);
  padding: clamp(15px, 1.5vw, 20px) 0;
}
.system__chip { width: 13px; height: 13px; background: var(--lime); flex: 0 0 auto; transform: translateY(-2px); }
.system__label {
  font-family: var(--ui); font-size: clamp(1.0625rem, 1.6vw, 1.5rem);
  font-weight: 500; letter-spacing: -.025em; line-height: 1.2;
}

/* --- Process -------------------------------------------------------------- */

.process { max-width: var(--shell); margin-inline: auto; padding: var(--block) var(--gutter) 0; }
.process__h2 { padding-bottom: clamp(24px, 2.8vw, 40px); }
.process__grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: clamp(10px, 1vw, 14px);
}
.step {
  background: var(--lime); color: var(--ink);
  padding: clamp(22px, 2.2vw, 30px) clamp(22px, 2.2vw, 30px) clamp(28px, 2.8vw, 38px);
  display: flex; flex-direction: column; min-height: clamp(200px, 20vw, 250px);
}
.step__top { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
.step__num {
  font-family: var(--display); font-weight: 900;
  font-size: clamp(2.5rem, 4.4vw, 4rem); line-height: .84; letter-spacing: -.03em;
}
.step__day {
  font-family: var(--mono); font-size: 11px; letter-spacing: .14em;
  text-transform: uppercase; color: var(--lime-mute);
}
.step__h {
  font-family: var(--display); font-weight: 800;
  font-size: clamp(1.25rem, 1.9vw, 1.8125rem); line-height: 1.02; letter-spacing: -.022em;
  padding-top: clamp(16px, 1.8vw, 24px);
}
.step__p {
  font-family: var(--sans); font-size: clamp(.9375rem, 1.1vw, 1rem);
  line-height: 1.5; color: var(--lime-ink);
  padding-top: clamp(9px, 1vw, 13px); text-wrap: pretty;
}

/* --- Price ---------------------------------------------------------------- */

.price { margin-top: var(--block); background: var(--ink); color: var(--paper); }
.price__inner { max-width: var(--shell); margin-inline: auto; padding: clamp(56px, 7vw, 110px) var(--gutter); }
.price__compare {
  display: flex; flex-wrap: wrap; align-items: baseline;
  gap: 8px clamp(14px, 1.4vw, 20px); padding-bottom: clamp(18px, 2vw, 28px);
}
.price__compare-label {
  font-family: var(--sans); font-size: clamp(1rem, 1.25vw, 1.1875rem);
  letter-spacing: -.01em; color: var(--d-3);
}
.price__compare-strike {
  font-family: var(--display); font-weight: 800;
  font-size: clamp(1.375rem, 2.1vw, 2rem); letter-spacing: -.025em; color: var(--d-1);
  text-decoration: line-through; text-decoration-color: var(--red);
  text-decoration-thickness: 2px; text-underline-offset: 0;
}
.price__h2 { padding-bottom: clamp(32px, 4vw, 56px); max-width: 20ch; }
.price__cols { display: flex; flex-wrap: wrap; gap: clamp(36px, 4vw, 0px); }
.price__col { flex: 1 1 400px; min-width: 0; padding-right: clamp(0px, 4vw, 72px); }
.price__col--split {
  padding-right: 0; padding-left: clamp(0px, 4vw, 72px);
  border-left: 1px solid var(--rule-dark);
}
.price__fig {
  font-family: var(--display); font-weight: 900;
  font-size: clamp(3.5rem, 10vw, 10rem); line-height: .82; letter-spacing: -.045em; color: var(--lime);
}
.price__term {
  font-family: var(--ui); font-size: clamp(1rem, 1.35vw, 1.25rem); font-weight: 700;
  letter-spacing: -.02em; padding-top: clamp(14px, 1.6vw, 22px);
}
.price__term-sub { font-weight: 400; color: var(--d-3); }
.price__list { border-top: 1px solid var(--rule-dark); margin-top: clamp(22px, 2.4vw, 34px); }
.price__item {
  border-bottom: 1px solid var(--rule-dark);
  padding: clamp(12px, 1.15vw, 15px) 0;
  font-family: var(--sans); font-size: clamp(.9375rem, 1.15vw, 1.0625rem); letter-spacing: -.01em;
}

/* --- Close ---------------------------------------------------------------- */

.close { background: var(--lime); color: var(--ink); }
.close__inner {
  max-width: var(--shell); margin-inline: auto;
  padding: clamp(56px, 7vw, 110px) var(--gutter) clamp(48px, 6vw, 92px);
}
.close__h2 {
  font-family: var(--display); font-weight: 900;
  font-size: clamp(2.4rem, 6.4vw, 6.5rem); line-height: .86; letter-spacing: -.045em;
  max-width: 15ch; text-wrap: balance;
}
.close__hang { display: inline-block; width: .13em; height: .13em; margin-left: .06em; background: var(--ink); }
.close__actions {
  display: flex; align-items: center; flex-wrap: wrap;
  gap: clamp(18px, 2vw, 28px); padding-top: clamp(26px, 3vw, 38px);
}

/* --- Footer --------------------------------------------------------------- */

.foot { background: var(--ink); color: var(--paper); }
.foot__inner {
  max-width: var(--shell); margin-inline: auto;
  padding: clamp(32px, 3.6vw, 52px) var(--gutter) clamp(28px, 3vw, 44px);
  display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between;
  gap: clamp(20px, 3vw, 48px);
}
.foot__logo { width: min(100%, 820px); height: auto; flex: 1 1 380px; min-width: 240px; }
.foot__meta {
  display: flex; flex-direction: column; gap: .7em; text-align: right;
  font-family: var(--mono); font-size: clamp(10.5px, .8vw, 11.5px);
  letter-spacing: .14em; text-transform: uppercase; color: var(--d-3);
}
.foot__mail {
  font-family: var(--mono); font-size: clamp(13px, 1.05vw, 15px);
  letter-spacing: -.01em; text-transform: none; color: var(--paper);
  border-bottom: 1.5px solid var(--lime); padding-bottom: 2px; align-self: flex-end;
}

/* --- Reduced motion ------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
  .trust__ticker { white-space: normal; }
  .trust__track { flex-wrap: wrap; }
  .plate__frame { opacity: 1; }
}
