/* SYNOTACY — DROP 001 — "LE RELEVÉ"
   ============================================================================
   Direction: the embroidery is not on the page until the light finds it.
   Black thread on black cloth vanishes under flat light and returns when the
   garment moves; the site makes the visitor discover it the same way.

   THE MECHANIC is two images of the same frame stacked, crossfading on scroll.
   The lit layer is a PRE-BAKED file — transfer out = clamp((in*2.8-0.5)*2.0+0.5)
   exported with ImageMagick — not a live CSS filter, mask or blend. Measured
   acceptance, verified against the real exports:
       ls-yoke   bright-pixel area  0.774% -> 8.448%   (10.9x)
       proof     bright-pixel area  0.337% -> 6.946%   (20.6x)
   A live filter would vary by engine, cost per-frame paint, and be unverifiable
   without eyes. Baked files make the reveal a measurable artifact and reduce the
   animation to opacity, the cheapest compositor-only property there is.

   IT FIRES EXACTLY TWICE. Tiling every packshot at 200px and averaging local
   standard deviation over dark-cloth tiles:
       SYN-LS-001  23.6 -> 34.4  amplified   <- carries it
       SYN-JR-002  19.4 -> 24.1  amplified   <- carries it
       SYN-SH-003   6.9 ->  1.5  collapses
       SYN-CT-004   7.2 ->  2.2  collapses
       SYN-HT-005  18.7 ->  3.0  collapses
   Three of five garments have nothing to reveal. Applying the mechanic to all
   five ships three dead cells that no DOM assertion can detect.

   TWO DELIBERATE DEVIATIONS from the brief, both to remove fragility:
   1. The lift is driven by JS setting --p, not by animation-timeline:view().
      The brief had CSS drive opacity while JS drove the RELEVÉ readout — two
      sources of truth for one progress value, which desync. One source instead.
   2. The rail never uses mix-blend-mode. The brief's own adversarial critic
      called the blended rail the most fragile construction on the page. It sits
      on opaque paper, so the dark plate reads as full-bleed-minus-rail, which is
      the same picture with none of the risk.
   ========================================================================== */

*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body,h1,h2,h3,p,figure,ul{margin:0}
ul{padding:0;list-style:none}
img{display:block;max-width:100%}
button,input,select{font:inherit;color:inherit}
a{color:inherit;text-decoration:none}

:root{
  /* SIX VALUES. Not one is pure. Ratios computed against the WCAG formula. */
  --paper:#F7F5F0;   /* the only page ground. No alternating bands.           */
  --ink:#17161B;     /* all type, the button fill.    16.51:1 on paper        */
  --mute:#57534A;    /* micro register.                7.03:1 on paper        */
  --hover:#6E6A5F;   /* the entire hover vocabulary — dim, never brighten     */
  --deep:#0E0D10;    /* LA PREUVE only. The whole contrast budget, spent once */
  --white:#FFFFFF;   /* form fields only                                      */
  --bad:#6E2B28;     /* error text.                    7.51:1 on paper        */
  --hair:rgba(23,22,27,.11);

  --display:clamp(56px,15vw,210px);
  --statement:24px;
  --body:15px;
  --micro:11px;

  --gut:clamp(20px,4vw,56px);
  --ease:cubic-bezier(.20,0,0,1);

  --serif:"Bodoni Moda",Georgia,"Times New Roman",serif;
  --sans:"Archivo","Helvetica Neue",Arial,sans-serif;
}

body{
  background:var(--paper);color:var(--ink);
  font-family:var(--sans);font-size:var(--body);line-height:1.6;
  font-variation-settings:"wght" 420,"wdth" 100;
  font-optical-sizing:auto;
  letter-spacing:0;                /* the third tracking value: everything else */
  overflow-x:hidden;
}
p{max-width:62ch}                  /* ONE measure, every paragraph on the page */

/* The two uppercase registers. 0.16em on every 11px element, no exceptions.
   0.01em on the wordmark and only the wordmark — POSITIVE, because capitals
   were drawn for wide interletter space and tightening them is the clearest
   tell of a lowercase-display habit applied to a capital setting. There is no
   negative tracking anywhere in this file. */
.micro{
  font-size:var(--micro);line-height:15px;text-transform:uppercase;
  font-variation-settings:"wght" 500,"wdth" 88;
  letter-spacing:.16em;color:var(--mute);
}
.micro--ink{color:var(--ink)}
.stmt{
  font-family:var(--serif);font-size:var(--statement);line-height:1.3;
  font-variation-settings:"opsz" 24,"wght" 500;letter-spacing:0;
}
.num{font-variant-numeric:tabular-nums}

.sr{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
    clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;border:0}
.skip{position:absolute;left:-9999px;top:0;background:var(--ink);color:var(--paper);
      padding:12px 18px;z-index:200;font-size:var(--micro);letter-spacing:.16em;
      text-transform:uppercase}
.skip:focus{left:0}
:focus-visible{outline:2px solid var(--ink);outline-offset:3px}

/* ---------- LE VOILE ----------
   display:none by default and only shown once <html> has .js, so with JS
   disabled this element never exists and can never blank the page. */
#voile{display:none}
.js #voile{
  display:block;position:fixed;inset:0;background:var(--paper);z-index:120;
  pointer-events:none;opacity:1;transition:opacity .42s var(--ease);
}
#voile.gone{opacity:0}

/* ---------- page shell: main + the standing rail ---------- */
@media(min-width:1180px){
  .shell{display:grid;grid-template-columns:1fr 22%;align-items:start}
  /* a grid item is min-width:auto by default, so this column refused to shrink
     below its widest content and shoved the rail off the page */
  .shell>main{min-width:0}
}

/* ---------- 1. LE NOM ---------- */
.nom{
  min-height:100svh;display:flex;flex-direction:column;justify-content:center;
  position:relative;overflow:clip;padding:0 var(--gut);
}
.nom__mark{
  font-family:var(--serif);
  font-variation-settings:"opsz" 96,"wght" 500;
  font-size:var(--display);line-height:.84;letter-spacing:.01em;
  color:var(--ink);
  /* 106% of its CONTAINER, not of the viewport: at >=1180px this column is
     78% wide because the rail takes the rest, and sizing off vw overflowed the
     page by 426px. The S and the final Y are still cut by the column edges. */
  width:106%;margin-inline:-3%;text-align:center;
  transform:translateY(-18px);     /* optically centred, not mathematically */
}
.nom__meta{
  position:absolute;left:var(--gut);right:var(--gut);bottom:24px;
  display:flex;justify-content:space-between;gap:16px;flex-wrap:wrap;
}

/* ---------- the lift ----------
   No border, no radius, no shadow, no card. The packshot's own white ground is
   within a few luminance levels of --paper, so the frame is invisible and the
   garment floats on the page. */
.lift{position:relative;overflow:hidden;background:var(--paper)}
.lift img{width:100%;height:auto}
.lift__lit{position:absolute;inset:0;height:100%;object-fit:cover;opacity:1}
.js .lift__lit{opacity:var(--p,0)}   /* no JS => stays 1 => embroidery always shown */

/* ---------- 2. ÉTAT I ---------- */
.etat{padding:clamp(72px,10vw,150px) var(--gut)}
.etat__in{display:grid;gap:clamp(32px,5vw,64px)}
@media(min-width:900px){.etat__in{grid-template-columns:62fr 38fr;align-items:center}}
.etat__fig{max-width:700px;margin:0}
.etat__cap{margin-bottom:10px}
.etat__read{margin-top:10px}
.etat__rule{border:0;border-top:1px solid var(--hair);margin:26px 0}
.etat__body{margin:0 0 26px}

/* ---------- the form. Identical in all three ask instances. ---------- */
.f__lab{display:block;margin-bottom:8px}
.f__in,.f__sel{
  width:100%;height:52px;padding-inline:14px;
  background:var(--white);border:1px solid rgba(23,22,27,.22);border-radius:0;
  font-size:16px;              /* never below 16 or iOS zooms the page on focus */
  font-variation-settings:"wght" 420;
  transition:border-color .18s var(--ease);
}
.f__sel{padding-inline:10px}
.f__in:focus,.f__sel:focus{outline:none;border-color:var(--ink)}
.f__in::placeholder{color:var(--mute)}
.f__gap{height:18px}
.f__btn{
  width:100%;height:52px;background:var(--ink);color:var(--paper);
  border:0;border-radius:0;cursor:pointer;
  font-size:var(--micro);line-height:1;text-transform:uppercase;
  font-variation-settings:"wght" 500,"wdth" 88;letter-spacing:.16em;
  transition:background-color .18s var(--ease);
}
.f__btn:hover,.f__btn:active{background:var(--hover)}
.f__btn[disabled]{opacity:.5;cursor:default}
.f__help{margin-top:12px}
.f__err{margin-top:10px;color:var(--bad);min-height:15px}
.f__hp{position:absolute;left:-9999px;width:1px;height:1px;opacity:0}
.f__done{
  background:var(--ink);color:var(--paper);padding:20px;
  font-size:var(--micro);line-height:1.7;text-transform:uppercase;
  font-variation-settings:"wght" 500,"wdth" 88;letter-spacing:.16em;
}

/* ---------- 3. LE REGISTRE ----------
   Five ledger rows, not a grid of cards. The image side alternates down the page
   so it reads as a spread. Scale is ranked by hand — the flagship largest, the
   beanie smallest — because a uniform grid hands every piece equal weight, which
   is a merchandising decision nobody made. */
.reg{padding:clamp(48px,7vw,90px) 0 0}
.reg__lab{padding:0 var(--gut);margin-bottom:clamp(28px,4vw,52px)}
.row{
  display:grid;gap:clamp(20px,4vw,48px);align-items:center;
  padding:clamp(36px,5vw,72px) var(--gut);
  border-top:1px solid var(--hair);      /* full-bleed rule, no margin gap */
}
@media(min-width:860px){
  .row{grid-template-columns:46fr 50fr}
  .row--flip .row__fig{order:2}
  .row--flip .row__meta{order:1}
}
.row__fig{margin:0;background:var(--paper)}
/* one filter chain on every packshot so five pieces shot across different
   sessions read as one campaign */
/* MEASURED: all five packshots ship a PURE #FFFFFF ground (sampled via canvas
   on the live page), and the paper is #F7F5F0. That is an 8/10/15 per-channel
   delta — plainly visible — so each garment sat in a white rectangle instead of
   floating, which is the opposite of the intended effect.
   multiply maps white onto whatever is behind it (white x paper = paper), so the
   studio ground disappears exactly while the black garment is unaffected. This is
   why the packshots do not need re-exporting. */
.row__fig img{
  filter:grayscale(1) contrast(1.06);mix-blend-mode:multiply;
  width:var(--w,100%);height:auto;margin-inline:auto;
}
.row__sku{margin-bottom:10px}
.row__name{display:block;margin-bottom:14px;transition:color .18s var(--ease)}
.row__meta .micro+.micro{margin-top:5px}
.row:hover .row__name,.row:hover .row__sku{color:var(--hover)}

/* entrance is an upward unmask — a camera gesture, not the translateY+opacity
   fade that is the house style of every Shopify theme */
.rv{clip-path:inset(0 0 0 0)}
.js .rv{clip-path:inset(0 0 100% 0);transition:clip-path .9s var(--ease)}
.js .rv.in{clip-path:inset(0 0 0 0)}

/* ---------- 4. LA PREUVE ---------- */
.preuve{
  background:var(--deep);min-height:100svh;
  display:flex;flex-direction:column;justify-content:center;
  padding:clamp(48px,8vw,96px) var(--gut);gap:20px;
}
.preuve__fig{width:min(993px,88vw);margin:0 auto}
.preuve__bar{
  width:min(993px,88vw);margin:0 auto;
  display:flex;justify-content:space-between;gap:20px;flex-wrap:wrap;
}
.preuve .micro{color:#C9C6BE}      /*  9.90:1 on --deep */
.preuve .micro--ink{color:#F7F5F0} /* 17.78:1 on --deep */

/* ---------- 5. LA FICHE ---------- */
.fiche{padding:clamp(120px,18vw,240px) var(--gut)}
.fiche__rec{display:grid;grid-template-columns:108px 1fr;gap:10px 24px;max-width:560px}
.fiche__gloss{margin-top:28px;max-width:none}
.fiche__gloss span{display:block}
.fiche__cond{margin-top:clamp(48px,7vw,96px)}
@media(min-width:900px){.fiche__cond{margin-left:16%}} /* the one deliberate grid violation */
.fiche__cond p{margin:0;max-width:none}

/* ---------- 6. L'INSCRIPTION ----------
   The damask is ONE enormous crop at 6% — never tiled. Tiling is the single
   fastest route to wedding-invitation. */
.insc{
  position:relative;padding:clamp(72px,10vw,140px) var(--gut);
  border-top:1px solid var(--hair);overflow:hidden;
}
.insc::before{
  content:"";position:absolute;inset:0;z-index:0;
  background:url("../assets/art/damask.webp") center/auto 150% no-repeat;
  opacity:.06;pointer-events:none;
}
.insc__in{position:relative;z-index:1;max-width:520px;margin:0 auto}
.insc__stmt{margin:14px 0 26px}

/* ---------- 7. LE COLOPHON ---------- */
.colo{padding:clamp(40px,5vw,64px) var(--gut) 40px;border-top:1px solid var(--hair)}
.colo__grid{display:grid;gap:10px 32px;grid-template-columns:repeat(auto-fit,minmax(190px,1fr))}
.colo__grid a{display:inline-block;padding:16px 0;margin:-16px 0}

/* ---------- 8. LA COLONNE (desktop) / LA BARRE (mobile) ---------- */
.rail{display:none}
@media(min-width:1180px){
  .rail{
    display:flex;flex-direction:column;gap:18px;
    position:sticky;top:0;min-height:100svh;
    padding:28px var(--gut) 28px 28px;
    border-left:1px solid var(--hair);
    background:var(--paper);   /* opaque, always. never blends. */
  }
  .rail__sp{flex:1}
  .rail hr{border:0;border-top:1px solid var(--hair);margin:0;width:100%}
}
body{padding-bottom:56px}
@media(min-width:1180px){body{padding-bottom:0}}
.barre{
  position:fixed;left:0;right:0;bottom:0;z-index:100;
  background:var(--ink);color:var(--paper);
}
@media(min-width:1180px){.barre{display:none}}
.barre__top{display:flex;align-items:stretch}
.barre__open{
  flex:1;min-height:56px;background:none;border:0;cursor:pointer;color:inherit;
  font-size:var(--micro);text-transform:uppercase;letter-spacing:.16em;
  font-variation-settings:"wght" 500,"wdth" 88;text-align:left;padding:0 var(--gut);
}
.barre__x{width:56px;min-height:56px;background:none;border:0;cursor:pointer;
          color:inherit;font-size:18px;line-height:1}
.barre__form{padding:0 var(--gut) 20px}
.barre .micro{color:#C9C6BE}
.barre .f__in{margin-bottom:12px}

@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.01ms!important;transition-duration:.01ms!important}
  .js .rv{clip-path:none}
  .js .lift__lit{opacity:1}   /* show the embroidery rather than animate to it */
}
