/* ==========================================================================
   PixelForge — pxlforge.site
   Built on the PixelForge design system (Swiss editorial / signal red).
   Tokens below are lifted verbatim from the design-system source.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. TOKENS
   -------------------------------------------------------------------------- */
/* WARM CALIBRATION
   The three anchor values below (--paper-100, --ink-900, --red-500) are sampled
   from the approved render; the rest of each ramp is tuned to sit with them so
   hairlines and muted surfaces stay warm instead of going grey-blue on cream.
   Original design-system values are kept in comments — restore those three and
   their ramps to return to the stock palette. */
:root{
  color-scheme:light;

  /* theme-bound literals — values that cannot be expressed as a ramp token
     because they are translucent or must survive the dark flip untouched */
  --btn-sweep:var(--ink-900);
  --nav-stuck-bg:rgba(255,251,226,0.88);

  /* Carroyage — graph-paper ruling on the page ground. Measured off the
     reference sheet: square cells, and a rule ~9% darker than the paper.
     Cell is larger than the reference's 20px because that sheet was 736px
     wide; 28px keeps the same visual density on a desktop viewport. */
  --grid-cell:28px;
  --grid-line:rgba(0,0,0,0.075);

  /* base ramp — ink */
  --ink-1000:#000000;
  --ink-900:#000000;   /* system: #0E0E0E */
  --ink-800:#141414;   /* system: #1A1A1A */
  --ink-700:#262626;   /* system: #2B2B2B */
  --ink-500:#5A574E;   /* system: #5C5C5C */
  --ink-400:#8A8779;   /* system: #8A8A8A */
  --ink-300:#B5B2A4;   /* system: #B5B5B5 */
  --ink-200:#DAD5BE;   /* system: #D8D5CF */
  --ink-100:#EAE5CE;   /* system: #E8E5DE */

  /* base ramp — paper */
  --paper-000:#FFFFFF;
  --paper-050:#FFFDF2; /* system: #FAF9F6 */
  --paper-100:#FFFBE2; /* system: #F4F2ED — the page ground */
  --paper-200:#F6F1D8; /* system: #EBE8E1 */

  /* base ramp — signal red */
  --red-700:#A80000;   /* system: #A50F16 */
  --red-600:#D40000;   /* system: #C8141A */
  --red-500:#FB0000;   /* system: #EE1B22 */
  --red-400:#FF3B2E;   /* system: #FF3A34 */
  --red-100:#FFDCDA;   /* system: #FCDCDC */

  /* semantic — surfaces */
  --surface-page:var(--paper-100);
  --surface-card:var(--paper-000);
  --surface-inverse:var(--ink-900);
  --surface-accent:var(--red-500);
  --surface-muted:var(--paper-200);

  /* semantic — text */
  --text-body:var(--ink-700);
  --text-strong:var(--ink-900);
  --text-muted:var(--ink-500);
  --text-accent:var(--red-500);
  --text-on-dark:var(--paper-050);
  --text-on-accent:var(--paper-000);

  /* semantic — lines */
  --line-hairline:var(--ink-200);
  --line-strong:var(--ink-900);
  --line-accent:var(--red-500);

  /* semantic — interactive */
  --action-bg:var(--red-500);
  --action-bg-hover:var(--red-600);
  --action-bg-active:var(--red-700);
  --action-fg:var(--paper-000);
  --focus-ring:var(--red-500);

  /* families */
  --font-display:"Anton","Archivo Black","Arial Narrow",sans-serif;
  /* The slogan only. Anton stays the fallback so the headline degrades to the
     house display face rather than to Arial if the webfont fails. */
  --font-slogan:"Wedgie","Anton","Archivo Black",sans-serif;
  --font-core:"Archivo","Helvetica Neue",Helvetica,sans-serif;
  --font-mono:"JetBrains Mono",ui-monospace,monospace;
  /* Wordmark only. Chakra Petch's clipped 45° terminals echo the chamfered
     corners of the PF mark, so mark and name read as one lockup. */
  /* Wordmark only. Chakra Petch stays behind it as the fallback. */
  --font-brand:"Karmatic Arcade","Chakra Petch","Archivo","Helvetica Neue",sans-serif;

  /* display scale — fluid, capped at the system's reference sizes */
  /* Sized for the slogan face. Wedgie sets "SITES WEB" at 8.42em against
     Anton's 3.95em — 2.1x wider — so the old 112px cap would have run ~290px
     past the hero's text column. These values were derived from the font's
     own advance widths against the narrowest column at each width, with the
     tightest case being just above 900px where the two-column grid still
     applies. Falls back gracefully: Anton simply sets smaller. */
  --display-xxl:clamp(32px, calc(14px + 4.6vw), 74px);
  --display-xl:clamp(44px, 7.4vw, 76px);
  --display-lg:clamp(36px, 5.2vw, 54px);
  --display-md:clamp(30px, 3.9vw, 38px);
  --display-sm:clamp(24px, 2.9vw, 28px);
  --leading-display:0.9;
  --tracking-display:-0.01em;

  /* headings */
  --heading-lg:26px;
  --heading-md:20px;
  --heading-sm:16px;
  --leading-heading:1.15;
  --tracking-heading:0.01em;

  /* body */
  --body-lg:16px;
  --body-md:14px;
  --body-sm:13px;
  --leading-body:1.6;

  /* labels */
  --label-md:12px;
  --label-sm:10px;
  --tracking-label:0.14em;
  --leading-label:1.2;

  /* weights */
  --weight-regular:400;
  --weight-medium:500;
  --weight-bold:700;
  --weight-black:900;

  /* space */
  --space-1:4px;  --space-2:8px;  --space-3:12px; --space-4:16px;
  --space-5:24px; --space-6:32px; --space-7:48px; --space-8:64px;
  --space-9:96px; --space-10:128px;

  /* layout */
  --gutter:14px;
  /* Both curves hit their desktop values (40px / 96px) at ~1080px, so the
     desktop composition is untouched, and interpolate below it instead of
     stepping at 1080 and 640. */
  --page-margin:clamp(18px, calc(4.55vw - 9px), 40px);
  --container-max:1180px;
  --section-gap:clamp(48px, calc(10.9vw - 22px), 96px);
  --hairline:1px;
  --rule-heavy:3px;
  --nav-h:80px;

  /* corners + borders */
  --radius-none:0px;
  --radius-sm:10px;
  --radius-pill:999px;
  --radius-circle:50%;
  --border-hairline:1px solid var(--line-hairline);
  --border-strong:2px solid var(--line-strong);
  --border-accent:2px solid var(--line-accent);

  /* shadows */
  --shadow-lift:0 10px 24px rgba(0,0,0,0.10);
  --shadow-modal:0 24px 60px rgba(0,0,0,0.28);
  --shadow-offset-ink:8px 8px 0 var(--ink-900);
  --shadow-offset-red:8px 8px 0 var(--red-500);

  /* motion */
  --dur-fast:120ms;
  --dur-base:200ms;
  --dur-slow:420ms;
  --dur-marquee:26s;
  --ease-standard:cubic-bezier(0.2,0,0.2,1);
  --ease-out:cubic-bezier(0.16,1,0.3,1);
  --ease-in:cubic-bezier(0.6,0,1,1);
  --press-scale:0.97;
}

/* --------------------------------------------------------------------------
   1b. DARK THEME
   Both ramps flip wholesale instead of being re-picked component by component.
   Every rule in this file pairs an ink value with a paper one, so inverting
   both ends preserves each contrast pair automatically and the page keeps its
   polarity logic: sections marked "inverse" stay inverse, they just land the
   other way up. Two deliberate breaks from a straight inversion:
   paper-000 is set ABOVE paper-100 so cards still read as lifted rather than
   sunken, and anything sitting on signal red is pinned, because the red
   surface itself never changes between themes.
   -------------------------------------------------------------------------- */
[data-theme="dark"]{
  color-scheme:dark;

  /* ink ramp — now the light end of the scale */
  --ink-1000:#FFFDF2;
  --ink-900:#FFFBE2;
  --ink-800:#F2EDD3;
  --ink-700:#E2DCC2;
  --ink-500:#A8A390;
  --ink-400:#8E8977;
  --ink-300:#7E7A6C;
  --ink-200:#332F27;
  --ink-100:#241F18;

  /* paper ramp — now the dark end */
  --paper-000:#1B1811;
  --paper-050:#242017;
  --paper-100:#100E0A;
  --paper-200:#2A251B;

  /* pinned: these sit on red, which does not flip */
  --action-fg:#FFFFFF;
  --text-on-accent:#FFFFFF;

  --btn-sweep:#0B0A07;
  --nav-stuck-bg:rgba(16,14,10,0.90);
  /* the ruling inverts to light-on-dark, and needs to be fainter to read as
     texture rather than as a lit grid */
  --grid-line:rgba(255,255,255,0.055);

  /* ink shadows disappear on ink, so they carry more weight here */
  --shadow-lift:0 10px 24px rgba(0,0,0,0.50);
  --shadow-modal:0 24px 60px rgba(0,0,0,0.70);
}

/* Inverse panels stay DARK here rather than flipping to cream. On a dark page
   "inverse" has to mean lifted, not light — a cream slab would be a headlight.
   Re-declaring the ramp on the panel itself re-points every var() its own
   rules already use, so ground, headings, muted copy and hairlines all follow
   without overriding them one by one. */
[data-theme="dark"] .skip-link,
[data-theme="dark"] .section--ink,
[data-theme="dark"] .stats,
[data-theme="dark"] .ticker,
[data-theme="dark"] .drawer,
[data-theme="dark"] .why:hover,
[data-theme="dark"] .compare__head,
[data-theme="dark"] .guard,
[data-theme="dark"] .toast{
  --ink-900:#100E0A;   /* the page's own ground — one continuous dark */
  --ink-800:#1F1C15;   /* hover lifts off it slightly */
  --ink-700:#302C24;   /* hairlines and chips sitting on it */
  --ink-400:#8E8977;
  --ink-300:#A8A390;
  --paper-000:#FFFBE2; /* and the type that sits on it */
  --paper-050:#F2EDD3;
  /* .stats reads these two, and they resolve at :root unless restated here.
     Transparent so the carroyage runs through the section and the stat bar —
     both were already painting the page's own colour, so nothing else moves. */
  --surface-inverse:transparent;
  --text-on-dark:#F2EDD3;
}
/* --ink-900 above is the page ground (the drawer and ticker depend on it), so
   the guarantee cards are set separately to the same lifted tone the other
   cards use in this theme. */
[data-theme="dark"] .section--ink .guard{background:#1B1811}
/* The toast floats above the page, so it is the one panel that must not
   share the page's ground or it loses its edge entirely. */
[data-theme="dark"] .toast{--ink-900:#232019}
/* Expertise cards keep the light-mode logic — the wipe is signal red, and the
   red card alone wipes to ink. Only that ink end needs restating here, since
   --ink-900 resolves to cream in this theme. The ink card also needs a real
   ground: on the page's own black it would have no edge at all. */
[data-theme="dark"] .work--ink{background:#1B1811;color:#F2EDD3}
/* The paper card is white in light mode, which resolves to the same #1B1811
   as the ink card here — that would collapse two of the three variants into
   one tone. Held a step lighter so the rhythm survives the theme. */
[data-theme="dark"] .work--paper{background:#2A251B}
/* wipes to the ink card's own ground, not the page's, so the card keeps its
   footprint — the red card literally becomes the ink card, and vice versa */
[data-theme="dark"] .work--accent .work__wipe{background:#1B1811}
[data-theme="dark"] .work:hover,
[data-theme="dark"] .work:focus-visible{color:#FFFFFF}

/* Foregrounds on the red surface keep their light-mode values. */
[data-theme="dark"] ::selection{color:#FFFFFF}
[data-theme="dark"] .cta__lines,
[data-theme="dark"] .work--accent,
[data-theme="dark"] .svc:hover .svc__ico,
[data-theme="dark"] .guard:hover .guard__ico{color:#FFFFFF}
[data-theme="dark"] .cta__btn{background:#FFFFFF;color:#000000;border-color:#FFFFFF}
[data-theme="dark"] .cta__btn:hover{background:#000000;color:#FFFFFF;border-color:#000000}
[data-theme="dark"] .btn--outline:hover{color:var(--ink-900)}

/* Only the black mark needs flipping — the white one still sits on a dark
   panel in both themes, so it is left alone. */
/* invert first, so the red offset is not inverted along with the mark */
[data-theme="dark"] .nav__logo{filter:invert(1) drop-shadow(3px 3px 0 var(--red-500))}

[data-theme="dark"] .compare__col--us{background:rgba(251,0,0,0.09)}

/* --------------------------------------------------------------------------
   1c. SLOGAN FACE
   Self-hosted rather than linked, so it is subset to the characters the
   headline actually sets and costs 8 KB. The shipped file also carries an
   E-acute composed from the font's own E and quote mark: the original had no
   accents at all, which left ÉLÉGANT pulling its És from a fallback face.
   -------------------------------------------------------------------------- */
@font-face{
  font-family:"Karmatic Arcade";
  /* versioned for the same reason as the slogan face — see below */
  src:url("../fonts/karmatic.woff2?v=1") format("woff2");
  font-weight:400;
  font-style:normal;
  font-display:swap;
}

@font-face{
  font-family:"Wedgie";
  /* Versioned: the font is served immutable for a year, so replacing the file
     in place would leave returning visitors on the old cut. Bump this whenever
     the .woff2 is rebuilt. */
  src:url("../fonts/wedgie.woff2?v=2") format("woff2");
  font-weight:400;
  font-style:normal;
  /* the headline is held hidden until document.fonts.ready anyway, so swap
     never shows a flash of the fallback */
  font-display:swap;
}

/* --------------------------------------------------------------------------
   2. BASE
   -------------------------------------------------------------------------- */
*,*::before,*::after{box-sizing:border-box}

html{
  -webkit-text-size-adjust:100%;
  scroll-behavior:smooth;
  scroll-padding-top:calc(var(--nav-h) + 24px);
}

body{
  margin:0;
  /* The page itself is the sheet of graph paper. Cards, panels and the nav
     keep their own opaque grounds and sit ON it — only surfaces that ARE the
     page (footer, the garanties section) are transparent so the ruling runs
     through them unbroken. */
  background-color:var(--surface-page);
  background-image:
    linear-gradient(to right, var(--grid-line) 1px, transparent 1px),
    linear-gradient(to bottom, var(--grid-line) 1px, transparent 1px);
  background-size:var(--grid-cell) var(--grid-cell);
  color:var(--text-body);
  font:var(--weight-regular) var(--body-md)/var(--leading-body) var(--font-core);
  -webkit-font-smoothing:antialiased;
  -moz-osx-font-smoothing:grayscale;
  /* `clip` contains the full-bleed marquees without turning body into a
     scroll container, which would break the sticky nav. */
  overflow-x:hidden;
  overflow-x:clip;
}

body.is-locked{overflow:hidden}

h1,h2,h3,h4,p{margin:0}
ul{margin:0;padding:0;list-style:none}
img{max-width:100%;display:block}
button{font:inherit;color:inherit;background:none;border:0}

a{color:inherit;text-decoration:none}

::selection{background:var(--red-500);color:var(--paper-000)}

/* `hidden` must win over the layout display values set further down. */
[hidden]{display:none !important}

:focus-visible{
  outline:2px solid var(--focus-ring);
  outline-offset:3px;
}

.sprite{position:absolute;width:0;height:0;overflow:hidden}

.icon{
  width:1em;height:1em;
  flex:0 0 auto;
  fill:none;
  stroke:currentColor;
  stroke-width:1.75;
  stroke-linecap:round;
  stroke-linejoin:round;
  font-size:20px;
}

.skip-link{
  position:fixed;top:8px;left:8px;z-index:200;
  transform:translateY(-160%);
  background:var(--ink-900);color:var(--paper-000);
  padding:10px 16px;
  font:var(--weight-bold) var(--label-md)/1 var(--font-core);
  letter-spacing:var(--tracking-label);text-transform:uppercase;
  transition:transform var(--dur-base) var(--ease-out);
}
.skip-link:focus{transform:none}

/* --------------------------------------------------------------------------
   3. LAYOUT PRIMITIVES
   -------------------------------------------------------------------------- */
.shell{
  width:100%;
  max-width:var(--container-max);
  margin:0 auto;
  padding:0 var(--page-margin);
}

.section{padding:var(--section-gap) 0}
.section--tight{padding-bottom:var(--space-7)}

.section--ink{
  background:var(--surface-inverse);
  color:var(--text-on-dark);
  padding:var(--space-9) 0;
}
/* …but it sits on the page ground rather than reading as an inverse slab.
   Re-pointing the ramp here flips the heading, the cards, the muted copy and
   the grid hairlines in one place, leaving every component rule untouched.
   Literals, not var()s: these tokens are redefined in this very block. */
.section--ink{
  /* transparent, not the page colour: painting it opaquely would stamp a
     blank patch over the carroyage running underneath */
  --surface-inverse:transparent;
  --text-on-dark:#262626;
  /* The cards stay opaque white, like every other card grid on the site.
     .guard-grid paints --ink-700 behind them and only the 1px gaps show, so a
     transparent card exposes that backing colour across the whole block. */
  --ink-900:#FFFFFF;
  --ink-800:#FFFDF2;         /* hover, a shade off the card */
  --ink-700:#DAD5BE;         /* grid hairlines + the icon chip */
  --ink-400:#5A574E;         /* the heading note */
  --ink-300:#5A574E;         /* card body copy */
  --paper-000:#000000;       /* and the type that sits on it */
  --paper-050:#141414;
}
/* the chip fills with red on hover, so its glyph stays white */
.section--ink .guard:hover .guard__ico{color:#FFFFFF}

.eyebrow{
  font:var(--weight-bold) var(--label-sm)/var(--leading-label) var(--font-core);
  letter-spacing:var(--tracking-label);
  text-transform:uppercase;
  color:var(--text-muted);
}
.eyebrow--accent{color:var(--text-accent)}

.display{
  font-family:var(--font-display);
  font-weight:400;
  line-height:var(--leading-display);
  letter-spacing:var(--tracking-display);
  text-transform:uppercase;
  color:var(--text-strong);
}
.display--md{font-size:var(--display-md)}
.section--ink .display{color:var(--paper-000)}

.heading{
  display:flex;
  align-items:flex-end;
  justify-content:space-between;
  gap:var(--space-5);
  flex-wrap:wrap;
  padding-bottom:var(--space-4);
  border-bottom:var(--border-hairline);
  margin-bottom:var(--space-6);
}
.heading .eyebrow{margin-bottom:var(--space-2)}
.heading__note{
  font-size:var(--body-sm);
  color:var(--text-muted);
  max-width:24em;
  text-align:right;
}
.heading--ondark{border-bottom-color:var(--ink-700)}
.heading--ondark .heading__note{color:var(--ink-400)}

/* --------------------------------------------------------------------------
   4. BUTTONS + LINKS
   -------------------------------------------------------------------------- */
.btn{
  position:relative;
  display:inline-flex;
  align-items:center;
  justify-content:center;
  gap:10px;
  padding:12px 20px;
  font:var(--weight-bold) var(--label-md)/1 var(--font-core);
  letter-spacing:var(--tracking-label);
  text-transform:uppercase;
  border-radius:var(--radius-sm);
  cursor:pointer;
  overflow:hidden;
  isolation:isolate;
  background:var(--action-bg);
  color:var(--action-fg);
  border:2px solid var(--action-bg);
  transition:color var(--dur-base) var(--ease-standard),
             border-color var(--dur-base) var(--ease-standard),
             transform var(--dur-fast) var(--ease-standard);
  will-change:transform;
}
.btn > span{position:relative;z-index:1}
.btn .icon{position:relative;z-index:1;font-size:16px;stroke-width:2;
  transition:transform var(--dur-base) var(--ease-out)}

/* the sweep: two discs of ink glide in from the side edges and meet in the
   middle. Sized as a share of the button, not in em, so the pair still closes
   over a full-width .btn--block; the round caps are clipped by overflow. */
.btn::before,
.btn::after{
  content:"";
  position:absolute;
  top:50%;
  width:75%;
  aspect-ratio:1;
  z-index:0;
  border-radius:var(--radius-circle);
  background:var(--btn-sweep);
  transition:transform 500ms var(--ease-out);
}
.btn::before{left:0;transform:translate(-105%,-50%)}
.btn::after{right:0;transform:translate(105%,-50%)}
.btn:hover::before,.btn:focus-visible::before{transform:translate(-10%,-50%)}
.btn:hover::after,.btn:focus-visible::after{transform:translate(10%,-50%)}
.btn:hover{border-color:var(--ink-900)}
.btn:hover .btn__arrow{transform:translate(3px,-3px)}
.btn:active{transform:scale(var(--press-scale));border-color:var(--red-500)}

.btn--sm{padding:8px 14px;font-size:var(--label-sm);gap:8px}
.btn--sm .icon{font-size:14px}
.btn--lg{padding:16px 28px;font-size:var(--body-md);gap:12px}
.btn--lg .icon{font-size:18px}
.btn--block{display:flex;width:100%}

.btn--outline{
  background:transparent;
  color:var(--ink-900);
  border-color:var(--ink-900);
}
.btn--outline:hover{color:var(--paper-000)}

.textlink{
  display:inline-flex;
  align-items:center;
  gap:6px;
  padding-bottom:3px;
  font:var(--weight-bold) var(--label-md)/1 var(--font-core);
  letter-spacing:var(--tracking-label);
  text-transform:uppercase;
  color:var(--ink-900);
  border-bottom:1px solid transparent;
  transition:color var(--dur-fast) var(--ease-standard),
             border-color var(--dur-fast) var(--ease-standard);
}
.textlink .icon{font-size:14px;stroke-width:2;
  transition:transform var(--dur-base) var(--ease-out)}
.textlink:hover{color:var(--text-accent);border-bottom-color:var(--red-500)}
.textlink:hover .icon{transform:translate(3px,-3px)}

/* --------------------------------------------------------------------------
   5. NAV
   -------------------------------------------------------------------------- */
.nav{
  position:sticky;top:0;z-index:100;
  background:var(--paper-100);
  border-bottom:var(--border-hairline);
  transition:background var(--dur-base) var(--ease-standard),
             box-shadow var(--dur-base) var(--ease-standard);
}
.nav.is-stuck{
  background:var(--nav-stuck-bg);
  backdrop-filter:saturate(1.4) blur(12px);
  -webkit-backdrop-filter:saturate(1.4) blur(12px);
  box-shadow:0 1px 0 var(--ink-200),0 12px 28px rgba(0,0,0,0.06);
}

/* Full-bleed rather than centred on the container: the brand sits hard in the
   top-left corner of the page, with the CTA mirroring it on the right. */
.nav__bar{
  height:var(--nav-h);
  padding:0 var(--page-margin);
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:var(--space-6);
}

/* Brand lockup. The lockup uses logo-mark.png — the same artwork with its dead
   padding trimmed off, so the mark fills 96% of its box instead of 59% and
   reads at the weight of the wordmark beside it. The originals keep their
   padding for the favicon and the section watermarks. That padding used to
   double as the optical gap, so the gap is now explicit. */
.nav__brand{
  display:inline-flex;
  align-items:center;
  gap:clamp(6px, 0.8vw, 12px);
  font-family:var(--font-brand);
  font-weight:700;
  /* Karmatic sets PIXELFORGE. at 8.79em — far wider than Chakra Petch did.
     Two pinch points, not one: 320px, where the mark, the toggle and the
     burger already fill the row; and 901-1080px, the only band where the five
     links AND the CTA are both visible. A steeper curve cleared 320 but hit
     its 21px ceiling by 558px and overflowed 1024. This reaches full size at
     ~1360px instead, so the crowded band gets a smaller wordmark. Dropping the
     trailing dot freed 0.586em, which paid for most of this size increase. */
  font-size:clamp(12px, calc(4px + 1.4vw), 23px);
  letter-spacing:0.015em;
  text-transform:uppercase;
  color:var(--ink-900);
  white-space:nowrap;
}
/* Smaller box than before, but a bigger mark: the trimmed artwork fills it.
   The red offset is the same idiom as the hero mark — it traces the glyph, not
   a square, and stops the lockup reading flat next to the arcade wordmark. */
.nav__logo{
  height:58px;width:58px;
  flex:0 0 auto;
  filter:drop-shadow(3px 3px 0 var(--red-500));
  transition:transform var(--dur-base) var(--ease-out);
}
.nav__brand:hover .nav__logo{transform:translateY(-2px) rotate(-4deg)}

.nav__links{display:flex;gap:var(--space-6)}
.nav__links a{
  position:relative;
  padding-bottom:4px;
  font:var(--weight-bold) var(--label-md)/1 var(--font-core);
  letter-spacing:var(--tracking-label);
  text-transform:uppercase;
  color:var(--ink-700);
  transition:color var(--dur-fast) var(--ease-standard);
}
.nav__links a::after{
  content:"";
  position:absolute;left:0;right:0;bottom:0;
  height:2px;background:var(--red-500);
  transform:scaleX(0);transform-origin:left;
  transition:transform var(--dur-base) var(--ease-out);
}
.nav__links a:hover{color:var(--ink-900)}
.nav__links a:hover::after,
.nav__links a.is-active::after{transform:scaleX(1)}
.nav__links a.is-active{color:var(--red-500)}

.nav__actions{display:flex;align-items:center;gap:var(--space-3)}

/* theme toggle — squares off against the burger, visible at every width */
.nav__theme{
  display:grid;
  place-items:center;
  width:44px;height:44px;
  flex:0 0 auto;
  padding:0;
  background:transparent;
  color:var(--text-strong);
  border:2px solid var(--line-strong);
  border-radius:var(--radius-sm);
  cursor:pointer;
  transition:background var(--dur-fast) var(--ease-standard),
             color var(--dur-fast) var(--ease-standard);
}
.nav__theme:hover{background:var(--surface-inverse);color:var(--surface-page)}
.nav__theme:active{transform:scale(var(--press-scale))}
.nav__theme .icon{
  grid-area:1/1;
  font-size:18px;stroke-width:2;
  transition:transform var(--dur-base) var(--ease-out),opacity var(--dur-fast) linear;
}
/* one icon per theme, the outgoing one twisting away */
.nav__theme .icon--moon{opacity:0;transform:rotate(-90deg) scale(0.6)}
[data-theme="dark"] .nav__theme .icon--sun{opacity:0;transform:rotate(90deg) scale(0.6)}
[data-theme="dark"] .nav__theme .icon--moon{opacity:1;transform:none}

.nav__progress{height:2px;background:transparent}
.nav__progress span{
  display:block;height:100%;width:100%;
  background:var(--red-500);
  transform:scaleX(0);transform-origin:left;
}

/* Mirrors .nav__theme: same box, radius, border token, hover inversion and
   press response. The two sit side by side, so any difference between them
   reads as a mistake — this one had square corners against the toggle's
   rounded ones, a different hover, and no press state.
   Flex column, not grid: the grid stacked the bars from the top of the box
   rather than centring them as a group. */
.nav__burger{
  display:none;
  flex-direction:column;
  align-items:center;
  justify-content:center;
  gap:5px;
  width:44px;height:44px;
  flex:0 0 auto;
  padding:0;
  background:transparent;
  color:var(--text-strong);
  border:2px solid var(--line-strong);
  border-radius:var(--radius-sm);
  cursor:pointer;
  transition:background var(--dur-fast) var(--ease-standard),
             color var(--dur-fast) var(--ease-standard);
}
.nav__burger:hover{background:var(--surface-inverse);color:var(--surface-page)}
.nav__burger:active{transform:scale(var(--press-scale))}
.nav__burger span{
  display:block;width:20px;height:2px;
  /* currentColor, so the bars invert with the button on hover */
  background:currentColor;
  transition:transform var(--dur-base) var(--ease-out),
             opacity var(--dur-fast) linear;
}
/* centre-to-centre is 7px (a 2px bar plus the 5px gap), so that is exactly how
   far the outer bars travel to meet in the middle and form the X */
.nav__burger[aria-expanded="true"] span:nth-child(1){transform:translateY(7px) rotate(45deg)}
.nav__burger[aria-expanded="true"] span:nth-child(2){opacity:0}
.nav__burger[aria-expanded="true"] span:nth-child(3){transform:translateY(-7px) rotate(-45deg)}

/* mobile drawer */
.drawer{
  position:fixed;inset:var(--nav-h) 0 0;
  z-index:99;
  background:var(--ink-900);
  color:var(--text-on-dark);
  padding:var(--space-5) var(--page-margin) var(--space-6);
  /* Stays clipped: .drawer__mark bleeds past two edges on purpose, and would
     otherwise become scrollable area. The link list scrolls instead. */
  overflow:hidden;
  display:flex;flex-direction:column;justify-content:space-between;
  gap:var(--space-6);
  opacity:0;
  transform:translateY(-12px);
  transition:opacity var(--dur-base) var(--ease-out),transform var(--dur-base) var(--ease-out);
}
.drawer.is-open{opacity:1;transform:none}
.drawer__mark{
  position:absolute;
  right:-18%;bottom:-14%;
  width:82%;height:auto;
  opacity:0.07;
  pointer-events:none;
}
/* Six links at display-sm overflow a short phone (and any phone in landscape).
   min-height:0 lets this flex child actually shrink, so the list scrolls while
   the CTA below stays pinned and reachable. */
.drawer__links{
  position:relative;
  display:grid;gap:2px;
  min-height:0;
  overflow-y:auto;
  overscroll-behavior:contain;
  -webkit-overflow-scrolling:touch;
}
.drawer__foot{position:relative;flex:0 0 auto}
.drawer__links a{
  display:flex;align-items:baseline;gap:var(--space-4);
  padding:var(--space-4) 0;
  border-bottom:1px solid var(--ink-700);
  font-family:var(--font-display);
  font-size:var(--display-sm);
  text-transform:uppercase;
  color:var(--paper-000);
  transition:color var(--dur-fast) var(--ease-standard),
             padding-left var(--dur-base) var(--ease-out);
}
.drawer__links a em{
  font:var(--weight-bold) var(--label-sm)/1 var(--font-mono);
  font-style:normal;
  color:var(--red-500);
}
.drawer__links a:hover{color:var(--red-500);padding-left:var(--space-3)}

/* --------------------------------------------------------------------------
   6. TICKER (promise strip under nav)
   -------------------------------------------------------------------------- */
.ticker{
  background:var(--ink-900);
  color:var(--paper-050);
  overflow:hidden;
  padding:9px 0;
}
/* No flex `gap` on marquee tracks: spacing lives on the children so that
   duplicating the content makes the -50% loop seamless to the pixel. */
.ticker__track{
  display:flex;align-items:center;
  width:max-content;
  animation:pf-marquee 34s linear infinite;
}
.ticker__track > *{margin-right:var(--space-5)}
.ticker__track span{
  font:var(--weight-bold) var(--label-sm)/1 var(--font-core);
  letter-spacing:var(--tracking-label);
  text-transform:uppercase;
  white-space:nowrap;
}
.ticker__track i{color:var(--red-500);font-style:normal;font-size:11px}

@keyframes pf-marquee{
  from{transform:translate3d(0,0,0)}
  to{transform:translate3d(-50%,0,0)}
}

/* --------------------------------------------------------------------------
   7. HERO
   -------------------------------------------------------------------------- */
.hero{padding:var(--space-7) 0 var(--space-8)}

/* Text left, mark right. The left column is wide enough that the headline
   still breaks over the same two lines it did at full width — checked against
   the longest rotator word, EXCLUSIF*. */
.hero__grid{
  display:grid;
  grid-template-columns:minmax(0,1.25fr) minmax(0,0.75fr);
  gap:var(--space-7);
  align-items:center;
}
.hero__content{min-width:0}

/* The red offset is a drop-shadow, not a box-shadow: it follows the mark's
   alpha, so the offset traces the glyph itself rather than a square. It is
   the --shadow-offset-red idiom applied to artwork. */
/* Uses the trimmed mark, so the box IS the mark — the padded file left ~40% of
   this element as invisible padding, which on mobile read as the logo floating
   in dead space. These numbers are the old ones x0.612 (the ratio between the
   two files' fill), so the mark renders at exactly the size it did before. */
.hero__logo{
  width:100%;
  max-width:clamp(92px, 17.1vw, 245px);
  height:auto;
  justify-self:end;
  filter:drop-shadow(9px 9px 0 var(--red-500));
}
/* invert first, so the red offset is not inverted along with the mark */
[data-theme="dark"] .hero__logo{
  filter:invert(1) drop-shadow(9px 9px 0 var(--red-500));
}

.hero__title{
  margin:var(--space-4) 0 0;
  font-family:var(--font-slogan);
  font-weight:400;
  font-size:var(--display-xxl);
  /* Not --leading-display (0.9): that was set for Anton, which has no accent
     to house. Wedgie's É reaches 1.059em above its own baseline, so the lines
     must sit further apart than that or the accent climbs into the line above
     — line 1 descends only 0.005em, so the baseline gap is the whole budget.
     1.12 leaves ~4px of daylight at desktop size. */
  line-height:1.12;
  /* Wedgie is already wide and carries its own 3D extrusion to the right;
     Anton's negative tracking would jam the faces together. */
  letter-spacing:0;
  text-transform:uppercase;
  color:var(--ink-900);
}
/* The accented cap tops out at 1.073em. With line-height 0.9 against the
   font's 1.14em content box, half-leading puts the line-box top at 0.797em —
   so the accent sits 0.28em above the clip edge and ÉLÉGANT loses its marks.
   Pad the clip area upward and pull it straight back with an equal negative
   margin: the headroom is free, the text does not move. */
.hero__title .mask{
  display:block;
  overflow:hidden;
  padding-top:0.5em;
  margin-top:-0.5em;
  padding-bottom:0.02em;
}
.hero__title .mask > span{display:block}
.js .hero__title .mask > span{transform:translateY(105%)}

/* Alternating word. The first word stays in the flow so the line keeps its
   height and baseline; the others stack on top of it and slide through the
   mask. Width is set in JS and eased, so the asterisk stays snug. */
.hero__title .rotator{position:relative;display:inline-block;white-space:nowrap}
.hero__title .rotator > span{display:inline-block;white-space:nowrap}
.hero__title .rotator > span + span{display:none} /* no JS: first word only */

/* Width eases on the same curve and duration as the slide, so the asterisk
   travels in step with the word instead of trailing it. */
.js .hero__title .rotator{transition:width 700ms var(--ease-out)}
.js .hero__title .rotator > span{
  position:absolute;
  left:0;
  top:0;
  display:inline-block;
  opacity:0;
  /* 180%, not 140%: the mask now carries 0.5em of headroom for the É accent,
     and at 140% a parked word's lower edge sat inside that band and showed
     above the line. */
  transform:translateY(180%);
  transition:transform 700ms var(--ease-out), opacity 300ms linear;
  will-change:transform,opacity;
}
.js .hero__title .rotator > span:first-child{position:relative}
/* Keeps the headline readable if main.js never runs: until the script marks
   the rotator ready, the first word simply sits there. */
.js .hero__title .rotator:not(.is-ready) > span:first-child{opacity:1;transform:none}
/* One direction only — a word enters from below and leaves through the top.
   There is no "parked above" state, so the cycle never runs backwards. */
.js .hero__title .rotator > span.is-on{opacity:1;transform:translateY(0)}
.js .hero__title .rotator > span.is-out{opacity:0;transform:translateY(-180%)}

.hero__body{
  margin-top:var(--space-6);
  padding-top:var(--space-5);
  border-top:var(--border-hairline);
}
.lede{
  font:var(--weight-black) clamp(18px,2vw,22px)/1.25 var(--font-core);
  text-transform:uppercase;
  color:var(--ink-900);
}
.lede--accent{color:var(--red-500)}
.copy{
  margin-top:var(--space-4);
  max-width:30em;
  font-size:var(--body-md);
  color:var(--text-muted);
}
.hero__actions{
  margin-top:var(--space-6);
  display:flex;align-items:center;gap:var(--space-5);flex-wrap:wrap;
}

/* --------------------------------------------------------------------------
   8. STAT BAR
   -------------------------------------------------------------------------- */
.stats-wrap{padding-bottom:var(--space-8)}
.stats{
  display:grid;
  grid-template-columns:repeat(4,1fr);
  background:var(--surface-inverse);
  color:var(--text-on-dark);
}
.stat{
  padding:var(--space-6) var(--space-5);
  border-left:1px solid var(--ink-700);
  position:relative;
  overflow:hidden;
}
.stat:first-child{border-left:0}
.stat::after{
  content:"";position:absolute;left:0;right:0;bottom:0;height:3px;
  background:var(--red-500);
  transform:scaleX(0);transform-origin:left;
  transition:transform var(--dur-slow) var(--ease-out);
}
.stat:hover::after{transform:scaleX(1)}
.stat__v{
  font-family:var(--font-display);
  font-size:var(--display-md);
  line-height:1;
  color:var(--red-500);
}
.stat__l{
  margin-top:var(--space-3);
  font:var(--weight-bold) var(--label-md)/1.4 var(--font-core);
  letter-spacing:var(--tracking-label);
  text-transform:uppercase;
}

/* --------------------------------------------------------------------------
   9. SOCIAL PROOF MARQUEE
   -------------------------------------------------------------------------- */
.proof{padding-bottom:var(--space-7)}
.proof__label{
  border-top:2px solid var(--red-500);
  padding-top:var(--space-4);
  margin-bottom:var(--space-5);
  font:var(--weight-bold) var(--label-md)/1 var(--font-core);
  letter-spacing:var(--tracking-label);
  text-transform:uppercase;
  color:var(--red-500);
}
.marquee{overflow:hidden;padding:var(--space-2) 0}
.marquee__track{
  display:flex;align-items:center;
  width:max-content;
  animation:pf-marquee var(--dur-marquee) linear infinite;
}
.marquee__track > *{margin-right:var(--space-6)}
.marquee--rev .marquee__track{animation-direction:reverse}
.marquee:hover .marquee__track{animation-play-state:paused}
/* Row one sets solid, row two the same words in outline — an editorial
   two-weight rhythm rather than one flat band of grey. */
.marquee__track span{
  font:var(--weight-black) clamp(20px,2.6vw,30px)/1.1 var(--font-core);
  letter-spacing:0.01em;
  text-transform:uppercase;
  color:var(--ink-900);
  white-space:nowrap;
  transition:color var(--dur-base) var(--ease-standard);
}
.marquee--rev .marquee__track span{
  color:transparent;
  -webkit-text-stroke:1px var(--ink-400);
}
.marquee__track span:hover{color:var(--red-500);-webkit-text-stroke-color:var(--red-500)}
.marquee__track i{color:var(--red-500);font-style:normal;font-size:22px}

/* --------------------------------------------------------------------------
   10. SERVICES
   -------------------------------------------------------------------------- */
.svc-grid{
  display:grid;
  grid-template-columns:repeat(4,1fr);
  gap:1px;
  background:var(--line-hairline);
  border:1px solid var(--line-hairline);
}

.svc-hero{
  background:var(--red-500);
  color:var(--paper-000);
  padding:var(--space-5);
  display:flex;flex-direction:column;justify-content:space-between;
  min-height:230px;
  position:relative;overflow:hidden;
}
.svc-hero__mark{
  position:absolute;
  left:-16%;bottom:-22%;
  width:88%;height:auto;
  opacity:0.16;
  pointer-events:none;
}
.svc-hero__t{
  position:relative;
  font-family:var(--font-display);
  font-size:var(--display-sm);
  line-height:0.95;
  text-transform:uppercase;
  max-width:5em;
}
.svc-hero__a{
  position:relative;
  font-size:34px;stroke-width:1.5;align-self:flex-end;
  transition:transform var(--dur-slow) var(--ease-out);
}
.svc-hero:hover .svc-hero__a{transform:translate(6px,-6px)}

.svc{
  position:relative;
  background:var(--paper-000);
  padding:var(--space-5);
  min-height:230px;
  display:flex;flex-direction:column;
  overflow:hidden;
  transition:background var(--dur-base) var(--ease-standard);
  --mx:50%;--my:50%;
}
.svc::after{
  content:"";position:absolute;inset:0;pointer-events:none;
  background:radial-gradient(240px circle at var(--mx) var(--my),rgba(251,0,0,0.09),transparent 68%);
  opacity:0;transition:opacity var(--dur-base) var(--ease-standard);
}
.svc:hover{background:var(--paper-050)}
.svc:hover::after{opacity:1}

.svc__num{
  position:absolute;top:var(--space-5);right:var(--space-5);
  font:var(--weight-medium) var(--label-sm)/1 var(--font-mono);
  letter-spacing:0.1em;
  color:var(--ink-300);
  transition:color var(--dur-base) var(--ease-standard);
}
.svc:hover .svc__num{color:var(--red-500)}

.svc__ico{
  width:44px;height:44px;
  display:grid;place-items:center;
  border-radius:var(--radius-circle);
  border:1px solid var(--red-500);
  color:var(--red-500);
  background:transparent;
  margin-bottom:var(--space-4);
  transition:background var(--dur-base) var(--ease-standard),
             color var(--dur-base) var(--ease-standard),
             transform var(--dur-base) var(--ease-out);
}
.svc:hover .svc__ico{background:var(--red-500);color:var(--paper-000);transform:rotate(-8deg)}

.svc h3{
  font:var(--weight-black) var(--heading-sm)/1.15 var(--font-core);
  letter-spacing:var(--tracking-heading);
  text-transform:uppercase;
  color:var(--text-strong);
  margin-bottom:var(--space-2);
}
.svc p{font-size:var(--body-sm);color:var(--text-muted);max-width:24em}
.svc__tag{
  margin-top:auto;
  align-self:flex-start;
  padding-top:var(--space-4);
  font:var(--weight-bold) var(--label-sm)/1 var(--font-core);
  letter-spacing:var(--tracking-label);
  text-transform:uppercase;
  color:var(--red-500);
}

/* --------------------------------------------------------------------------
   11. EXPERTISE
   -------------------------------------------------------------------------- */
.work-grid{
  display:grid;
  grid-template-columns:repeat(6,1fr);
  gap:var(--gutter);
}
.work{
  position:relative;
  grid-column:span 2;
  min-height:250px;
  padding:var(--space-5);
  display:flex;flex-direction:column;
  overflow:hidden;
  isolation:isolate;
}
.work--wide{grid-column:span 3}
.work--ink{background:var(--ink-900);color:var(--paper-050)}
.work--paper{background:var(--paper-000);color:var(--ink-900)}
.work--accent{background:var(--red-500);color:var(--paper-000)}

.work__wipe{
  position:absolute;inset:0;z-index:-1;
  background:var(--red-500);
  /* 101%, not 100%: at exactly 100% sub-pixel rounding left a 1px red sliver
     showing along the bottom edge of the lighter cards */
  transform:translateY(101%);
  transition:transform var(--dur-slow) var(--ease-out);
}
.work--accent .work__wipe{background:var(--ink-900)}
.work:hover .work__wipe{transform:translateY(0)}
.work:hover,.work:focus-visible{color:var(--paper-000)}

.work__ico{
  width:40px;height:40px;
  display:grid;place-items:center;
  border:1px solid currentColor;
  border-radius:var(--radius-circle);
  opacity:0.75;
  margin-bottom:var(--space-5);
  transition:transform var(--dur-base) var(--ease-out),opacity var(--dur-base) linear;
}
.work:hover .work__ico{opacity:1;transform:translateY(-3px)}

.work__t{
  font-family:var(--font-display);
  font-weight:400;
  font-size:var(--display-sm);
  line-height:0.95;
  text-transform:uppercase;
  max-width:8em;
}
.work__d{
  margin-top:var(--space-3);
  font-size:var(--body-sm);
  opacity:0.72;
  max-width:26em;
}
.work__meta{
  margin-top:auto;padding-top:var(--space-5);
  display:flex;justify-content:space-between;align-items:flex-end;gap:var(--space-4);
  font:var(--weight-bold) var(--label-sm)/1 var(--font-core);
  letter-spacing:var(--tracking-label);
  text-transform:uppercase;
  opacity:0.7;
}

/* --------------------------------------------------------------------------
   12. WHY + COMPARISON
   -------------------------------------------------------------------------- */
.why-grid{
  display:grid;
  grid-template-columns:repeat(3,1fr);
  gap:1px;
  background:var(--line-hairline);
  border:1px solid var(--line-hairline);
}
.why{
  position:relative;
  background:var(--paper-000);
  padding:var(--space-6) var(--space-5);
  overflow:hidden;
  transition:background var(--dur-base) var(--ease-standard),
             color var(--dur-base) var(--ease-standard);
  --mx:50%;--my:50%;
}
.why::after{
  content:"";position:absolute;inset:0;pointer-events:none;
  background:radial-gradient(220px circle at var(--mx) var(--my),rgba(251,0,0,0.08),transparent 70%);
  opacity:0;transition:opacity var(--dur-base) var(--ease-standard);
}
.why:hover{background:var(--ink-900);color:var(--paper-050)}
.why:hover::after{opacity:1}
.why:hover h3{color:var(--paper-000)}
.why:hover p{color:var(--ink-300)}
.why__ico{
  display:grid;place-items:center;
  width:38px;height:38px;
  color:var(--red-500);
  border:2px solid var(--red-500);
  margin-bottom:var(--space-4);
  transition:transform var(--dur-base) var(--ease-out);
}
.why:hover .why__ico{transform:translateY(-3px) rotate(-6deg)}
.why h3{
  font:var(--weight-black) var(--heading-sm)/1.15 var(--font-core);
  letter-spacing:var(--tracking-heading);
  text-transform:uppercase;
  color:var(--text-strong);
  margin-bottom:var(--space-2);
  transition:color var(--dur-base) var(--ease-standard);
}
.why p{font-size:var(--body-sm);color:var(--text-muted);
  transition:color var(--dur-base) var(--ease-standard)}

.compare{
  margin-top:var(--space-7);
  border:2px solid var(--ink-900);
  background:var(--paper-000);
}
.compare__head,.compare__row{
  display:grid;
  grid-template-columns:1.6fr repeat(3,1fr);
  align-items:center;
}
.compare__head{
  background:var(--ink-900);
  color:var(--paper-050);
}
.compare__head span{
  padding:var(--space-4) var(--space-4);
  font:var(--weight-bold) var(--label-sm)/1.3 var(--font-core);
  letter-spacing:var(--tracking-label);
  text-transform:uppercase;
  text-align:center;
}
.compare__head .compare__feat{text-align:left}
.compare__head .compare__col--us{color:var(--red-500)}

.compare__row{border-top:var(--border-hairline);
  transition:background var(--dur-fast) var(--ease-standard)}
.compare__row:hover{background:var(--paper-050)}
.compare__row .compare__feat{
  padding:var(--space-4);
  font:var(--weight-bold) var(--body-sm)/1.35 var(--font-core);
  color:var(--text-strong);
}
.compare__row .compare__col{
  padding:var(--space-4);
  display:grid;place-items:center;
}
.compare__col--us{background:rgba(251,0,0,0.05)}
.compare .icon{font-size:20px;stroke-width:2.5}
.compare .ok{color:var(--red-500)}
.compare .no{color:var(--ink-300)}
.compare .mid{color:var(--ink-400)}

/* --------------------------------------------------------------------------
   13. PROCESS
   -------------------------------------------------------------------------- */
.process{
  position:relative;
  display:grid;
  grid-template-columns:repeat(4,1fr);
  gap:var(--gutter);
  padding-top:var(--space-7);
}
.process__rail{
  position:absolute;left:0;right:0;top:0;
  height:3px;background:var(--ink-100);
}
.process__rail span{
  display:block;height:100%;width:100%;
  background:var(--red-500);
  transform:scaleX(var(--p,0));transform-origin:left;
  transition:transform 120ms linear;
}
.step{
  position:relative;
  padding-top:var(--space-5);
  padding-right:var(--space-4);
}
.step::before{
  content:"";
  position:absolute;left:0;top:-3px;
  width:14px;height:3px;background:var(--ink-900);
}
.step__n{
  display:block;
  font-family:var(--font-display);
  font-size:var(--display-md);
  line-height:1;
  color:var(--ink-200);
  transition:color var(--dur-base) var(--ease-standard);
}
.step:hover .step__n{color:var(--red-500)}
.step__day{
  display:inline-block;
  margin:var(--space-3) 0 var(--space-2);
  font:var(--weight-medium) var(--label-sm)/1 var(--font-mono);
  letter-spacing:0.1em;
  text-transform:uppercase;
  color:var(--red-500);
  border:1px solid var(--red-500);
  padding:5px 8px;
}
.step h3{
  font:var(--weight-black) var(--heading-sm)/1.15 var(--font-core);
  letter-spacing:var(--tracking-heading);
  text-transform:uppercase;
  color:var(--text-strong);
  margin-bottom:var(--space-2);
}
.step p{font-size:var(--body-sm);color:var(--text-muted)}

/* --------------------------------------------------------------------------
   14. GUARANTEES (dark)
   -------------------------------------------------------------------------- */
.guard-grid{
  display:grid;
  grid-template-columns:repeat(3,1fr);
  gap:1px;
  background:var(--ink-700);
  border:1px solid var(--ink-700);
}
.guard{
  position:relative;
  background:var(--ink-900);
  padding:var(--space-6) var(--space-5);
  overflow:hidden;
  transition:background var(--dur-base) var(--ease-standard);
}
.guard::before{
  content:"";position:absolute;left:0;top:0;bottom:0;width:3px;
  background:var(--red-500);
  transform:scaleY(0);transform-origin:top;
  transition:transform var(--dur-base) var(--ease-out);
}
.guard:hover{background:var(--ink-800)}
.guard:hover::before{transform:scaleY(1)}
.guard__ico{
  display:grid;place-items:center;
  width:40px;height:40px;
  color:var(--red-500);
  border:1px solid var(--red-500);
  border-radius:var(--radius-circle);
  margin-bottom:var(--space-4);
  transition:background var(--dur-base) var(--ease-standard),
             color var(--dur-base) var(--ease-standard);
}
.guard:hover .guard__ico{background:var(--red-500);color:var(--paper-000)}
.guard h3{
  font:var(--weight-black) var(--heading-sm)/1.15 var(--font-core);
  letter-spacing:var(--tracking-heading);
  text-transform:uppercase;
  color:var(--paper-000);
  margin-bottom:var(--space-2);
}
.guard p{font-size:var(--body-sm);color:var(--ink-300)}

/* --------------------------------------------------------------------------
   15. CTA + CONTACT
   -------------------------------------------------------------------------- */
.trust{
  display:flex;align-items:center;gap:var(--space-6);flex-wrap:wrap;
  border-top:2px solid var(--red-500);
  padding:var(--space-5) 0;
  margin-bottom:var(--space-5);
}
.trust__label{
  font:var(--weight-bold) var(--label-md)/1 var(--font-core);
  letter-spacing:var(--tracking-label);
  text-transform:uppercase;
  color:var(--red-500);
}
.trust__items{
  display:flex;gap:var(--space-7);flex-wrap:wrap;flex:1;
  justify-content:space-between;
}
.trust__items span{
  font:var(--weight-black) 17px/1 var(--font-core);
  letter-spacing:0.02em;
  color:var(--ink-700);
  white-space:nowrap;
}

.cta-grid{
  display:grid;
  grid-template-columns:1.4fr 0.8fr 0.6fr;
  gap:var(--gutter);
  align-items:stretch;
}

.cta{
  display:flex;align-items:center;justify-content:space-between;gap:var(--space-6);
  background:var(--red-500);
  padding:var(--space-6) var(--space-7);
  position:relative;overflow:hidden;
}
.cta::before{
  content:"";position:absolute;inset:0;
  background:radial-gradient(60% 120% at 80% 110%,rgba(0,0,0,0.22),transparent 70%);
  pointer-events:none;
}
.cta__lines{
  position:relative;
  font-family:var(--font-display);
  font-size:var(--display-md);
  line-height:1.02;
  text-transform:uppercase;
  color:var(--paper-000);
}
.cta__lines span{display:block}
.cta__btn{
  position:relative;
  width:64px;height:64px;flex:0 0 auto;
  display:grid;place-items:center;
  border-radius:var(--radius-circle);
  background:var(--paper-000);
  color:var(--ink-900);
  border:2px solid var(--paper-000);
  transition:background var(--dur-base) var(--ease-standard),
             color var(--dur-base) var(--ease-standard),
             border-color var(--dur-base) var(--ease-standard);
  will-change:transform;
}
.cta__btn .icon{font-size:26px;stroke-width:2;
  transition:transform var(--dur-base) var(--ease-out)}
.cta__btn:hover{background:var(--ink-900);color:var(--paper-000);border-color:var(--ink-900)}
.cta__btn:hover .icon{transform:translate(3px,-3px)}
.cta__btn:active{transform:scale(var(--press-scale))}

.contact-col{
  background:var(--paper-000);
  border:var(--border-hairline);
  padding:var(--space-5);
}
.contact-col .eyebrow{margin-bottom:var(--space-4)}

.contact-row{
  width:100%;
  display:flex;align-items:center;gap:var(--space-3);
  padding:var(--space-3) 0;
  border-bottom:var(--border-hairline);
  color:var(--text-body);
  cursor:pointer;
  text-align:left;
  transition:color var(--dur-fast) var(--ease-standard),
             padding-left var(--dur-base) var(--ease-out);
}
.contact-row:last-child{border-bottom:0}
.contact-row .icon{font-size:18px;color:var(--red-500)}
.contact-row span{
  display:flex;flex-direction:column;gap:2px;flex:1;
  font:var(--weight-bold) var(--body-sm)/1.3 var(--font-core);
  color:var(--text-strong);
  word-break:break-word;
}
.contact-row span em{
  font:var(--weight-bold) var(--label-sm)/1 var(--font-core);
  font-style:normal;
  letter-spacing:var(--tracking-label);
  text-transform:uppercase;
  color:var(--text-muted);
}
.contact-row__a{opacity:0;transform:translate(-4px,4px);
  transition:opacity var(--dur-base) linear,transform var(--dur-base) var(--ease-out)}
.contact-row:hover{padding-left:var(--space-2)}
.contact-row:hover .contact-row__a{opacity:1;transform:none}
.contact-note{
  margin-top:var(--space-4);
  font-size:var(--body-sm);
  color:var(--text-muted);
}

/* --------------------------------------------------------------------------
   16. FOOTER
   -------------------------------------------------------------------------- */
.footer{
  /* was the page colour; transparent so the carroyage carries to the bottom */
  background:transparent;
  padding:var(--space-8) 0 var(--space-6);
  border-top:var(--border-hairline);
}
.footer__grid{
  display:grid;
  grid-template-columns:1.6fr repeat(3,0.8fr);
  gap:var(--space-6) var(--gutter);
}
.footer__brand p{
  margin-top:var(--space-4);
  max-width:30em;
  font-size:var(--body-sm);
  color:var(--text-muted);
}
.footer__grid .eyebrow{margin-bottom:var(--space-4)}
.footer__list{display:grid;gap:8px}
.footer__list a{
  font-size:var(--body-sm);
  color:var(--text-body);
  transition:color var(--dur-fast) var(--ease-standard);
}
.footer__list a:hover{color:var(--red-500)}

.footer__bar{
  display:flex;justify-content:space-between;align-items:center;
  gap:var(--space-5);flex-wrap:wrap;
  margin-top:var(--space-7);
  padding-top:var(--space-3);
  border-top:var(--border-hairline);
  font:var(--weight-bold) var(--label-sm)/1 var(--font-core);
  letter-spacing:var(--tracking-label);
  text-transform:uppercase;
  color:var(--text-muted);
}
.footer__legal{display:flex;gap:var(--space-5);align-items:center}
.footer__legal a{transition:color var(--dur-fast) var(--ease-standard)}
.footer__legal a:hover{color:var(--red-500)}
.footer__top{display:inline-flex;align-items:center;gap:6px}
.footer__top .icon{font-size:12px;stroke-width:2.5;
  transition:transform var(--dur-base) var(--ease-out)}
.footer__top:hover .icon{transform:translate(2px,-2px)}

/* --------------------------------------------------------------------------
   17. TOAST
   -------------------------------------------------------------------------- */
.toast{
  position:fixed;left:50%;bottom:28px;z-index:150;
  /* the clipboard fallback puts the whole address in here, which would run
     off a 320px screen without a cap */
  max-width:calc(100% - 2 * var(--page-margin));
  display:flex;align-items:center;gap:10px;
  padding:14px 20px;
  background:var(--ink-900);
  color:var(--paper-000);
  border-left:3px solid var(--red-500);
  font:var(--weight-bold) var(--label-md)/1 var(--font-core);
  letter-spacing:var(--tracking-label);
  text-transform:uppercase;
  box-shadow:var(--shadow-modal);
  transform:translate(-50%,20px);
  opacity:0;
  transition:opacity var(--dur-base) var(--ease-out),transform var(--dur-base) var(--ease-out);
}
.toast .icon{font-size:16px;stroke-width:2.5;color:var(--red-500);flex:0 0 auto}
.toast span{min-width:0;word-break:break-word}
.toast.is-on{opacity:1;transform:translate(-50%,0)}

/* --------------------------------------------------------------------------
   18. REVEAL
   -------------------------------------------------------------------------- */
.js [data-reveal]{
  opacity:0;
  transform:translateY(20px);
  transition:opacity 0.7s var(--ease-out),transform 0.7s var(--ease-out);
  transition-delay:calc(var(--d,0) * 90ms);
}
.js [data-reveal].is-in{opacity:1;transform:none}

/* --------------------------------------------------------------------------
   19. RESPONSIVE
   -------------------------------------------------------------------------- */
/* Four layout bands. --page-margin, --section-gap, --display-xxl and the hero
   panel height are fluid tokens now, so nothing below restates them — these
   queries only change things a curve cannot: column counts, flow direction
   and which chrome is visible. */

/* --- the nav row gives way before it wraps ------------------------------
   Measured, not guessed: brand + five links + the CTA need 1184px on one
   line. Below that the links were wrapping mid-label ("POURQUOI / NOUS") and
   the CTA was breaking onto two lines. The burger takes over instead, which
   is why this is its own breakpoint rather than part of the 900px block —
   the hero and the grids are fine well below here. 1200 rather than 1184, so
   the first width that shows the links has ~20px of slack instead of ~3. */
@media (max-width:1200px){
  .nav__links{display:none}
  .nav__burger{display:flex}
  .nav__actions .btn{display:none}
}

/* --- small laptop / tablet landscape ----------------------------------- */
@media (max-width:1080px){
  .svc-grid{grid-template-columns:repeat(2,1fr)}
  .cta-grid{grid-template-columns:1fr 1fr}
  .cta{grid-column:1 / -1}
  .footer__grid{grid-template-columns:1fr 1fr 1fr}
  .footer__brand{grid-column:1 / -1}
}

/* --- tablet portrait: nav collapses, hero stacks ------------------------ */
@media (max-width:900px){
  :root{--nav-h:68px}
  .nav__logo{height:50px;width:50px}

  .hero{padding-top:var(--space-6)}
  /* Single column, and the mark is dropped rather than shrunk: stacked under
     the copy it had nothing to balance against, and the nav carries the same
     logo a few hundred pixels above it. Desktop keeps it — there it fills the
     column beside the headline. */
  .hero__grid{grid-template-columns:1fr}
  .hero__logo{display:none}

  .stats{grid-template-columns:repeat(2,1fr)}
  .stat:nth-child(3){border-left:0}
  .stat:nth-child(n+3){border-top:1px solid var(--ink-700)}

  .why-grid{grid-template-columns:repeat(2,1fr)}
  .guard-grid{grid-template-columns:repeat(2,1fr)}
  .work-grid{grid-template-columns:repeat(2,1fr)}
  .work,.work--wide{grid-column:span 1}

  .process{grid-template-columns:repeat(2,1fr);gap:var(--space-6) var(--gutter)}
  .process__rail{display:none}
  .step::before{display:none}
  .step{border-top:3px solid var(--ink-900);padding-top:var(--space-4)}

  .heading__note{text-align:left}

  /* The 4-column comparison cannot honestly collapse, so it scrolls inside
     its own border rather than pushing the page sideways. */
  .compare{overflow-x:auto;overscroll-behavior-x:contain;-webkit-overflow-scrolling:touch}
  .compare__head,.compare__row{min-width:560px}
}

/* --- mobile ------------------------------------------------------------- */
@media (max-width:640px){
  .hero__actions{gap:var(--space-4)}
  .hero__actions .btn{width:100%}

  .svc-grid{grid-template-columns:1fr}
  .svc,.svc-hero{min-height:0}
  .why-grid{grid-template-columns:1fr}
  .guard-grid{grid-template-columns:1fr}
  .work-grid{grid-template-columns:1fr}
  .work{min-height:0}
  .process{grid-template-columns:1fr}

  /* Stats deliberately stay two-up (inherited from the 900px band): stacking
     all four made the page needlessly long, and each label holds at half a
     320px screen. */

  .cta-grid{grid-template-columns:1fr}
  .cta{flex-direction:column;align-items:flex-start;gap:var(--space-5);padding:var(--space-5)}
  .trust{gap:var(--space-4)}
  .trust__items{gap:var(--space-3) var(--space-5);justify-content:flex-start}
  .trust__items span{font-size:15px;white-space:normal}

  .footer__grid{grid-template-columns:1fr 1fr}
  .footer__bar{flex-direction:column;align-items:flex-start;gap:var(--space-3)}
}

/* --- small mobile (320–400px) ------------------------------------------- */
@media (max-width:400px){
  /* brand + theme toggle + burger is 316px of a 320px bar at the old sizes.
     The wordmark sizes itself fluidly now, so only the mark steps down here. */
  .nav__logo{height:40px;width:40px}
  .nav__actions{gap:var(--space-2)}

  .drawer__links a{font-size:22px;padding:var(--space-3) 0}
  .lede{font-size:17px}
  .cta{padding:var(--space-4)}
  .contact-col{padding:var(--space-4)}
  .footer__legal{gap:var(--space-4)}
}

/* --- touch input: nothing may depend on hover --------------------------- */
@media (hover:none){
  /* the row arrow is a hover reveal on desktop; on touch it must just be there */
  .contact-row__a{opacity:0.55;transform:none}
  /* pause-on-hover is unreachable, so the marquees simply keep running */
  .marquee:hover .marquee__track{animation-play-state:running}
}

@media (pointer:coarse){
  /* 13px footer links sit ~21px tall — below a comfortable tap target */
  .footer__list a,
  .footer__legal a,
  .footer__top{display:inline-flex;align-items:center;min-height:44px}
  .footer__list{gap:0}
  .textlink{padding-block:10px}
}

/* --------------------------------------------------------------------------
   20. REDUCED MOTION
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  *,*::before,*::after{
    animation-duration:0.001ms !important;
    animation-iteration-count:1 !important;
    transition-duration:0.001ms !important;
  }
  .js [data-reveal]{opacity:1;transform:none}
  .js .hero__title .mask > span{transform:none}
  .ticker__track,.marquee__track{animation:none}
}

@media print{
  .nav,.drawer,.ticker,.marquee,.toast{display:none}
  body{background:#fff}
}
