/* Vitrine — landing template for local shops.
   Mobile-first. No build step. Every colour comes from a token so a site can be
   re-skinned from its JSON without touching this file. */

:root {
  --primary: #1F3A2F;
  --primary-ink: #F7F1E3;
  --accent: #7A5A1E;
  --bg: #FAF7F0;
  --surface: #FFFFFF;
  --fg: #1C1A16;
  --fg-soft: #5A5347;
  --border: #E4DBC9;
  /* Open / closed, sent / failed, and a field in error. Theme tokens since
     2026-09-23: as literals they could not follow a dark palette, and the
     contrast check in render.py could not measure them. */
  --ok: #15803d;
  --bad: #b91c1c;

  --radius: 14px;
  --radius-sm: 9px;
  --btn-radius: 999px;
  --shadow-1: 0 1px 2px rgba(17, 12, 10, .05), 0 1px 3px rgba(17, 12, 10, .04);
  --shadow-2: 0 10px 30px -12px rgba(17, 12, 10, .22);
  --card-shadow: none;

  /* Skins override these. Every value here is what the original single
     template used, so the classique profile needs no skin file at all. */
  --h1: clamp(2.5rem, 11vw, 4.75rem);
  --h1-lh: 1.08;
  --h2: clamp(1.75rem, 6.5vw, 2.6rem);
  --display-weight: 400;
  --display-tracking: -0.015em;
  --body-size: 17px;
  --body-lh: 1.65;
  --sec-pad: 48px;
  --sec-pad-wide: 48px;
  --eyebrow-tracking: .12em;

  --s1: 4px;  --s2: 8px;  --s3: 12px; --s4: 16px;
  --s5: 24px; --s6: 32px; --s7: 48px; --s8: 64px; --s9: 88px;

  --maxw: 1080px;
  --font-display: "Vitrine Display", Georgia, "Times New Roman", serif;
  --font-body: "Vitrine Sans", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
}

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font-family: var(--font-body);
  font-size: var(--body-size);
  line-height: var(--body-lh);
  -webkit-font-smoothing: antialiased;
}

img { max-width: 100%; height: auto; display: block; }

h1, h2, h3 {
  font-family: var(--font-display);
  font-weight: var(--display-weight);
  line-height: 1.08;
  letter-spacing: var(--display-tracking);
  margin: 0;
}
/* 1.08 is display leading for a one-line h1. Section titles wrap on a phone,
   and at 1.08 two lines of h2 sat 2px apart (fb-0007, back on h2 at the
   2026-09-23 round check). h3 is small enough to need body-ish leading. */
h2 { line-height: 1.15; }
h3 { line-height: 1.25; }

a { color: inherit; }

.wrap { width: 100%; max-width: var(--maxw); margin: 0 auto; padding: 0 var(--s5); }

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

:where(a, button, input, textarea, select):focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 2px;
  border-radius: 4px;
}

/* ---------- preview ribbon (demo pages only) ---------- */

.preview-note {
  background: #1c1917;
  color: #fafaf9;
  font-size: 14px;
  line-height: 1.45;
  padding: var(--s3) var(--s5);
  text-align: center;
}
.preview-note strong { color: #fde68a; font-weight: 600; }

/* ---------- header ---------- */

.site-head {
  position: sticky; top: 0; z-index: 40;
  background: color-mix(in srgb, var(--bg) 88%, transparent);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--border);
}
.site-head .wrap {
  display: flex; align-items: center; gap: var(--s4);
  min-height: 62px;
}
.brand {
  font-family: var(--font-display);
  font-size: 20px;
  /* It inherited body leading, so "Volaillerie Saint-" / "Vincent" wrapped
     with a paragraph's gap between the two halves of one name. */
  line-height: 1.2;
  letter-spacing: -0.01em;
  text-decoration: none;
  margin-right: auto;
}
.nav { display: none; gap: var(--s5); font-size: 15px; }
.nav a { text-decoration: none; color: var(--fg-soft); padding: var(--s2) 0; }
.nav a:hover { color: var(--fg); }
@media (min-width: 860px) { .nav { display: flex; } }

/* ---------- buttons ---------- */

.btn {
  display: inline-flex; align-items: center; justify-content: center;
  gap: var(--s2);
  min-height: 48px;
  padding: 0 var(--s5);
  border-radius: var(--btn-radius);
  border: 1px solid transparent;
  font: inherit; font-size: 16px; font-weight: 600;
  text-decoration: none;
  cursor: pointer;
  transition: transform .18s ease, background-color .18s ease, box-shadow .18s ease;
}
.btn svg { width: 19px; height: 19px; flex: 0 0 auto; }
.btn:active { transform: scale(.97); }
.btn-primary { background: var(--primary); color: var(--primary-ink); box-shadow: var(--shadow-1); }
.btn-primary:hover { background: color-mix(in srgb, var(--primary) 88%, #000); }
.btn-ghost { background: var(--surface); color: var(--fg); border-color: var(--border); }
.btn-ghost:hover { border-color: color-mix(in srgb, var(--fg) 30%, var(--border)); }
.btn-sm { min-height: 42px; font-size: 15px; padding: 0 var(--s4); }
@media (prefers-reduced-motion: reduce) { .btn { transition: none; } .btn:active { transform: none; } }

/* ---------- hero ---------- */

.hero { padding: var(--s7) 0 var(--s6); }
.hero-grid { display: grid; gap: var(--s6); grid-template-columns: 1fr; align-items: start; }
@media (min-width: 980px) {
  .hero { padding: var(--s8) 0 var(--s7); }
  .hero-grid { grid-template-columns: minmax(0, 1.55fr) minmax(280px, .95fr); gap: var(--s7); }
}

/* The card repeats what the hours section says further down. On a phone that
   would just be a second scroll of the same thing, so it only appears once
   there is a column standing empty next to the headline. */
.hero-card { display: none; }
@media (min-width: 980px) {
  .hero-card {
    display: block;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: var(--s5);
    box-shadow: var(--shadow-2);
  }
  .hero-card-row { display: flex; gap: var(--s4); margin: 0 0 var(--s4); font-size: 16px; }
  .hero-card-row .k {
    flex: 0 0 92px;
    font-size: 12px; letter-spacing: .09em; text-transform: uppercase;
    font-weight: 600; color: var(--accent); padding-top: 4px;
  }
  .hero-card-row .v { color: var(--fg); font-variant-numeric: tabular-nums; }
  .hero-card-row .v a { text-decoration: none; font-weight: 600; }
  .hero-card .btn { width: 100%; }
}
.hero .eyebrow {
  font-size: 13px; font-weight: 600; letter-spacing: var(--eyebrow-tracking); text-transform: uppercase;
  color: var(--accent); margin: 0 0 var(--s4);
}
.hero h1 {
  font-size: var(--h1); line-height: var(--h1-lh);
  margin-bottom: var(--s4);
}
.hero .lede {
  font-size: clamp(1.06rem, 4vw, 1.3rem);
  color: var(--fg-soft);
  max-width: 34ch;
  margin: 0 0 var(--s5);
}
.hero-actions { display: flex; flex-wrap: wrap; gap: var(--s3); }
.hero-actions .btn { flex: 1 1 auto; }
@media (min-width: 640px) { .hero-actions .btn { flex: 0 0 auto; } }

.status-line {
  display: inline-flex; align-items: center; gap: var(--s2);
  margin-top: var(--s5);
  font-size: 15px; font-weight: 600;
}
.status-dot { width: 9px; height: 9px; border-radius: 50%; background: var(--fg-soft); flex: 0 0 auto; }
.status-open   .status-dot { background: var(--ok); }
.status-closed .status-dot { background: var(--bad); }
.status-open   { color: var(--ok); }
.status-closed { color: var(--bad); }
.status-line .status-detail { color: var(--fg-soft); font-weight: 400; }

/* ---------- sections ---------- */

section { padding: var(--sec-pad) 0; }
section + section { border-top: 1px solid var(--border); }
.section-title { font-size: var(--h2); margin-bottom: var(--s5); }
.section-intro { color: var(--fg-soft); max-width: 60ch; margin: calc(var(--s5) * -1 + var(--s3)) 0 var(--s6); }

/* ---------- services ---------- */

.cards { display: grid; gap: var(--s4); grid-template-columns: 1fr; }
@media (min-width: 700px) { .cards { grid-template-columns: repeat(2, 1fr); gap: var(--s5); } }
@media (min-width: 980px) { .cards.cards-3 { grid-template-columns: repeat(3, 1fr); } }

.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: var(--s5);
}
.card .icon {
  width: 42px; height: 42px; border-radius: 11px;
  display: grid; place-items: center;
  background: color-mix(in srgb, var(--accent) 14%, var(--surface));
  color: var(--accent);
  margin-bottom: var(--s4);
}
.card .icon svg { width: 22px; height: 22px; }
.card h3 { font-size: 1.25rem; margin-bottom: var(--s2); }
.card p { margin: 0; color: var(--fg-soft); font-size: 16px; }

/* ---------- hours ---------- */

.hours-layout { display: grid; gap: var(--s6); grid-template-columns: 1fr; }
@media (min-width: 880px) { .hours-layout { grid-template-columns: 1fr 1fr; gap: var(--s7); align-items: start; } }

.hours { width: 100%; border-collapse: collapse; font-variant-numeric: tabular-nums; }
.hours th, .hours td { text-align: left; padding: var(--s3) 0; border-bottom: 1px solid var(--border); }
.hours th { font-weight: 500; color: var(--fg-soft); }
.hours td { text-align: right; font-weight: 500; }
.hours tr.today th, .hours tr.today td { color: var(--fg); font-weight: 700; }
.hours tr:last-child th, .hours tr:last-child td { border-bottom: 0; }
.hours-note { font-size: 15px; color: var(--fg-soft); margin-top: var(--s4); }

.map-frame {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--surface);
}
.map-frame iframe { width: 100%; height: 300px; border: 0; display: block; }
.addr { font-style: normal; margin: 0 0 var(--s4); font-size: 17px; line-height: 1.6; }
.addr .label { display: block; font-size: 13px; letter-spacing: .1em; text-transform: uppercase; color: var(--accent); font-weight: 600; margin-bottom: var(--s2); }

/* ---------- photos ---------- */

.gallery { display: grid; gap: var(--s3); grid-template-columns: repeat(2, 1fr); }
@media (min-width: 760px) { .gallery { grid-template-columns: repeat(3, 1fr); gap: var(--s4); } }
.gallery figure { margin: 0; border-radius: var(--radius); overflow: hidden; background: var(--surface); }
.gallery img { aspect-ratio: 4 / 3; object-fit: cover; width: 100%; }
/* Two up on a phone, so an odd count left the last frame alone on its row
   with a hole beside it: three of the four gallery pages at 390 (2026-09-23).
   The last one takes the whole row instead, at half the height a doubled 4/3
   would give it. CSS rather than a count rule, because the count of a
   customer's photos is theirs (see build_portfolio). */
@media (max-width: 759px) {
  .gallery > :last-child:nth-child(odd) { grid-column: span 2; }
  .gallery > .photo-slot:last-child:nth-child(odd),
  .gallery > figure:last-child:nth-child(odd) img { aspect-ratio: 8 / 3; }
}

/* ⚠ `align-content` as well as `place-items`. The slot has TWO children (the
   camera and its label) and a grid's implicit rows STRETCH by default, so
   without this the two rows split the box in half: the icon floats in the top
   half and the caption in the bottom, with a void between them that reads as a
   broken image rather than an empty frame. `.planche-slot` had it from the
   start, which is why the portfolio slots never looked wrong. */
.photo-slot {
  aspect-ratio: 4 / 3;
  border: 1px dashed color-mix(in srgb, var(--fg) 28%, var(--border));
  border-radius: var(--radius);
  display: grid; place-items: center; align-content: center; text-align: center;
  padding: var(--s4);
  color: var(--fg-soft);
  font-size: 14px;
  background: color-mix(in srgb, var(--surface) 70%, var(--bg));
}
.photo-slot svg { width: 26px; height: 26px; margin: 0 auto var(--s2); display: block; opacity: .55; }

/* ---------- reviews ---------- */

.quotes { display: grid; gap: var(--s4); grid-template-columns: 1fr; }
@media (min-width: 820px) { .quotes { grid-template-columns: repeat(2, 1fr); gap: var(--s5); } }
.quote {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); padding: var(--s5);
}
.quote blockquote { margin: 0 0 var(--s4); font-size: 17px; }
.quote figcaption { font-size: 14px; color: var(--fg-soft); }
.stars { display: flex; gap: 2px; color: var(--accent); margin-bottom: var(--s3); }
.stars svg { width: 17px; height: 17px; }

/* ---------- contact form ---------- */

.contact-layout { display: grid; gap: var(--s6); grid-template-columns: 1fr; }
@media (min-width: 880px) { .contact-layout { grid-template-columns: 5fr 6fr; gap: var(--s7); align-items: start; } }

.field { margin-bottom: var(--s4); }
.field label { display: block; font-size: 15px; font-weight: 600; margin-bottom: var(--s2); }
.field .hint { display: block; font-weight: 400; color: var(--fg-soft); font-size: 14px; margin-top: 2px; }
.field input, .field textarea {
  width: 100%;
  min-height: 48px;
  padding: var(--s3) var(--s4);
  font: inherit; font-size: 16px;
  color: var(--fg);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
}
.field textarea { min-height: 140px; resize: vertical; }
.field input:focus, .field textarea:focus { border-color: var(--accent); }
.field .err { display: none; color: var(--bad); font-size: 14px; margin-top: var(--s2); font-weight: 500; }
.field.invalid .err { display: block; }
.field.invalid input, .field.invalid textarea { border-color: var(--bad); }

.hp { position: absolute; left: -9999px; opacity: 0; height: 0; }

.form-note { font-size: 14px; color: var(--fg-soft); margin: var(--s4) 0 0; }
.form-status { margin: var(--s4) 0 0; font-size: 16px; font-weight: 600; }
.form-status.ok  { color: var(--ok); }
.form-status.bad { color: var(--bad); }

/* ---------- footer ---------- */

.site-foot {
  border-top: 1px solid var(--border);
  padding: var(--s6) 0 calc(var(--s8) + env(safe-area-inset-bottom));
  font-size: 15px;
  color: var(--fg-soft);
}
.foot-grid { display: grid; gap: var(--s5); grid-template-columns: 1fr; }
@media (min-width: 760px) { .foot-grid { grid-template-columns: repeat(3, 1fr); } }
.site-foot h4 { font-family: var(--font-body); font-size: 14px; letter-spacing: .1em; text-transform: uppercase; color: var(--fg); margin: 0 0 var(--s3); }
.site-foot a { text-decoration: none; }
.site-foot a:hover { text-decoration: underline; }
/* The one footer link that goes somewhere on the page, so it has to look like
   a link. After `.site-foot a`, which it has to beat. */
.foot-hours a { text-decoration: underline; text-underline-offset: 3px; }
.colophon { margin-top: var(--s6); padding-top: var(--s4); border-top: 1px solid var(--border); font-size: 13px; }

/* ---------- sticky mobile action bar ---------- */

.action-bar {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 50;
  display: flex; gap: var(--s2);
  padding: var(--s3) var(--s4) calc(var(--s3) + env(safe-area-inset-bottom));
  background: color-mix(in srgb, var(--bg) 94%, transparent);
  backdrop-filter: blur(10px);
  border-top: 1px solid var(--border);
}
.action-bar .btn { flex: 1 1 0; min-width: 0; }
.action-bar .btn span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
@media (min-width: 860px) { .action-bar { display: none; } .site-foot { padding-bottom: var(--s7); } }

/* ---------- entrance motion (subtle, opt-out) ---------- */

@media (prefers-reduced-motion: no-preference) {
  .reveal { opacity: 0; transform: translateY(10px); transition: opacity .45s ease-out, transform .45s ease-out; }
  .reveal.in { opacity: 1; transform: none; }
}

/* ==========================================================================
   Section library. Everything below is shared by every skin; a skin file
   changes the variables above and adds its own one structural device.
   ========================================================================== */

@media (min-width: 900px) { section { padding: var(--sec-pad-wide) 0; } }

/* ---------- hero variants ---------- */

.hero-band { margin-top: var(--s6); }
.hero-band img { width: 100%; aspect-ratio: 21 / 9; max-height: 460px; object-fit: cover; }
/* The empty state is deliberately shorter than a real photo would be. At 21/9
   across a desktop viewport an empty dashed box reads as a broken image the
   size of a billboard.
   ⚠ `width: 100%` is what makes the height cap a cap rather than a WIDTH.
   Without it the box is sized from `max-height` back through the aspect ratio
   -- 300px tall means 686px wide -- so it sat left-aligned against the viewport
   edge, half the width of the band a real photo fills, which is exactly what
   made it read as broken. `align-content` for the same reason as `.photo-slot`
   above. */
.hero-slot {
  aspect-ratio: 16 / 7; max-height: 300px; width: 100%;
  display: grid; place-items: center; align-content: center; text-align: center; gap: var(--s2);
  border: 1px dashed color-mix(in srgb, var(--fg) 26%, var(--border));
  background: color-mix(in srgb, var(--surface) 70%, var(--bg));
  color: var(--fg-soft); font-size: 14px; padding: var(--s4);
}
.hero-slot svg { width: 28px; height: 28px; opacity: .55; }

/* An empty band is held to the page measure, and to a placeholder's height.
   Full-bleed is the media hero's device and a photograph should keep it, but an
   empty frame taking the same room is a 1425x300 dashed void running edge to
   edge past every other block on the page -- the one thing with no side gutters,
   which is exactly what makes it read as a broken image rather than as a frame
   waiting for a picture. Shrinking it is the same call base.css already made
   with max-height, carried the rest of the way.
   ⚠ `aspect-ratio: auto` and `max-height: none` both have to go, or the ratio
   fights min-height and the box springs back to 300px. */
.hero-band-empty { padding: 0 var(--s5); }
.hero-band-empty .hero-slot {
  aspect-ratio: auto; max-height: none; min-height: 148px;
  /* Minus the gutters, not just `--maxw`. `.wrap` puts its padding INSIDE its
     max-width, so a 1080 box centred in the band lines up with the wrap's border
     edge and comes out 24px wider on each side than the `.photo-slot` frames in
     the gallery. Two dashed placeholders on one page at two different widths is
     worse than either width on its own. */
  max-width: calc(var(--maxw) - var(--s5) * 2); margin: 0 auto;
  border-radius: var(--radius);
}

.hero-typographic .hero-rule {
  display: block; width: 64px; height: 1px;
  background: color-mix(in srgb, var(--fg) 45%, transparent);
  margin: var(--s5) 0;
}
.hero-editorial .since { color: var(--fg-soft); font-weight: 500; }
.hero-editorial .status-inline { margin-top: var(--s4); }
.hero-today {
  margin: var(--s2) 0 var(--s5);
  color: var(--fg-soft); font-size: 15px;
  font-variant-numeric: tabular-nums;
}
.hero-today strong { color: var(--fg); }

/* ---------- services price line ---------- */

.card-price {
  margin: var(--s3) 0 0;
  font-family: var(--font-display);
  font-size: 18px; font-weight: 600; color: var(--fg);
  font-variant-numeric: tabular-nums;
}

/* ---------- menu (la carte) ---------- */

.menu { display: grid; gap: var(--s6); grid-template-columns: 1fr; }
@media (min-width: 820px) { .menu { grid-template-columns: repeat(2, 1fr); gap: var(--s6) var(--s7); } }
/* A single group in a two-column grid leaves half the page empty and stretches
   the price leaders across it. One group gets one centred column. */
.menu-1 { grid-template-columns: 1fr; max-width: 620px; margin-inline: auto; }
@media (min-width: 820px) { .menu-1 { grid-template-columns: 1fr; } }
.menu-group h3 {
  font-size: 1.15rem; margin-bottom: var(--s3);
  padding-bottom: var(--s2); border-bottom: 1px solid var(--border);
}
.menu-list, .products, .brands { list-style: none; margin: 0; padding: 0; }
.menu-item { padding: var(--s3) 0; }
.menu-item, .p-head {
  display: flex; align-items: baseline; gap: var(--s2); flex-wrap: wrap;
}
.mi-name, .p-name { font-weight: 600; }
.mi-leader {
  flex: 1 1 24px; min-width: 24px; align-self: center;
  border-bottom: 2px dotted var(--border);
}
.mi-price {
  font-family: var(--font-display); font-weight: 600;
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.mi-desc, .p-desc {
  flex: 1 1 100%; margin: var(--s1) 0 0;
  color: var(--fg-soft); font-size: 15px;
}

/* ---------- products (spécialités) ---------- */

.product { padding: var(--s4) 0; border-bottom: 1px solid var(--border); }
.product:last-child { border-bottom: 0; }
.p-badge {
  font-size: 12px; font-weight: 600; letter-spacing: .04em;
  padding: 3px var(--s2); border-radius: var(--radius-sm);
  background: color-mix(in srgb, var(--accent) 15%, var(--surface));
  color: var(--accent); white-space: nowrap;
}

/* ---------- steps (le parcours) ---------- */

.steps { list-style: none; margin: 0; padding: 0; counter-reset: none; }
.step { display: flex; gap: var(--s4); padding-bottom: var(--s5); position: relative; }
.step:last-child { padding-bottom: 0; }
.step-n {
  /* Width and height are both explicit: on desktop the list turns into a
     column flex and a flex-basis would become the HEIGHT, which stretched the
     numerals into ellipses. */
  flex: 0 0 auto; width: 40px; height: 40px;
  display: grid; place-items: center;
  border: 2px solid var(--accent); border-radius: 50%;
  color: var(--accent); font-weight: 700; font-size: 15px;
  background: var(--bg);
  font-variant-numeric: tabular-nums;
}
/* The connector runs behind the numerals and stops at the last one. */
.step:not(:last-child)::before {
  content: ""; position: absolute; left: 19px; top: 40px; bottom: 8px;
  width: 2px; background: color-mix(in srgb, var(--accent) 35%, var(--border));
}
/* Headings inherit the display leading, 1.08, which is right for an h1 and much
   too tight once a 17px h3 wraps: on a phone every one of these titles wraps,
   and the two lines all but touch. Both sections are absent from `classique`,
   so the pixel contract does not see this. */
.step-b h3 { font-size: 1.15rem; line-height: 1.25; margin-bottom: var(--s2); }
.step-b p { margin: 0; color: var(--fg-soft); font-size: 16px; }
@media (min-width: 900px) {
  .steps { display: flex; gap: var(--s5); }
  .step { flex: 1 1 0; flex-direction: column; padding-bottom: 0; }
  .step:not(:last-child)::before {
    left: 48px; right: -24px; top: 19px; bottom: auto; width: auto; height: 2px;
  }
}

/* ---------- portfolio (la planche) ---------- */

.s-portfolio { overflow: hidden; }
.planche {
  display: grid; gap: 2px; margin-top: var(--s5);
  grid-template-columns: repeat(2, 1fr);
  grid-auto-flow: dense;
}
@media (min-width: 760px) { .planche { grid-template-columns: repeat(4, 1fr); } }
.planche-tile { margin: 0; position: relative; overflow: hidden; }
.planche-tile img { width: 100%; aspect-ratio: 4 / 5; object-fit: cover; }
.planche-tile:first-child { grid-column: span 2; grid-row: span 2; }
.planche-tile figcaption {
  position: absolute; left: 0; right: 0; bottom: 0;
  padding: var(--s3) var(--s4);
  font-size: 13px; color: #fff;
  background: linear-gradient(to top, rgba(0, 0, 0, .62), transparent);
}
.planche-slot {
  aspect-ratio: 4 / 5;
  display: grid; place-items: center; align-content: center; gap: var(--s2);
  text-align: center; padding: var(--s4);
  border: 1px dashed color-mix(in srgb, var(--fg) 26%, var(--border));
  background: color-mix(in srgb, var(--surface) 70%, var(--bg));
  color: var(--fg-soft); font-size: 13px;
}
.planche-slot:first-child { grid-column: span 2; grid-row: span 2; }
.planche-slot svg { width: 26px; height: 26px; opacity: .5; }
/* A plate with no photograph in it at all (build_portfolio adds the class).
   Held to the page measure and square tiles, the same call .hero-band-empty
   makes: full-bleed empty frames on ylann were ~1100px of dashed void on a
   phone (2026-09-23). The box matches .wrap: max-width with the padding
   inside it. The 2x2 tile's cap is phone-only: from 760px it shares its two
   rows with tiles 2 to 5, and a cap there would leave it short of them. */
.planche-empty { max-width: var(--maxw); margin-inline: auto; padding: 0 var(--s5); }
.planche-empty .planche-slot { aspect-ratio: 1 / 1; }
@media (max-width: 759px) {
  .planche-empty .planche-slot:first-child { aspect-ratio: auto; height: 260px; }
}

/* ---------- trust (garanties) ---------- */

.trust { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s5); }
@media (min-width: 820px) { .trust { grid-template-columns: repeat(2, 1fr); gap: var(--s5) var(--s7); } }
.trust-row { display: flex; gap: var(--s4); align-items: flex-start; }
.t-icon {
  flex: 0 0 40px; height: 40px; border-radius: var(--radius-sm);
  display: grid; place-items: center;
  background: color-mix(in srgb, var(--accent) 13%, var(--surface));
  color: var(--accent);
}
.t-icon svg { width: 21px; height: 21px; }
.trust-row h3 { font-size: 1.1rem; line-height: 1.25; margin-bottom: var(--s2); }
.trust-row p { margin: 0; color: var(--fg-soft); font-size: 16px; }

/* ---------- faq ---------- */

.faq { max-width: 68ch; }
.faq-item { border-bottom: 1px solid var(--border); }
.faq-item summary {
  cursor: pointer; list-style: none;
  padding: var(--s4) 0; padding-right: var(--s6);
  font-weight: 600; position: relative;
}
.faq-item summary::-webkit-details-marker { display: none; }
.faq-mark {
  position: absolute; right: 4px; top: 50%; width: 12px; height: 2px;
  background: var(--accent); transform: translateY(-50%);
}
.faq-mark::after {
  content: ""; position: absolute; inset: 0;
  background: var(--accent); transform: rotate(90deg);
  transition: opacity .18s ease;
}
.faq-item[open] .faq-mark::after { opacity: 0; }
.faq-a { padding: 0 0 var(--s4); color: var(--fg-soft); }
@media (prefers-reduced-motion: reduce) { .faq-mark::after { transition: none; } }

/* ---------- brands ---------- */

.brands { display: flex; flex-wrap: wrap; gap: var(--s2); }
.brands li {
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  padding: var(--s2) var(--s4); font-size: 15px; font-weight: 500;
  background: var(--surface);
}

/* ---------- cta band ---------- */

.cta-band {
  background: var(--primary);
  color: var(--primary-ink);
  text-align: center;
  border-top: 0;
}
.cta-band h2 { font-size: var(--h2); margin-bottom: var(--s3); }
.cta-band p { margin: 0 auto var(--s5); max-width: 44ch; opacity: .88; }
.btn-oncta {
  background: var(--primary-ink); color: var(--primary);
  border-color: var(--primary-ink);
}
.btn-oncta:hover { background: color-mix(in srgb, var(--primary-ink) 88%, var(--primary)); }
/* `.cta-band .cta-num`, not `.cta-num`: `.cta-band p` above outranks a single
   class, so its bottom margin and .88 opacity won and the number sat ~8px
   under the button (2026-09-23). */
.cta-band .cta-num {
  margin: var(--s4) auto 0; font-family: var(--font-display);
  font-size: 1.4rem; font-variant-numeric: tabular-nums; opacity: 1;
}

/* ---------- signature hero (profiles.SIGNATURES) ----------
   The headline column and the signature's composition side by side from
   900px, stacked below it. The composition is the signature's to draw
   (template/signatures/<name>/); this only gives it a column. */

.hero-sig-grid { display: grid; gap: var(--s6); grid-template-columns: 1fr; align-items: center; }
@media (min-width: 900px) {
  .hero-sig-grid { grid-template-columns: minmax(0, 1.1fr) minmax(0, .9fr); gap: var(--s7); }
}
.hero-art { min-width: 0; }
.hero-art .sa-photo { width: 100%; height: auto; display: block; }

/* The band's second button (cta_band.link): same size, drawn in outline so
   the call stays the first choice. */
.btn-oncta-alt {
  /* The band's own text colour, whatever a signature painted the band:
     primary-ink on the default band, dark ink on a light card. */
  background: transparent; color: inherit;
  border-color: color-mix(in srgb, currentColor 60%, transparent);
  margin-left: var(--s2);
}
.btn-oncta-alt:hover { background: color-mix(in srgb, currentColor 10%, transparent); }

/* Galerie — the boutique skin. Few words, well weighted, the object speaks.
   Device: a hairline frame inset from the viewport edge that turns the page
   into a display case, and rectangles everywhere instead of pills. */

:root {
  --h1: clamp(2.5rem, 10vw, 4.8rem);
  --h1-lh: 1.04;
  --h2: clamp(1.6rem, 5.5vw, 2.5rem);
  --display-weight: 500;
  --display-tracking: 0;
  --body-size: 16.5px;
  --body-lh: 1.75;
  --radius: 2px;
  --radius-sm: 2px;
  --btn-radius: 2px;
  --sec-pad: 64px;
  --sec-pad-wide: 96px;
  --shadow-1: none;
  --shadow-2: none;
  --card-shadow: none;
  --eyebrow-tracking: .18em;
  --maxw: 1120px;
}

.btn-primary { box-shadow: none; }
.card, .quote { box-shadow: none; }
.section-intro { max-width: 58ch; }
.hero .lede { max-width: 42ch; }

/* The frame. Fixed, ignores pointer events, and only on screens wide enough
   that 12px of margin is not eating the content. */
@media (min-width: 900px) {
  body::after {
    content: "";
    position: fixed; inset: 12px;
    border: 1px solid color-mix(in srgb, var(--fg) 16%, transparent);
    pointer-events: none;
    z-index: 60;
  }
}

/* Hairline-ruled vitrine: images sit in a grid of thin lines, captions below.
   ⚠ The rules are drawn by the TILES, not by the grid. Painting the container
   and letting each tile punch a --bg hole in it looks identical while the grid
   is full, and paints a solid block in any cell that has no tile. The gallery
   is 2-up on a phone and 3-up from 760px, so only a multiple of six is full at
   both widths: beryl's three slots came out as two frames and one grey
   rectangle at 390, which reads as a photograph that failed to load rather than
   as an empty vitrine. Each tile ringing itself gives the same 1px line in the
   1px gap, and an empty cell now paints nothing. */
.gallery { gap: 1px; }
.gallery figure, .gallery .photo-slot {
  background: var(--bg);
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--fg) 12%, transparent);
}
.gallery img { aspect-ratio: 1 / 1; }
/* The tile's ring IS the rule here, so an empty frame drops the dashed border
   base.css gives it: both drew, a dashed line inside a solid hairline. */
.gallery .photo-slot { border: 0; }
/* The lone last photo on a phone spans the row (base.css): 2/1 keeps it the
   height of the square beside it, where base's 8/3 would come out shorter. */
@media (max-width: 759px) {
  .gallery > figure:last-child:nth-child(odd) img { aspect-ratio: 2 / 1; }
}

.brands li { background: transparent; border-color: color-mix(in srgb, var(--fg) 20%, transparent); }
.product { border-bottom-color: color-mix(in srgb, var(--fg) 12%, transparent); }

/* Signature: Écrin. A jeweller's case: the page is ivory paper with wide
   margins, and the two places that hold something precious (the hero and the
   list of what is done in the shop) open onto bottle-green velvet inside a
   gold double fillet. Section titles are Garamond, flush left, reached by a
   hairline that runs in from the edge of the page like the fillet of a case.
   Nothing is drawn: velvet, satin quilting, fillets and lettering only. */

@font-face { font-family: 'Ecrin Serif'; font-style: normal; font-weight: 500; font-display: swap;
  src: url('fonts/cormorant-garamond-500.woff2') format('woff2'); }
@font-face { font-family: 'Ecrin Serif'; font-style: italic; font-weight: 500; font-display: swap;
  src: url('fonts/cormorant-garamond-500i.woff2') format('woff2'); }
@font-face { font-family: 'Ecrin Sans'; font-style: normal; font-weight: 400; font-display: swap;
  src: url('fonts/jost-400.woff2') format('woff2'); }
@font-face { font-family: 'Ecrin Sans'; font-style: normal; font-weight: 500; font-display: swap;
  src: url('fonts/jost-500.woff2') format('woff2'); }

:root {
  --font-display: 'Ecrin Serif', 'Cormorant Garamond', Garamond, Georgia, serif;
  --font-body: 'Ecrin Sans', 'Futura', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --display-weight: 500;
  --display-tracking: -0.005em;
  --h1: clamp(2.75rem, 11.5vw, 5.2rem);
  --h1-lh: 1.1;
  --h2: clamp(2.1rem, 8.4vw, 3.3rem);
  --body-size: 16.5px;
  --body-lh: 1.7;
  --radius: 0;
  --radius-sm: 0;
  --btn-radius: 1px;
  --sec-pad: 64px;
  --sec-pad-wide: 104px;
  --eyebrow-tracking: .24em;

  /* The case. Velvet is the theme's primary taken deeper; gold is only ever
     drawn on velvet or as a hairline, never as text on the ivory page (the
     page's gold text is the theme's darker `accent`). Measured on --velvet:
     --gold-text 7.6:1, --ivory 12.9:1, --ivory-soft 8.4:1. */
  --velvet: color-mix(in srgb, var(--primary) 78%, #000);
  --velvet-lift: color-mix(in srgb, var(--primary) 92%, #fff);
  --gold: #B8964F;
  --gold-hi: #E7D29E;
  --gold-text: #D9C088;
  --ivory: #F4ECDA;
  --ivory-soft: #CFC4AB;
  --tag: #F6EFDF;
  --hair: color-mix(in srgb, var(--gold) 70%, transparent);
  /* Velvet nap: a fine fractal grain, drawn once as an SVG and tiled. */
  --nap: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .55 0'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* ---- chrome ---- */
.preview-note { background: #13241D; color: #F4ECDA; }
.preview-note strong { color: var(--gold-hi); }
.site-head { border-bottom-color: color-mix(in srgb, var(--gold) 30%, var(--border)); }
.brand { font-style: italic; font-size: 26px; letter-spacing: 0; line-height: 1.15; }
.nav a { font-size: 13px; letter-spacing: .16em; text-transform: uppercase; }
@media (min-width: 900px) {
  body::after { border-color: color-mix(in srgb, var(--gold) 38%, transparent); }
}

.btn { font-weight: 500; letter-spacing: .03em; }
.btn-primary { background: var(--primary); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--gold) 40%, transparent); }
.btn-primary:hover { background: var(--velvet); }
.btn-ghost { background: transparent; border-color: color-mix(in srgb, var(--fg) 34%, transparent); }
.btn-ghost:hover { border-color: var(--fg); }

/* ---- hero ---- */
.hero-sig { padding-top: var(--s7); padding-bottom: var(--s5); }
.hero .eyebrow { display: flex; align-items: center; gap: var(--s3); font-weight: 500; font-size: 12.5px; }
.hero .eyebrow::before { content: ""; width: 28px; height: 1px; background: var(--accent); flex: 0 0 auto; }
.hero h1 { margin-bottom: var(--s5); max-width: 13ch; }
.hero .lede { font-size: clamp(1.02rem, 3.9vw, 1.16rem); max-width: 40ch; }
@media (min-width: 900px) {
  .hero-sig { padding-top: var(--s9); padding-bottom: var(--s9); }
  .hero-sig-grid { grid-template-columns: minmax(0, 1fr) minmax(0, .92fr); gap: var(--s9); }
}

.ecrin { margin: var(--s3) 0 0; display: grid; }
.ecrin .sa-photo { margin-bottom: var(--s4); box-shadow: 0 0 0 1px var(--hair); }

.ecrin-case {
  position: relative;
  background: var(--velvet);
  box-shadow:
    0 1px 0 color-mix(in srgb, var(--gold) 45%, transparent),
    0 34px 50px -34px rgba(16, 28, 22, .75),
    0 10px 18px -12px rgba(16, 28, 22, .35);
  isolation: isolate;
}
/* The gold double fillet, over lid and bed alike. */
.ecrin-case::before, .ecrin-case::after {
  content: ""; position: absolute; pointer-events: none; z-index: 2;
}
.ecrin-case::before { inset: 9px; border: 1px solid var(--hair); }
.ecrin-case::after { inset: 13px; border: 1px solid color-mix(in srgb, var(--gold) 32%, transparent); }

/* The lid: quilted satin, two diagonal seams and a sheen, seen from the front. */
.ecrin-lid {
  height: clamp(64px, 17vw, 88px);
  background:
    linear-gradient(180deg, rgba(255, 255, 255, .10), rgba(0, 0, 0, .22)),
    repeating-linear-gradient(45deg, transparent 0 17px, rgba(0, 0, 0, .28) 17px 18px, rgba(255, 255, 255, .05) 18px 19px),
    repeating-linear-gradient(-45deg, transparent 0 17px, rgba(0, 0, 0, .28) 17px 18px, rgba(255, 255, 255, .05) 18px 19px),
    var(--velvet-lift);
  border-bottom: 1px solid var(--gold);
  box-shadow: 0 6px 10px -4px rgba(0, 0, 0, .55);
  position: relative; z-index: 1;
}

/* The bed: velvet, lit from the top left. */
.ecrin-bed {
  display: grid; justify-items: center; text-align: center;
  padding: clamp(34px, 8vw, 48px) 28px clamp(76px, 18vw, 92px);
  background:
    radial-gradient(120% 80% at 22% 0%, rgba(255, 255, 255, .10), transparent 60%),
    radial-gradient(90% 70% at 50% 110%, rgba(0, 0, 0, .35), transparent 70%),
    var(--nap),
    var(--velvet);
  background-size: auto, auto, 160px 160px, auto;
}

/* The monogram: the initial engraved in an oval cartouche, two rings. */
.ecrin-mono {
  width: 112px; height: 138px; border-radius: 50%;
  display: grid; place-items: center;
  border: 1px solid var(--gold);
  box-shadow: 0 0 0 5px var(--velvet), 0 0 0 6px color-mix(in srgb, var(--gold) 50%, transparent),
    inset 0 2px 8px rgba(0, 0, 0, .45);
}
.ecrin-initial {
  font-family: var(--font-display); font-style: italic; font-weight: 500;
  font-size: 88px; line-height: 1.1; padding: 0 .08em .06em 0;
  color: var(--gold-text);
  background: linear-gradient(160deg, #F1E2B8 0%, #CDAE68 38%, #A98740 60%, #EAD6A2 100%);
  background-size: 100% 100%;
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent;
  filter: drop-shadow(0 1px 0 rgba(0, 0, 0, .55));
}
.ecrin-name {
  margin-top: var(--s5);
  font-family: var(--font-display); font-weight: 500;
  font-size: clamp(17px, 4.8vw, 21px); line-height: 1.25;
  letter-spacing: .26em; text-transform: uppercase;
  color: var(--gold-text);
  text-shadow: 0 -1px 0 rgba(0, 0, 0, .6), 0 1px 0 rgba(255, 255, 255, .08);
  padding-left: .26em; /* the tracking hangs off the last letter; even it out */
}
/* The cushion slit a ring would stand in. Empty. */
.ecrin-slit {
  width: min(58%, 210px); height: 9px; border-radius: 9px;
  margin: var(--s5) 0;
  background: #0C1B15;
  box-shadow: inset 0 2px 3px rgba(0, 0, 0, .75), 0 1px 0 rgba(255, 255, 255, .09);
}
.ecrin-street {
  font-size: 12px; font-weight: 500; letter-spacing: .2em; text-transform: uppercase;
  color: var(--ivory-soft); line-height: 1.6;
}
.ecrin-dist { white-space: nowrap; }
.ecrin-sep { display: inline-block; width: 4px; height: 4px; border-radius: 50%; background: var(--gold); vertical-align: middle; margin: 0 .8em 2px; }

/* The price tag, tied on and turned a little, carrying the week. */
.ecrin-tag {
  position: relative; z-index: 3;
  justify-self: end;
  width: min(94%, 318px);
  margin: -58px 10px 0 0;
  padding: 14px 44px 14px 18px;
  color: var(--fg);
  transform: rotate(-3deg);
  transform-origin: 90% 50%;
  filter: drop-shadow(0 6px 8px rgba(16, 28, 22, .28)) drop-shadow(0 1px 1px rgba(16, 28, 22, .25));
}
.ecrin-tag::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background:
    linear-gradient(90deg, transparent calc(100% - 44px), color-mix(in srgb, var(--gold) 16%, transparent) calc(100% - 44px)),
    var(--tag);
  clip-path: polygon(0 0, calc(100% - 22px) 0, 100% 50%, calc(100% - 22px) 100%, 0 100%);
}
/* The eyelet. */
.ecrin-tag::after {
  content: ""; position: absolute; right: 12px; top: 50%; width: 10px; height: 10px; margin-top: -5px;
  border-radius: 50%; background: var(--bg);
  box-shadow: 0 0 0 1.5px var(--gold), inset 0 1px 2px rgba(0, 0, 0, .3);
}
/* The cord, from the eyelet up onto the case. */
.ecrin-tag-t::after {
  content: ""; position: absolute; right: 0; bottom: calc(50% - 2px); width: 44px; height: 130px;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='44' height='130' viewBox='0 0 44 130'%3E%3Cpath d='M27 128 C 18 92, 42 64, 30 2' fill='none' stroke='%23C9A860' stroke-width='1.5' stroke-linecap='round'/%3E%3C/svg%3E") no-repeat;
  z-index: 1;
}
.ecrin-tag-t {
  display: block; margin-bottom: 4px;
  font-family: var(--font-display); font-style: italic; font-size: 21px; line-height: 1.2;
  color: var(--accent);
}
.ecrin-week { list-style: none; margin: 0; padding: 0; font-size: 13.5px; white-space: nowrap; line-height: 1.45; font-variant-numeric: tabular-nums; }
.ecrin-week li { display: grid; grid-template-columns: 74px 1fr; gap: var(--s2); padding: 4px 0;
  border-top: 1px solid color-mix(in srgb, var(--fg) 12%, transparent); }
.ecrin-week .sa-d { color: var(--fg-soft); }
.ecrin-week .sa-h { color: var(--fg); font-weight: 500; }

/* Phone: the case opens the page, above the headline, closed down to the
   size of a ring box so the name, the street and the headline share the
   first screen. The price tag (the week) drops out: #horaires has it in
   full and the status line under the buttons says today's. */
@media (max-width: 899px) {
  .hero-sig { padding-top: var(--s5); }
  .hero-sig-grid { gap: var(--s5); }
  .hero-sig .hero-art { order: -1; }
  .ecrin { margin-top: 0; }
  .ecrin .sa-photo { max-height: 200px; object-fit: cover; margin-bottom: var(--s3); }
  .ecrin-case::before { inset: 7px; }
  .ecrin-case::after { inset: 10px; }
  .ecrin-lid { height: 30px; }
  .ecrin-bed {
    grid-template-columns: auto minmax(0, 1fr); column-gap: 20px; align-items: center;
    justify-items: start; text-align: left;
    padding: 24px 26px 26px;
  }
  .ecrin-mono { grid-row: 1 / span 3; width: 70px; height: 86px;
    box-shadow: 0 0 0 4px var(--velvet), 0 0 0 5px color-mix(in srgb, var(--gold) 50%, transparent),
      inset 0 2px 6px rgba(0, 0, 0, .45); }
  .ecrin-initial { font-size: 54px; }
  .ecrin-name { margin-top: 0; font-size: 17px; letter-spacing: .2em; padding-left: 0; }
  .ecrin-slit { width: min(100%, 150px); height: 7px; margin: 10px 0; }
  .ecrin-street { font-size: 11.5px; letter-spacing: .16em; }
  .ecrin-sep { display: none; }
  .ecrin-dist { display: block; }
  .ecrin-tag { display: none; }
  .hero .eyebrow { margin-bottom: var(--s2); }
}

@media (min-width: 900px) {
  .ecrin { margin-top: 0; }
  .ecrin-tag { margin: -70px -18px 0 0; }
}

@media (prefers-reduced-motion: no-preference) {
  .ecrin-initial { background-size: 220% 100%; animation: ecrin-sheen 9s ease-in-out infinite; }
  @keyframes ecrin-sheen { 0%, 100% { background-position: 0% 0; } 50% { background-position: 100% 0; } }
}

/* ---- sections ---- */
section + section { border-top: 0; }
main > section { overflow-x: clip; }
.section-title { position: relative; padding-left: 26px; margin-bottom: var(--s6); }
/* The fillet: from the page edge to just short of the first letter. */
.section-title::before {
  content: ""; position: absolute; top: .62em; right: calc(100% - 14px);
  width: 100vw; height: 1px; background: var(--gold);
}
@media (min-width: 900px) { .section-title { padding-left: 0; } .section-title::before { right: calc(100% + 22px); } }
.section-intro { margin-top: calc(var(--s6) * -1 + var(--s3)); }

/* La vitrine. The first frame is the window's centrepiece, the others stand
   beside it; empty, each is a mount with a gold fillet waiting for a piece. */
#photos .gallery { gap: 14px; }
#photos .gallery > * { box-shadow: none; }
#photos .photo-slot {
  aspect-ratio: 3 / 4;
  background: var(--surface);
  border: 1px solid var(--border);
  box-shadow: inset 0 0 0 12px #F3EDDF, inset 0 0 0 13px color-mix(in srgb, var(--gold) 55%, transparent);
  font-family: var(--font-display); font-style: normal; font-size: 19px; line-height: 1.25;
  color: var(--fg-soft);
  gap: 0;
}
#photos .photo-slot svg { display: none; }
#photos .photo-slot::before {
  content: ""; width: 22px; height: 1px; background: var(--gold); margin: 0 auto var(--s3);
}
@media (max-width: 759px) {
  #photos .gallery > :first-child:nth-last-child(odd) { grid-column: span 2; }
  #photos .gallery > .photo-slot:first-child:nth-last-child(odd) { aspect-ratio: 4 / 3; }
  #photos .gallery > .photo-slot:last-child:nth-child(odd):not(:first-child) { grid-column: auto; aspect-ratio: 3 / 4; }
  #photos .gallery > figure:last-child:nth-child(odd):not(:first-child) { grid-column: auto; }
  #photos .gallery > figure:last-child:nth-child(odd):not(:first-child) img { aspect-ratio: 1 / 1; }
}
@media (min-width: 760px) {
  #photos .gallery:has(> :first-child:nth-last-child(3)) { grid-template-columns: 2fr 1fr; gap: 18px; }
  #photos .gallery > :first-child:nth-last-child(3) { grid-row: span 2; }
  #photos .gallery > .photo-slot:first-child:nth-last-child(3) { aspect-ratio: auto; height: 100%; }
  #photos .gallery > .photo-slot:first-child:nth-last-child(3) ~ .photo-slot { aspect-ratio: 4 / 3; }
}

/* Ce qui se fait en boutique: the velvet tray, one compartment per craft. */
#specialites .products {
  counter-reset: ecrin;
  display: grid; gap: 10px; padding: 10px;
  background: var(--nap), var(--velvet);
  background-size: 160px 160px, auto;
  box-shadow: 0 0 0 1px var(--gold), 0 0 0 5px var(--bg), 0 0 0 6px color-mix(in srgb, var(--gold) 45%, transparent),
    0 30px 44px -30px rgba(16, 28, 22, .6);
  margin: 6px;
}
#specialites .product {
  counter-increment: ecrin;
  border: 0; padding: 22px 22px 24px;
  background: radial-gradient(120% 90% at 20% 0%, rgba(255, 255, 255, .07), transparent 60%), var(--velvet-lift);
  box-shadow: inset 0 2px 7px rgba(0, 0, 0, .55), inset 0 0 0 1px color-mix(in srgb, var(--gold) 22%, transparent);
}
#specialites .product::before {
  content: counter(ecrin, upper-roman);
  display: block; margin-bottom: var(--s2);
  font-family: var(--font-display); font-style: italic; font-size: 17px; line-height: 1.2;
  color: var(--gold-text); letter-spacing: .04em;
}
/* Not four equal boxes: the first craft is the flagship and gets the widest,
   tallest compartment with a larger name; the last, a one-line service, is a
   slim ring slot with name and line side by side. */
#specialites .product:first-child { padding: 30px 24px 32px; }
#specialites .product:first-child .p-name { font-size: 2rem; line-height: 1.15; }
#specialites .product:first-child::after {
  content: ""; display: block; width: 44px; height: 1px; margin-top: var(--s4);
  background: var(--gold);
}
#specialites .product:last-child:nth-child(4) {
  display: flex; flex-wrap: wrap; align-items: baseline; column-gap: var(--s3); row-gap: 2px;
  padding: 16px 22px;
}
#specialites .product:last-child:nth-child(4)::before { margin: 0; }
#specialites .product:last-child:nth-child(4) .p-name { font-size: 1.35rem; }
#specialites .product:last-child:nth-child(4) .p-desc { margin: 0; }
@media (min-width: 760px) {
  #specialites .product:first-child,
  #specialites .product:last-child:nth-child(4) { grid-column: 1 / -1; }
}
#specialites .p-name { font-family: var(--font-display); font-weight: 500; font-size: 1.6rem; line-height: 1.2; color: var(--ivory); }
#specialites .p-desc { color: var(--ivory-soft); font-size: 15.5px; line-height: 1.6; margin-top: var(--s2); }
#specialites .hours-note { font-family: var(--font-display); font-style: normal; font-size: 19px; line-height: 1.45; color: var(--fg-soft); max-width: 34ch; margin-top: var(--s6); }
@media (min-width: 760px) { #specialites .products { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1000px) {
  #specialites .wrap { display: grid; grid-template-rows: auto 1fr; grid-template-columns: minmax(0, .72fr) minmax(0, 1.6fr); column-gap: var(--s8); align-items: start; }
  #specialites .section-title { grid-column: 1; grid-row: 1; }
  #specialites .products { grid-column: 2; grid-row: 1 / span 2; }
  #specialites .hours-note { grid-column: 1; grid-row: 2; margin-top: 0; }
}

/* Horaires et accès: the table as a certificate card, the address set large. */
#horaires .hours-layout > div:first-child {
  position: relative; background: var(--surface);
  padding: clamp(20px, 5vw, 34px);
  border: 1px solid var(--border);
}
#horaires .hours-layout > div:first-child::before {
  content: ""; position: absolute; inset: 6px; pointer-events: none;
  border: 1px solid color-mix(in srgb, var(--gold) 45%, transparent);
}
.hours th { font-family: var(--font-display); font-size: 1.2rem; font-weight: 500; color: var(--fg); }
.hours td { font-size: 15px; color: var(--fg-soft); font-weight: 400; }
.hours th, .hours td { border-bottom-color: color-mix(in srgb, var(--fg) 10%, transparent); padding: 10px 0; }
.hours tr.today th { font-style: italic; color: var(--accent); font-weight: 500; }
.hours tr.today td { color: var(--fg); font-weight: 500; }
#horaires .hours-note { font-size: 14.5px; }
.addr { font-family: var(--font-display); font-size: 1.75rem; line-height: 1.25; }
.addr .label { font-family: var(--font-body); font-size: 12px; letter-spacing: .22em; font-weight: 500; margin-bottom: var(--s3); }
.map-frame { border-color: color-mix(in srgb, var(--gold) 45%, var(--border)); }
/* Desktop: the map runs down to the foot of the certificate card. */
@media (min-width: 880px) {
  #horaires .hours-layout { align-items: stretch; }
  #horaires .hours-layout > div:last-child { display: flex; flex-direction: column; }
  #horaires .hours-layout > div:last-child .map-frame { flex: 1 1 auto; display: flex; min-height: 300px; }
  #horaires .hours-layout > div:last-child .map-frame iframe { height: auto; flex: 1 1 auto; }
}

/* Contact: the question set large, the form plain and square. Accented copy
   stays roman across this signature: Cormorant's italic grave is drawn near
   vertical (official static and variable alike), and in 'pièce' it reads as
   a stray tick. Italic is kept for words without a grave. */
#contact .section-title { font-style: normal; }
#contact .section-intro { font-size: 1.05rem; }
.field label { font-weight: 500; font-size: 14.5px; letter-spacing: .02em; }
.field input, .field textarea { border-color: color-mix(in srgb, var(--fg) 22%, var(--border)); }
.field input:focus, .field textarea:focus { border-color: var(--primary); box-shadow: 0 0 0 1px var(--primary); }

.site-foot { border-top-color: color-mix(in srgb, var(--gold) 30%, var(--border)); }
.site-foot h4 { color: var(--accent); font-weight: 500; letter-spacing: .2em; font-size: 12.5px; }
.colophon { border-top-color: var(--border); }

/* ---- the map, behind the jeweller's gold double fillet. ---- */
.map-frame { padding: 6px; background: var(--bg); border: 0;
  box-shadow: inset 0 0 0 1px var(--gold), inset 0 0 0 4px var(--bg), inset 0 0 0 5px color-mix(in srgb, var(--gold) 40%, transparent); }
.map-frame iframe { filter: sepia(.3) saturate(.7); }

/* ---- contact, desktop: the heading, the words and the call ride in the
   left column beside the form (sticky), so the column is never an empty
   half of the page; name and e-mail share a line. ---- */
@media (min-width: 880px) {
  #contact .wrap { display: grid; grid-template-columns: 5fr 6fr; grid-template-rows: auto 1fr; column-gap: var(--s8); align-items: start; }
  #contact .section-title { grid-column: 1; grid-row: 1; }
  #contact .contact-layout { display: contents; }
  #contact .contact-layout > div { grid-column: 1; grid-row: 2; position: sticky; top: 110px; }
  #contact form { grid-column: 2; grid-row: 1 / span 2; display: grid; grid-template-columns: 1fr 1fr; column-gap: var(--s4); }
  #contact form > * { grid-column: 1 / -1; min-width: 0; }
  #contact form > .field:nth-of-type(1) { grid-column: 1; }
  #contact form > .field:nth-of-type(2) { grid-column: 2; }
}

/* ---- the call, catching the light ----
   Pointing at a call button (only where there is a pointer), tabbing to it
   or pressing it sends one gold sheen across it, under the words, the way a
   ring turns under the counter lamp. Once, not a loop. Nothing moves until
   touched, and with less motion asked for there is no sheen at all. */
.btn-primary, .btn-oncta { position: relative; isolation: isolate; overflow: hidden; -webkit-tap-highlight-color: transparent; }
.btn-primary::after, .btn-oncta::after {
  content: ""; position: absolute; z-index: -1; top: 0; bottom: 0; left: 0; width: 45%;
  pointer-events: none; opacity: 0;
  background: linear-gradient(100deg, transparent 0%, rgba(241, 226, 184, .42) 50%, transparent 100%);
  transform: translateX(-110%);
}
@media (prefers-reduced-motion: no-preference) {
  @media (hover: hover) {
    .btn-primary:hover::after, .btn-oncta:hover::after {
      opacity: 1; transform: translateX(250%); transition: transform .9s ease-in-out;
    }
  }
  .btn-primary:focus-visible::after, .btn-oncta:focus-visible::after {
    opacity: 1; transform: translateX(250%); transition: transform .9s ease-in-out;
  }
  .btn-primary:active::after, .btn-oncta:active::after { opacity: 1; animation: ecrin-glint .5s ease-out; }
  @keyframes ecrin-glint { from { transform: translateX(-110%); } to { transform: translateX(250%); } }
}

/* ---- the lines move (owner, fb-0097) ----
   The gold fillet runs in from the page edge to its title once as the
   title scrolls in, and light moves over the lid's satin now and then. The
   tag and the week on it stay still. (The cord's sway was too small to see:
   owner, 2026-09-30.) */
.ecrin-lid { overflow: hidden; }
@media (prefers-reduced-motion: no-preference) {
  .section-title.reveal::before { transform: scaleX(0); transform-origin: left center; }
  .section-title.reveal.in::before { transform: none; transition: transform 1.1s cubic-bezier(.3, .7, .3, 1) .15s; }
  .ecrin-lid::after {
    content: ""; position: absolute; top: 0; bottom: 0; left: 0; width: 35%; pointer-events: none;
    background: linear-gradient(90deg, transparent, rgba(241, 226, 184, .4) 50%, transparent);
    animation: ecrin-satin 8s ease-in-out infinite;
  }
  @keyframes ecrin-satin {
    0%, 55% { transform: translateX(-160%) skewX(-18deg); }
    85%, 100% { transform: translateX(360%) skewX(-18deg); }
  }
}
