/* ============================================================================
   AXT : the design system of the prototype (site 3, "les quatre portes").
   One file, every page links it. Light world, the photograph carries the
   colour, the interface carries none, except ONE red button per screen.

   Contract (WORKPLAN section 2), in the order it is written below:
     tokens . reset . type . layout (.wrap /.wrap-wide /.sec /.sec-grey)
     section head (.kicker + h2 + .lede) . buttons (.btn) . .arrow-link
     grids . .card . [data-reveal] . .pop . header + Vehicles dropdown
     hero . doors . shop items . cart drawer . forms . footer . responsive

   Rules that must not be broken by a page:
     1. No paragraph goes full width. Text lives in .wrap (1140px).
        Strong media may use .wrap-wide (1320px) or bleed to the edge.
     2. One vertical rhythm: every band is .sec. No invented padding.
     3. Section heads are left aligned. Centre only for a solemn moment
        (the 33, a confirmation): add .is-centre on .sec-head.
     4. A main call to action is a real .btn with a solid fill. .arrow-link
        is for tertiary links inside a paragraph, never for a main action.
============================================================================ */

/* ---------------------------------------------------------------- tokens */
:root{
  /* V3 palette */
  --white:#ffffff; --grey:#f4f4f4; --grey-2:#e8e8e8; --grey-3:#d6d6d6;
  /* ink-4 is the quietest text of the charter (kickers, numbers, verbs), so it
     is the one that has to stay legible: #757575 is 4.6:1 on white, the old
     #8a8a8a was 3.5:1 and failed AA on every kicker of the site. */
  --ink:#131313; --ink-2:#3e3e3e; --ink-3:#5c5c5c; --ink-4:#757575;
  --red:#e30613; --red-deep:#c00510;
  --r:4px; --shadow:0 1px 3px rgb(0 0 0 / .08); --shadow-2:0 4px 16px rgb(0 0 0 / .1);
  --t-fast:150ms; --t:300ms; --t-slow:600ms; --ease:cubic-bezier(.4,0,.2,1);
  /* layout */
  --wrap:1140px; --wrap-wide:var(--wrap);
  --sec-pad:clamp(64px,8vw,120px); --gap:24px;
  --block-gap:clamp(26px,3.5vw,44px); --page-top:clamp(36px,5vw,64px);
  --edge:24px; --head:56px;
  /* text on a photograph */
  --halo:0 1px 2px rgb(0 0 0 / .45), 0 2px 26px rgb(0 0 0 / .38);
}

/* ----------------------------------------------------------------- reset */
*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth;scroll-padding-top:calc(var(--head) + 12px)}
body{margin:0;background:var(--white);color:var(--ink);
  font-family:'Inter Tight',system-ui,-apple-system,'Segoe UI',Arial,sans-serif;
  font-weight:500;font-size:1rem;line-height:1.5;-webkit-font-smoothing:antialiased}
img{display:block;max-width:100%}
a{color:inherit;text-decoration:none}
button,input,select,textarea{font:inherit;color:inherit}
h1,h2,h3,h4,p,ol,ul,figure,fieldset{margin:0}
ol,ul{padding:0;list-style:none}
fieldset{border:0;padding:0;min-width:0}
h1,h2,h3,h4{font-weight:600;letter-spacing:-.02em;line-height:1.06}
::selection{background:var(--ink);color:#fff}
:focus-visible{outline:2px solid var(--ink);outline-offset:3px}
.sr{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
  clip:rect(0 0 0 0);white-space:nowrap;border:0}

/* ------------------------------------------------------------------ type */
h1{font-size:clamp(2.5rem,4.4vw,3.5rem)}
h2{font-size:clamp(2rem,3.4vw,2.75rem)}
h3{font-size:clamp(1.375rem,1.9vw,1.75rem)}
.kicker{font-size:.75rem;font-weight:600;letter-spacing:.12em;text-transform:uppercase;
  color:var(--ink-4);display:block}
.lede{font-size:1.0625rem;color:var(--ink-3);max-width:52ch}
.note{font-size:.8125rem;color:var(--ink-3);line-height:1.45}
.note b{color:var(--ink)}
/* the figure line: one number per screen, and it is read, not decorated */
.fig{display:inline-block}
.fig b{font-weight:600}
.on-photo{color:#fff;text-shadow:var(--halo)}
/* photo claire : encre sur photo claire (charte V3), halo blanc doux */
.on-photo.is-ink{color:var(--ink);text-shadow:0 1px 2px rgb(255 255 255 / .5),0 2px 38px rgb(255 255 255 / .8)}
/* solid ink, not a tint: at 78% over a sand photograph the line fell under AA
   (measured on the vehicles hero, 22 August 2026) */
.on-photo.is-ink .sub{color:var(--ink-2)}
.on-photo.is-ink .tag{color:var(--ink-2)}
.hero .btn-white,.door .btn-white{box-shadow:var(--shadow)}

/* ---------------------------------------------------------------- layout */
.wrap{max-width:var(--wrap);margin-inline:auto;padding-inline:var(--edge)}
.wrap-wide{max-width:var(--wrap-wide);margin-inline:auto;padding-inline:var(--edge)}
.sec{padding-block:var(--sec-pad)}
/* every page opens at the same height: the first block under the header
   breathes with --page-top, never with the full section pad */
main>.sec:first-child,main>.sec-tight:first-child{padding-top:var(--page-top)}
.sec-grey{background:var(--grey)}
.sec-tight{padding-block:calc(var(--sec-pad) * .55)}
.rule{height:1px;background:var(--grey-2);border:0;margin:0}

/* the single section head: kicker, then a title of four words at most, then one lede */
.sec-head{margin-bottom:clamp(28px,3.4vw,52px)}
.sec-head .kicker{margin-bottom:14px}
.sec-head h2+.lede{margin-top:16px}
.sec-head.is-centre{text-align:center;margin-inline:auto;max-width:760px}
.sec-head.is-centre .lede{margin-inline:auto}
/* a head that opens a column instead of a section keeps its bottom margin for
   what follows it inside the column */
.sec-head.is-flush{margin-bottom:0}

/* ---------------------------------------------------------- the contact */
/* Built by axt.js from ONE placeholder per page (see initContact): the two
   columns, the facts and the one product link out. Nothing here is written
   in a page. */
.talk{display:grid;gap:clamp(24px,4vw,72px);align-items:start;
  grid-template-columns:repeat(2,minmax(0,1fr))}
.talk-facts{margin-top:26px;display:grid;gap:10px}
.talk-sell{margin-top:26px}
@media (max-width:900px){.talk{grid-template-columns:minmax(0,1fr)}}

/* --------------------------------------------------------------- buttons */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:10px;
  height:44px;min-width:220px;padding:0 26px;border:0;border-radius:var(--r);
  font-size:.9375rem;font-weight:600;letter-spacing:.005em;cursor:pointer;white-space:nowrap;
  transition:background var(--t-fast) var(--ease),color var(--t-fast) var(--ease),
    box-shadow var(--t) var(--ease),transform var(--t) var(--ease)}
.btn-red{background:var(--red);color:#fff}
/* the lift is a shadow of the room, never a coloured halo of the button */
.btn-red:hover{background:var(--red-deep);box-shadow:0 6px 18px rgb(19 19 19 / .18);transform:translateY(-1px)}
/* A SHEEN CROSSES THE ONE RED BUTTON when the pointer arrives. Ported from the
   "shiny button" of the magicui registry, in one rule and one transform: it is
   the only button of a screen that carries it, so it stays a signal and not a
   decoration. Nothing but transform moves, and reduced motion never sees it. */
@media (prefers-reduced-motion:no-preference){
  .btn-red{position:relative;overflow:hidden}
  .btn-red::after{content:"";position:absolute;top:-20%;bottom:-20%;width:40%;z-index:1;
    pointer-events:none;transform:translateX(-260%) skewX(-18deg);
    background:linear-gradient(100deg,transparent,rgb(255 255 255 / .3),transparent)}
  .btn-red:hover::after{transform:translateX(340%) skewX(-18deg);
    transition:transform 820ms var(--ease)}
}
.btn-ink{background:var(--ink);color:#fff}
.btn-ink:hover{background:#000;box-shadow:var(--shadow-2);transform:translateY(-1px)}
.btn-white{background:#fff;color:var(--ink)}
.btn-white:hover{background:var(--grey-2);box-shadow:var(--shadow-2);transform:translateY(-1px)}
.btn-ghost{background:#fff;color:var(--ink);box-shadow:inset 0 0 0 1px var(--grey-3)}
.btn-ghost:hover{box-shadow:inset 0 0 0 1px var(--ink);transform:translateY(-1px)}
.btn:active{transform:translateY(0)}
.btn[disabled]{opacity:.5;cursor:not-allowed;transform:none}
.btn-sm{height:38px;min-width:0;padding:0 18px;font-size:.875rem}
/* a pair: two buttons of the same width, always */
.pair{display:flex;gap:12px;flex-wrap:wrap}
.pair .btn{flex:1 1 220px}
.pair-narrow{max-width:472px}
/* a command rail: full width, stacked */
.rail-btns{display:flex;flex-direction:column;gap:8px}
.rail-btns .btn{width:100%;min-width:0}

/* the tertiary link: permanent underline, and the arrow slides on hover */
.arrow-link{display:inline-flex;align-items:center;gap:8px;font-size:.9375rem;font-weight:600;
  padding-bottom:2px;border-bottom:1px solid var(--grey-3);
  transition:border-color var(--t) var(--ease),color var(--t) var(--ease)}
.arrow-link:hover{border-bottom-color:var(--ink)}
.arrow-link .arrow,.arrow{display:inline-block;transition:transform var(--t) var(--ease)}
.arrow-link:hover .arrow,a:hover>.arrow,button:hover>.arrow{transform:translateX(4px)}
.on-photo .arrow-link{color:#fff;border-bottom-color:rgb(255 255 255 / .55)}
.on-photo .arrow-link:hover{border-bottom-color:#fff}

/* ----------------------------------------------------------------- grids */
.grid-2,.grid-3,.grid-4{display:grid;gap:var(--gap)}
.grid-2{grid-template-columns:repeat(2,minmax(0,1fr))}
.grid-3{grid-template-columns:repeat(3,minmax(0,1fr))}
.grid-4{grid-template-columns:repeat(4,minmax(0,1fr))}

/* ------------------------------------------------------------ the light */
/* The card under the pointer lights up: see initLit in axt.js (6e), where the
   two coordinates are written. The node is built by the script and only when
   motion is allowed, so this rule paints nothing on its own. The highlight is
   INK: red belongs to the offer and to the one button. */
[data-lit]>*{position:relative}
.lit{position:absolute;inset:0;z-index:0;pointer-events:none;border-radius:inherit;opacity:0;
  transition:opacity var(--t) var(--ease);
  background:radial-gradient(340px circle at var(--mx,50%) var(--my,50%),
    rgb(19 19 19 / .065),transparent 62%)}
.is-lit>.lit{opacity:1}

/* ----------------------------------------------------------------- cards */
.card{background:var(--grey);border-radius:var(--r);padding:clamp(24px,3vw,40px)}
.card h3{margin-bottom:10px}
.card .kicker{margin-bottom:12px}
.card-white{background:#fff;box-shadow:var(--shadow)}

/* -------------------------------------------------------------- motion */
/* The class is put on <html> by axt.js, and only when motion is allowed and
   GSAP answered. Without javascript, or with prefers-reduced-motion, nothing
   is ever hidden and nothing below applies. Never recode a local reveal.

   The three verbs of the site: a line draws itself, a photograph opens, a word
   rises out of its own line. Only the resting state lives here, axt.js owns
   the movement. */
html.axt-motion [data-reveal]{opacity:0}
/* a photograph is never faded, it is masked: the picture is there from the
   first frame, only the window into it grows */
html.axt-motion [data-reveal="media"]{opacity:1;clip-path:inset(0 0 100% 0)}

/* a heading waits for its words to be cut before it shows anything */
html.axt-motion [data-split]{visibility:hidden}
html.axt-motion [data-split].is-split{visibility:visible}
.w-mask{display:inline-block;overflow:hidden;vertical-align:top;
  padding-bottom:.16em;margin-bottom:-.16em}
.w-in{display:inline-block;will-change:transform}

/* the scroll cue of a hero: a hairline that says the page goes on */
.cue{position:absolute;left:50%;bottom:clamp(18px,3.2vh,34px);transform:translateX(-50%);
  z-index:2;display:flex;flex-direction:column;align-items:center;gap:10px;
  font-size:.6875rem;font-weight:600;letter-spacing:.14em;text-transform:uppercase;
  color:var(--ink-2);padding:6px 10px}
.cue .cue-l{display:block;width:1px;height:clamp(28px,4.4vh,44px);background:currentColor;
  opacity:.5;transform-origin:top center;animation:cue-fall 2.6s var(--ease) infinite}
.cue:hover .cue-l{opacity:1}
@keyframes cue-fall{
  0%{transform:scaleY(.25);opacity:0}
  36%{transform:scaleY(1);opacity:.6}
  76%{transform:scaleY(1);opacity:.6}
  100%{transform:scaleY(1) translateY(100%);opacity:0}
}
.hero .cue{color:var(--ink-2);text-shadow:0 1px 20px rgb(255 255 255 / .7)}

/* -------------------------------------------------------------- popover */
/* markup: <span class="pop-anchor"><button class="pop-t" data-pop="id"
   aria-expanded="false" aria-controls="id">75%</button>
   <span class="pop" id="id" role="note" hidden>...</span></span> */
.pop-anchor{position:relative;display:inline-block}
.pop-t{background:none;border:0;padding:0 0 2px;cursor:pointer;font:inherit;font-weight:600;
  border-bottom:1px dashed var(--ink-4);transition:border-color var(--t) var(--ease)}
.pop-t:hover,.pop-t[aria-expanded="true"]{border-bottom-color:var(--ink);border-bottom-style:solid}
.pop{position:absolute;left:0;top:calc(100% + 10px);z-index:50;width:min(300px,78vw);
  background:#fff;border-radius:var(--r);box-shadow:var(--shadow-2);padding:16px 18px;
  font-size:.875rem;font-weight:500;color:var(--ink-2);line-height:1.45;text-align:left;
  text-shadow:none}
.pop[hidden]{display:none}
.pop b{color:var(--ink)}

/* ------------------------------------------------- the modules that explain */
/* Four small objects taken from the shadcn ecosystem and rewritten in the
   grammar of this site. Each one earns its place by making something already
   on the page easier to READ, never prettier: a figure that counts, a
   sequence that looks like a sequence, a page whose length is visible, a
   comparison you can see instead of compute.
   The rules they all obey, and the reason each original was rewritten rather
   than copied: nothing animates a width or a height, nothing adds a colour
   the charter does not have, nothing glows. Their movement lives in axt.js
   (paragraph 6), like every other movement of the site, so a page without
   javascript and a reader who refuses motion both get the finished state.

     [data-count]   the figure that counts itself up
     .steps         the rail that ties a numbered sequence together
     .hdr-p         the reading rail, in the bottom edge of the header
     .bar           the share, drawn on a track that always ends at 100

   0. THE COUNTED FIGURE keeps a twin of its true value for a screen reader
      and animates a mirror marked aria-hidden, so axt.js has to put two
      spans inside it (see paragraph 6a there). Those two spans are the only
      thing the module adds to a page, and they must be invisible to the
      typography: a block that styles its own spans (.cmp-row span,
      .pk-share span, .mvf span all do) would otherwise catch them and shrink
      the figure to the size of the caption beside it. This is the whole
      style the module needs, and it is written with two selectors so it beats
      any "one class plus one tag" rule a page writes after it. */
[data-count]>.ct{font:inherit;color:inherit;letter-spacing:inherit;
  font-variant-numeric:inherit;text-transform:inherit}
/* the twin is for a screen reader, not for a clipboard: without this, dragging
   across the figure copies it twice */
[data-count]>.sr{-webkit-user-select:none;user-select:none}

/* 1. THE STEP RAIL. Idea: "timeline" of the aceternity registry (a rail that
      fills as the reader goes down) crossed with "animated-beam" of magicui
      (a line that joins two anchors it has measured). The first animates the
      height of a purple gradient, the second loops a neon sweep for ever, and
      neither belongs in a white world. What is kept is the only useful part:
      a line that says these blocks are ONE sequence. So it is a hairline of
      ink that DRAWS ITSELF, which is the first verb of the site, and its
      nodes fall over the middle of the cards below through the same track and
      the same gap, computed in css: nothing is measured, so nothing has to be
      measured again at a resize.
      It carries no word (the cards keep their own "Step 01"), so it is
      aria-hidden, and under 720px, where the cards stack and the sequence
      reads itself down the page, it is simply not there.
      The line is a div scaled on X, not an svg stroke: an svg stretched
      across a whole column has to be scaled unevenly, and a dash pattern
      under an uneven scale is a pitfall with no upside here. One pixel high
      scaled on X only is the same picture and cannot be distorted.
      Markup, and the whole of it:
        <div class="steps steps-3" data-steps aria-hidden="true">
          <span class="steps-l"></span>
          <i class="steps-d"></i><i class="steps-d"></i><i class="steps-d"></i>
        </div> */
.steps{position:relative;display:grid;gap:var(--gap);height:11px;align-items:center;
  margin-bottom:clamp(20px,2.4vw,30px)}
/* three columns: the centre of the first is (W - 2 gaps) / 6 from the edge */
.steps-3{grid-template-columns:repeat(3,minmax(0,1fr))}
.steps-3>.steps-l{left:calc((100% - 2 * var(--gap)) / 6);right:calc((100% - 2 * var(--gap)) / 6)}
.steps-l{position:absolute;top:calc(50% - .5px);height:1px;background:var(--grey-3);
  transform-origin:left center}
.steps-d{justify-self:center;width:11px;height:11px;border-radius:50%;background:#fff;
  box-shadow:inset 0 0 0 2px var(--ink)}

/* 2. THE READING RAIL. Idea: "scroll-progress" of the magicui registry, which
      pins a coloured gradient bar across the top of the window. Here it is not
      a bar of its own: the header is already the one thing on this site that
      says the page has moved (.is-stuck), so the rail IS its bottom edge, in
      ink, and it grows by a transform. axt.js only builds it on a page that
      is long enough to have somewhere to go. */
/* bottom:-1px on purpose: the header draws its own hairline one pixel BELOW
   itself (box-shadow 0 1px 0 grey-2), so a rail sitting flush inside would
   stack two edges of different colours and leave a step where it stops. Set
   one pixel lower it covers that hairline instead, and the header keeps ONE
   edge: inked as far as the page has been read, grey for what is left. */
.hdr-p{position:absolute;left:0;right:0;bottom:-1px;height:2px;background:var(--ink);
  transform:scaleX(0);transform-origin:left center;pointer-events:none}

/* 3. THE SHARE, DRAWN. Idea: the Progress of shadcn/ui itself (Radix), which
      never touches a width: the track clips, and the fill is moved by a
      transform. That is exactly the mechanism this site wants, so it is the
      one kept, ease and colours aside.
      The track ALWAYS ends at 100, and the figure written beside it is the
      one drawn: a share of a night compared on a shortened axis would make a
      five point difference look like a chasm, and that is a lie a chart tells
      easily. .bar-lead is the AXT row, in ink; the others stay grey.
      ONE source for the value, and it is --v on the track, in the markup:
      <span class="bar bar-lead" style="--v:.75" aria-hidden="true"><i></i></span>
      A page without javascript therefore shows the right length already, and
      axt.js only has that same number to grow towards. */
.bar{display:block;position:relative;height:4px;border-radius:2px;overflow:hidden;
  background:var(--grey-2);margin-top:10px}
/* the quiet fill is ink-4 and not a grey of the greys: on the grey-2 track it
   would have been two shades of the same nothing, and a bar you cannot see is
   worse than no bar */
.bar>i{position:absolute;inset:0;transform-origin:left center;border-radius:2px;
  background:var(--ink-4);transform:scaleX(var(--v,1))}
.bar-lead>i{background:var(--ink)}

/* ---------------------------------------------------------------- header */
/* sticky, white, 56px. It takes its place in the flow, so no page ever needs
   a spacer, and the Vehicles panel hangs under it. */
.hdr{position:sticky;top:0;z-index:60;height:var(--head);background:#fff;
  box-shadow:0 1px 0 var(--grey-2);transition:box-shadow var(--t) var(--ease)}
/* once the page has left the top the header stops being a line and becomes a
   plane: it is the only thing that tells you the page has moved */
.hdr.is-stuck{box-shadow:0 1px 0 var(--grey-2),0 6px 20px rgb(19 19 19 / .07)}
.hdr-in{height:100%;max-width:var(--wrap-wide);margin-inline:auto;padding-inline:var(--edge);
  display:flex;align-items:center;gap:20px}
.mark{font-weight:700;font-size:1.125rem;letter-spacing:.2em;display:flex;align-items:center}
/* 22px, not 30: since the header carries the MONOGRAM alone (the two sublines
   of the full lockup were grey mush at this size) the glyphs fill the whole
   height, so the same number would draw a mark half again as tall. */
.mark img{height:22px;width:auto;display:block}
.nav{display:flex;align-items:center;gap:clamp(14px,2.2vw,32px);margin:0 auto;
  font-size:.875rem;font-weight:600}
.nav-item{position:static;display:flex;align-items:center}
.nav-item>a{position:relative;display:block;padding:18px 0;color:var(--ink-2);white-space:nowrap;
  transition:color var(--t) var(--ease)}
.nav-item>a::after{content:"";position:absolute;left:0;right:0;bottom:12px;height:1px;background:currentColor;
  transform:scaleX(0);transform-origin:left;transition:transform var(--t) var(--ease)}
.nav-item>a:hover{color:var(--ink)}
.nav-item>a:hover::after,.nav-item>a[aria-current="page"]::after{transform:scaleX(1)}
.nav-item>a[aria-current="page"]{color:var(--ink)}

/* the cart button. The badge is ink, not red: the red is reserved for the one
   red button of the screen. */
.cart-btn{position:relative;background:none;border:0;padding:6px;cursor:pointer;display:flex;
  align-items:center;gap:8px;font-size:.875rem;font-weight:600;color:var(--ink-2)}
.cart-btn:hover{color:var(--ink)}
.cart-btn svg{width:20px;height:20px;fill:none;stroke:currentColor;stroke-width:1.6;
  stroke-linecap:round;stroke-linejoin:round}
.cart-n{min-width:18px;height:18px;border-radius:9px;background:var(--ink);color:#fff;
  font-size:.6875rem;font-weight:600;display:grid;place-items:center;padding:0 5px}
.cart-n[hidden]{display:none}
.hdr-actions{display:flex;align-items:center;gap:8px}
.nav-toggle{display:none;align-items:center;justify-content:center;gap:9px;height:44px;padding:0 12px;
  border:0;background:transparent;border-radius:var(--r);cursor:pointer;font-size:.875rem;font-weight:600}
.nav-toggle i,.nav-toggle i::before,.nav-toggle i::after{display:block;width:18px;height:1px;background:currentColor}
.nav-toggle i{position:relative}
.nav-toggle i::before,.nav-toggle i::after{content:"";position:absolute;left:0}
.nav-toggle i::before{top:-5px}
.nav-toggle i::after{top:5px}
body.nav-open{overflow:hidden}
.nav-sheet{position:fixed;inset:0;z-index:100;visibility:hidden;opacity:0;pointer-events:none;
  transition:opacity var(--t-fast) var(--ease),visibility var(--t-fast) var(--ease)}
.nav-sheet.on{visibility:visible;opacity:1;pointer-events:auto}
.nav-sheet-back{position:absolute;inset:0;border:0;background:rgb(19 19 19 / .35);cursor:pointer}
.nav-sheet-p{position:absolute;inset-block:0;inset-inline-end:0;width:min(420px,100%);background:#fff;
  display:flex;flex-direction:column;transform:translateX(100%);transition:transform var(--t) var(--ease);
  box-shadow:var(--shadow-2);outline:0}
[dir="rtl"] .nav-sheet-p{transform:translateX(-100%)}
.nav-sheet.on .nav-sheet-p{transform:none}
.nav-sheet-h{height:var(--head);padding-inline:var(--edge);display:flex;align-items:center;
  justify-content:space-between;gap:16px;border-bottom:1px solid var(--grey-2)}
.nav-sheet-h b{font-size:1rem;font-weight:600}
.nav-sheet-x{width:44px;height:44px;border:0;background:transparent;border-radius:var(--r);
  cursor:pointer;font-size:1.6rem;line-height:1}
.nav-sheet-links{padding:18px var(--edge) 30px;display:grid;overflow-y:auto}
.nav-sheet-link{min-height:52px;display:flex;align-items:center;justify-content:space-between;
  border-bottom:1px solid var(--grey-2);font-size:1.125rem;font-weight:600}
.nav-sheet-link[aria-current="page"]::after{content:"Current";font-size:.6875rem;letter-spacing:.1em;
  text-transform:uppercase;color:var(--ink-4)}

/* ------------------------------------------- the Vehicles dropdown (Tesla) */
/* built by axt.js from window.AXT.vehicles, inserted right after its trigger so
   the tab order reads: Vehicles, the panel, then the next nav link. */
.nav-panel{position:absolute;left:0;right:0;top:100%;background:#fff;
  box-shadow:0 12px 28px rgb(0 0 0 / .1);border-top:1px solid var(--grey-2);
  opacity:0;visibility:hidden;transform:translateY(-6px);
  transition:opacity var(--t) var(--ease),transform var(--t) var(--ease),visibility var(--t) var(--ease)}
.nav-panel.on{opacity:1;visibility:visible;transform:none}
.nav-panel-in{max-width:var(--wrap-wide);margin-inline:auto;padding:28px var(--edge) 20px}
.nav-cars{display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));gap:8px}
.nav-car{display:flex;flex-direction:column;align-items:center;gap:6px;padding:14px 10px 18px;
  border-radius:var(--r);text-align:center;transition:background var(--t) var(--ease)}
.nav-car:hover{background:var(--grey)}
.nav-car img{width:100%;height:80px;object-fit:contain;transition:transform var(--t) var(--ease)}
.nav-car:hover img{transform:scale(1.04)}
.nav-car .cn{font-size:.9375rem;font-weight:600;letter-spacing:-.01em}
.nav-car .cp{font-size:.8125rem;color:var(--ink-3)}
.nav-foot{display:flex;flex-wrap:wrap;gap:12px 26px;align-items:center;
  margin-top:14px;padding-top:14px;border-top:1px solid var(--grey-2)}

/* ------------------------------------------------------------------ hero */
/* the one centred block of the site: a hero is a solemn moment. */
.hero{position:relative;min-height:calc(100svh - var(--head));display:flex;align-items:center;
  overflow:hidden;background:#0a1018;isolation:isolate}
/* the plate under the photograph is only ever seen when the photograph fails.
   A hero written in ink needs that plate light, or the one time the image does
   not arrive the title lands black on near black. */
.hero:has(.on-photo.is-ink){background:#e7ded0}
.hero-img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;z-index:-1}
/* A mixed photograph gets one shared readability layer, never a page-local
   text shadow. The copy and cue stay above it while the image remains the
   backdrop of the isolated hero. */
.hero-scrim::after{content:"";position:absolute;inset:0;z-index:0;pointer-events:none;
  background:radial-gradient(ellipse 78% 62% at 50% 52%,rgb(5 10 15 / .62) 0%,
    rgb(5 10 15 / .48) 48%,rgb(5 10 15 / .2) 100%)}
.hero-scrim.hero-scrim-soft::after{
  background:linear-gradient(180deg,rgb(5 10 15 / .26),rgb(5 10 15 / .44))}
.hero-scrim>.wrap{position:relative;z-index:1}
.hero-scrim .cue{color:#fff;text-shadow:0 1px 20px rgb(0 0 0 / .72)}
/* the scrubbed sequence of the hero: a canvas axt.js creates only when the
   frames exist (data-hero-seq / data-hero-frames). It sits over the still
   photograph, in the same negative layer, and never exists on mobile. */
.hero-canvas{position:absolute;inset:0;width:100%;height:100%;z-index:-1}
.hero .wrap{width:100%;padding-block:clamp(40px,7vh,80px);text-align:center}
.hero h1{margin-bottom:18px}
.hero .fig{font-size:clamp(1rem,1.3vw,1.125rem)}
.hero .sub{margin-top:16px;font-size:.9375rem;color:rgb(255 255 255 / .88);
  max-width:46ch;margin-inline:auto}
.hero .pair{margin:26px auto 0;justify-content:center}

/* ----------------------------------------------------------- the doors */
.doors{display:grid;grid-template-columns:1fr 1fr;gap:4px}
/* six service cards: the same door, three across, a touch shorter */
.doors-3{grid-template-columns:repeat(3,1fr)}
.doors-3 .door{min-height:clamp(340px,40vh,470px)}
.doors-3 .door h3{font-size:clamp(1.5rem,1.9vw,1.875rem)}
.door{position:relative;min-height:clamp(400px,50vh,560px);overflow:hidden;isolation:isolate;
  display:flex;flex-direction:column;justify-content:space-between;padding:clamp(22px,2.2vw,36px)}
.door>img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;z-index:-1;
  transition:transform 900ms var(--ease)}
.door:hover>img{transform:scale(1.035)}
.door .tag{display:flex;gap:10px;align-items:center;font-size:.75rem;font-weight:600;
  letter-spacing:.12em;text-transform:uppercase}
.door h3{font-size:clamp(1.75rem,2.35vw,2.25rem);max-width:16ch}
.door .fig{margin-top:12px;font-size:.9375rem;max-width:34ch}
.door .btn{margin-top:24px;align-self:flex-start}
/* the outline 33 sitting behind the last door */
.door-33{position:absolute;right:clamp(14px,2vw,34px);top:clamp(40px,7vh,86px);z-index:-1;
  font-size:clamp(6rem,13vw,12rem);font-weight:600;letter-spacing:-.04em;line-height:.8;
  color:transparent;-webkit-text-stroke:1px rgb(255 255 255 / .55)}

/* ------------------------------------------------------------ shop items */
.item{background:var(--grey);border-radius:var(--r);padding:12px 12px 14px;display:flex;
  flex-direction:column;gap:8px}
.item img{width:100%;height:clamp(150px,14vw,200px);object-fit:cover;border-radius:2px}
.item .in{font-size:1rem;font-weight:600;letter-spacing:-.01em}
.item .ip{font-size:.875rem;color:var(--ink-3);font-variant-numeric:tabular-nums}
.item .btn{width:100%;min-width:0;margin-top:auto}

/* ---------------------------------------------------- the configurator */
/* IT IS NOT HERE ANY MORE. Since 22 August 2026 the whole configurator, its
   markup, its logic and ITS STYLE live in two files of their own:
     assets/configurator.js   builds the DOM and runs it
     assets/configurator.css  .cfg-band, .cfg, .stage*, .rail, .seg, .tints,
                              .modes/.mode, .price, .ogrp*, .asset, .inside
   The reason is Arnaud's, and it is the only one that matters: the same block
   is mounted on vehicles.html AND full screen on the stand tablet
   (configurator.html), so touching one has to touch the other. A page links
   configurator.css after this file and never restyles the block in its own
   <style>. Look for a configurator rule THERE, never here. */

/* ----------------------------------------------------------- cart drawer */
/* the whole drawer is built by axt.js, every page gets it for free */
.drawer{position:fixed;inset:0;z-index:80;visibility:hidden}
.drawer.on{visibility:visible}
.drawer-back{position:absolute;inset:0;background:rgb(19 19 19 / .32);opacity:0;
  transition:opacity var(--t) var(--ease)}
.drawer.on .drawer-back{opacity:1}
.drawer-p{position:absolute;top:0;right:0;bottom:0;width:min(400px,100%);background:#fff;
  box-shadow:var(--shadow-2);display:flex;flex-direction:column;transform:translateX(100%);
  transition:transform var(--t) var(--ease)}
.drawer.on .drawer-p{transform:none}
.drawer-h{display:flex;align-items:center;justify-content:space-between;gap:16px;
  padding:16px clamp(18px,2vw,26px);border-bottom:1px solid var(--grey-2)}
.drawer-h b{font-size:1.0625rem;font-weight:600}
.drawer-x{background:none;border:0;font-size:1.5rem;line-height:1;cursor:pointer;padding:4px 6px}
.drawer-b{padding:clamp(18px,2vw,26px);overflow:auto}
.cart-row{padding-bottom:12px;margin-bottom:12px;border-bottom:1px solid var(--grey-2)}
.cart-l{display:flex;justify-content:space-between;gap:16px;font-size:.9375rem}
.cart-l span:last-child{font-variant-numeric:tabular-nums;font-weight:600;white-space:nowrap}
.cart-rm{margin-top:6px;background:none;border:0;padding:0 0 2px;cursor:pointer;
  font-size:.8125rem;font-weight:600;color:var(--ink-3);border-bottom:1px solid var(--grey-3);
  transition:color var(--t) var(--ease),border-color var(--t) var(--ease)}
.cart-rm:hover{color:var(--ink);border-bottom-color:var(--ink)}
.cart-t{display:flex;justify-content:space-between;align-items:baseline;gap:16px;padding-top:14px;
  border-top:1px solid var(--grey-2);margin:6px 0 16px}
.cart-t .tv{font-size:1.375rem;font-weight:600;font-variant-numeric:tabular-nums}
/* the fictional payment marks, drawn, never an outside image */
.pay-marks{display:flex;align-items:center;gap:8px}
.visa{font-weight:700;font-style:italic;letter-spacing:.06em;font-size:.8125rem;color:var(--ink-3)}
.mc{display:flex;align-items:center}
.mc i{width:13px;height:13px;border-radius:50%;background:var(--ink-4);display:block}
.mc i+i{background:var(--grey-3);margin-left:-5px}

/* a range input: the browser draws it, the ink colours it. Used by the
   owner calculator of the home; never animated, never resized by script. */
input[type="range"]{width:100%;height:28px;margin:0;padding:0;background:none;
  accent-color:var(--ink);cursor:pointer}

/* ------------------------------------------------------------------ form */
.form{background:#fff;border-radius:var(--r);padding:clamp(22px,2.4vw,34px);display:grid;gap:14px;
  box-shadow:var(--shadow)}
.form label{display:grid;gap:6px;font-size:.8125rem;font-weight:600;color:var(--ink-3)}
.form input,.form select,.form textarea{height:44px;border:0;box-shadow:inset 0 0 0 1px var(--grey-3);
  border-radius:var(--r);padding:0 14px;background:#fff;font-weight:500;color:var(--ink);width:100%}
.form textarea{height:auto;padding:12px 14px;resize:vertical}
.form input:focus,.form select:focus,.form textarea:focus{outline:0;box-shadow:inset 0 0 0 2px var(--ink)}
.form .btn{width:100%;min-width:0;margin-top:4px}
.form-done{background:#fff;border-radius:var(--r);padding:clamp(22px,2.4vw,34px);box-shadow:var(--shadow)}
.form-done b{display:block;font-size:1.25rem;margin-bottom:6px}

/* ---------------------------------------------------------------- footer */
.ftr{border-top:1px solid var(--grey-2);padding-block:40px}
.ftr-in{max-width:var(--wrap-wide);margin-inline:auto;padding-inline:var(--edge);
  display:flex;flex-wrap:wrap;gap:20px 40px;align-items:center}
.ftr nav{display:flex;flex-wrap:wrap;gap:8px 26px;font-size:.875rem;font-weight:600}
.ftr nav a{color:var(--ink-2);transition:color var(--t) var(--ease)}
.ftr nav a:hover{color:var(--ink)}
.ftr .note{flex:1 1 260px;text-align:right}

/* ------------------------------------------------------------ responsive */
/* the configurator has its own breakpoints, in configurator.css */
@media (max-width:1080px){
  .grid-4{grid-template-columns:repeat(2,minmax(0,1fr))}
  .nav-cars{grid-template-columns:repeat(3,minmax(0,1fr))}
  .doors-3{grid-template-columns:1fr 1fr}
}
@media (max-width:900px){
  .hdr-in{gap:12px}
  .nav{display:none}
  .hdr-actions{margin-inline-start:auto}
  .nav-toggle{display:inline-flex}
  .cart-btn{width:44px;height:44px;justify-content:center;padding:0}
  .cart-btn .cart-w{display:none}
  .doors,.doors-3{grid-template-columns:1fr}
  .door{min-height:clamp(340px,58vw,460px)}
  .ftr .note{text-align:left}
}
@media (max-width:720px){
  :root{--edge:18px}
  .grid-2,.grid-3,.grid-4{grid-template-columns:minmax(0,1fr)}
  /* the cards under it stack, so a horizontal rail would say the wrong thing:
     the sequence reads itself down the page and the rail leaves */
  .steps{display:none}
  .pair{flex-direction:column}
  .pair .btn{width:100%;flex:1 1 auto}
  .hero{min-height:calc(100svh - var(--head))}
  .hero .wrap{text-align:left}
  .hero .sub,.hero .pair{margin-inline:0}
  .cart-btn .cart-w{display:none}
  .nav{font-size:.8125rem;gap:16px}
  .mark{font-size:1rem}
  .door .btn{align-self:stretch;width:100%}
}

/* the movement explains, so when it is refused nothing is hidden and
   nothing moves */
@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  *,*::before,*::after{transition-duration:1ms !important;animation-duration:1ms !important;
    animation-iteration-count:1 !important}
  html.axt-motion [data-reveal]{opacity:1}
  html.axt-motion [data-reveal="media"]{clip-path:none}
  html.axt-motion [data-split]{visibility:visible}
  .cue .cue-l{animation:none;opacity:.6}
}

/* hidden gagne toujours, meme sur un composant qui pose son propre display */
[hidden]{display:none !important}

/* ============================================================================
   ADDENDUM, 23 August 2026, session "les familles de produits"
   (agent Claude, sous-agent d'Arnaud). Ajoute en FIN DE FICHIER pour ne pas
   croiser les trois autres sessions ouvertes sur ce depot le meme jour.
   A fondre dans le corps de la feuille (juste sous le bloc "the Vehicles
   dropdown") a la prochaine passe tranquille.

   Pourquoi ces regles existent : le catalogue est passe de trois caravanes a
   deux familles de produits (onze modeles). Le panneau Buy du header n'est
   plus une rangee de vignettes, c'est une colonne par famille ; et huit des
   onze modeles n'ont AUCUNE photographie publiable, donc il fallait une
   plaque digne a la place d'un cadre casse.
============================================================================ */

/* UNE COLONNE PAR FAMILLE. auto-fit et rien d'autre : une troisieme famille
   ajoute une colonne, personne ne compte. */
.nav-fams{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));
  gap:clamp(18px,2.6vw,40px)}
/* l'en-tete d'une colonne parle la grammaire des kickers du site */
.nav-fam-h{font-size:.75rem;font-weight:600;letter-spacing:.12em;text-transform:uppercase;
  color:var(--ink-4);margin:0 0 10px;padding-bottom:8px;border-bottom:1px solid var(--grey-2)}
/* les vignettes se resserrent DANS une colonne : la regle 1080px de la feuille
   force trois colonnes sur .nav-cars, ce qui n'a plus de sens ici */
.nav-fam .nav-cars{grid-template-columns:repeat(auto-fit,minmax(136px,1fr))}
.nav-fam-all{margin-top:10px;font-size:.8125rem}
/* le panneau ne pousse JAMAIS son pied hors de l'ecran. Mesure du 23 aout : a
   1440x900 il fait 542 px avec deux familles et 733 avec trois, pour 844
   disponibles. Une quatrieme resserre les colonnes, donc les empile plus haut :
   la soupape est ici, et elle coute une regle au lieu d'une surveillance. */
.nav-panel-in{max-height:calc(100svh - var(--head) - 8px);overflow-y:auto}
.nav-car .cp{display:block}
/* le mot que l'attribut data-placeholder ne dit pas a l'oeil : un montant non
   valide ne doit jamais se lire comme un prix arrete */
.cq{display:block;font-style:normal;font-size:.625rem;font-weight:600;letter-spacing:.1em;
  text-transform:uppercase;color:var(--ink-4);margin-top:2px}

/* LA PLAQUE QUI REMPLACE UNE PHOTOGRAPHIE ABSENTE. C'est une vraie image (un
   svg genere par AXT.placeholderImage, data-URI), pour que toute page qui lit
   AXT.vehicles trouve un images.white et n'escamote pas le produit en silence.
   Ici on dit seulement qu'elle n'est PAS une photo : elle remplit sa case au
   lieu de flotter dedans, et elle ne zoome pas au survol. Elle disparait toute
   seule le jour ou une image publiable entre dans le catalogue. */
img.is-plate{object-fit:cover;border-radius:var(--r)}
.nav-car:hover img.is-plate{transform:none}

/* LA CARTE D'UNE GAMME, dans le panneau d'une famille qui en tient plusieurs
   (23 aout 2026). C'est la meme vignette qu'un modele, avec une ligne de plus :
   l'accroche que l'admin a ecrite sur la gamme. Deux lignes au maximum, parce
   qu'un panneau au survol se lit d'un coup d'oeil et qu'une gamme muette ne
   doit pas decaler celles qui parlent. Aucune famille n'a deux gammes
   aujourd'hui : cette regle ne dessine donc encore rien, et le jour ou une
   deuxieme entre dans l'admin elle n'attend personne. */
.nav-car .cd{font-size:.75rem;line-height:1.35;color:var(--ink-4);text-align:center;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}

/* ===========================================================================
   THE STAND BAR (28 August 2026)

   A page opened with `?sales=1` has no site navigation at all: the rep hands
   the tablet to a visitor, and a menu at that moment is an invitation to leave
   the sentence he is in the middle of. What is left is one way back, to the
   three doors of the launcher, and the mark so the visitor knows whose screen
   he is holding. Deliberately quiet: it must never compete with the page.
   =========================================================================== */
.stand-bar{position:sticky;top:0;z-index:80;display:flex;align-items:center;justify-content:space-between;
  gap:16px;padding:12px clamp(16px,4vw,40px);background:var(--white,#fff);
  border-bottom:1px solid var(--grey-2,#e8e8e8)}
.stand-back{display:inline-flex;align-items:center;gap:8px;border:1px solid var(--grey-2,#e8e8e8);
  border-radius:999px;padding:9px 18px;font-size:.68rem;font-weight:600;letter-spacing:.16em;
  text-transform:uppercase;color:var(--ink,#131313);text-decoration:none;background:var(--white,#fff);
  transition:border-color .2s ease,transform .12s ease}
.stand-back:hover{border-color:var(--ink,#131313)}
.stand-back:active{transform:scale(.96)}
.stand-mark{font-weight:800;letter-spacing:.18em;font-size:.95rem;color:var(--ink,#131313)}
/* The tablet is held, not scrolled with a mouse: give the thumb room. */
@media (max-width:900px){.stand-bar{padding:14px 18px}.stand-back{padding:11px 20px}}
