/* 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: #7B2D26;
  --primary-ink: #FFFFFF;
  --accent: #2F5D50;
  --bg: #F6F3EC;
  --surface: #FFFFFF;
  --fg: #1B1916;
  --fg-soft: #5F594E;
  --border: #E2DCCF;
  /* 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: Cahier. French school stationery. The page is the paper a
   customer buys here: Seyès ruling (fine lilac-blue lines every 8px, a
   stronger one every 32px, a red margin) on the hero page and on the counter
   panel, a bristol card for the hours, an airmail edge on the contact form
   for the relais colis. The one repeated device is the schoolroom rule: every
   section title is underlined twice in red, with a ruler. Labels are typed
   (Special Elite), notes are handwritten (Kalam), names are set in Young
   Serif. */

@font-face { font-family: 'Cahier Serif'; font-style: normal; font-weight: 400; font-display: swap;
  src: url('fonts/young-serif-400.woff2') format('woff2'); }
@font-face { font-family: 'Cahier Typed'; font-style: normal; font-weight: 400; font-display: swap;
  src: url('fonts/special-elite-400.woff2') format('woff2'); }
@font-face { font-family: 'Cahier Hand'; font-style: normal; font-weight: 400; font-display: swap;
  src: url('fonts/kalam-400.woff2') format('woff2'); }
@font-face { font-family: 'Cahier Sans'; font-style: normal; font-weight: 400; font-display: swap;
  src: url('fonts/instrument-sans-400.woff2') format('woff2'); }
@font-face { font-family: 'Cahier Sans'; font-style: normal; font-weight: 600; font-display: swap;
  src: url('fonts/instrument-sans-600.woff2') format('woff2'); }

:root {
  --font-display: 'Cahier Serif', Georgia, 'Times New Roman', serif;
  --font-body: 'Cahier Sans', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --font-typed: 'Cahier Typed', 'Courier New', monospace;
  --font-hand: 'Cahier Hand', 'Comic Sans MS', cursive;
  --display-weight: 400;
  --display-tracking: -0.01em;
  --h1: clamp(2.35rem, 9.6vw, 4.2rem);
  --h1-lh: 1.1;
  --h2: clamp(1.75rem, 6.6vw, 2.6rem);
  --body-size: 17px;
  --body-lh: 1.65;
  --radius: 3px;
  --radius-sm: 2px;
  --btn-radius: 3px;
  --sec-pad: 56px;
  --sec-pad-wide: 72px;
  --shadow-1: none;
  --shadow-2: none;

  /* The paper. Seyès: 8px fine lines, a 32px strong line, verticals on the
     big square, and the margin in red. Colours are school-supply, not brand. */
  --seyes-fine: rgba(150, 140, 222, .30);
  --seyes-vert: rgba(150, 140, 222, .22);
  --seyes-bold: rgba(112, 100, 206, .52);
  --margin-red: #D9534F;
  --paper: #FFFFFF;
  --margin: 44px;
  /* A strip of tape: translucent, with torn ends from a zig-zag mask. */
  --tape: color-mix(in srgb, #E9DDB5 78%, transparent);
}

.preview-note { background: #16263D; }
.preview-note strong { color: #FFE08A; }

.site-head { background: color-mix(in srgb, var(--bg) 92%, transparent); border-bottom-color: var(--border); }
.brand { font-family: var(--font-display); font-size: 21px; color: var(--primary); }
.nav a { font-family: var(--font-typed); font-size: 15px; letter-spacing: .02em; }

.btn { font-weight: 600; }
.btn-primary { background: var(--primary); box-shadow: 3px 3px 0 color-mix(in srgb, var(--primary) 30%, transparent); }
.btn-ghost { background: var(--paper); border-color: color-mix(in srgb, var(--primary) 55%, transparent); color: var(--primary); }

/* Declared on the papers themselves, not on :root, so a paper that lowers
   --seyes-fine gets a ruling built from its own value. */
.ch-page, #specialites .wrap > .products {
  --seyes:
    linear-gradient(90deg, transparent 0 calc(var(--margin) - 2px), var(--margin-red) calc(var(--margin) - 2px) var(--margin), transparent var(--margin)),
    repeating-linear-gradient(180deg, transparent 0 31px, var(--seyes-bold) 31px 32px),
    repeating-linear-gradient(90deg, transparent 0 31px, var(--seyes-vert) 31px 32px),
    repeating-linear-gradient(180deg, transparent 0 7px, var(--seyes-fine) 7px 8px);
}

/* ---- hero ---- */
.hero-sig { padding-top: var(--s7); overflow: hidden; }
/* The category is typed on a strip and taped on, not set as an eyebrow. */
.hero .eyebrow {
  display: inline-block;
  font-family: var(--font-typed); font-weight: 400; text-transform: none;
  letter-spacing: .02em; font-size: 15px; color: var(--fg);
  background: var(--paper);
  border: 1px solid var(--border);
  padding: 6px 12px 5px;
  transform: rotate(-1.2deg);
  box-shadow: 1px 2px 0 color-mix(in srgb, var(--fg) 8%, transparent);
}
.hero h1 { color: var(--primary); }
.hero .lede { max-width: 36ch; }

.cahier { position: relative; margin: 0; padding: 0 0 26px; max-width: 480px; }
@media (min-width: 900px) { .cahier { margin-left: auto; max-width: 500px; } }
.cahier .sa-photo { border: 8px solid var(--paper); box-shadow: 0 2px 10px rgba(20, 30, 50, .18); margin-bottom: var(--s4); }

/* The cover: navy card stock with a faint cloth grain, and the classic label. */
.ch-cover {
  background-color: var(--primary);
  background-image:
    repeating-linear-gradient(45deg, rgba(255,255,255,.035) 0 2px, transparent 2px 5px),
    repeating-linear-gradient(-45deg, rgba(0,0,0,.06) 0 2px, transparent 2px 5px);
  border-radius: 4px 4px 0 0;
  padding: 26px 22px 30px;
  position: relative;
}
.ch-label {
  background: var(--paper);
  border-radius: 10px;
  padding: 14px 18px 12px;
  /* The double frame of every French notebook label. */
  box-shadow: inset 0 0 0 2px var(--paper), inset 0 0 0 3px var(--primary), inset 0 0 0 5px var(--paper), inset 0 0 0 6px color-mix(in srgb, var(--primary) 60%, var(--paper));
  display: grid; grid-template-columns: auto minmax(0, 1fr); column-gap: 12px; align-items: baseline;
}
.ch-label-k { font-family: var(--font-typed); font-size: 13px; color: var(--fg-soft); }
.ch-label-v {
  font-family: var(--font-display); color: var(--primary);
  font-size: clamp(1.35rem, 6vw, 1.75rem); line-height: 1.15;
  padding: 2px 0 6px;
  border-bottom: 1px dotted color-mix(in srgb, var(--fg) 35%, transparent);
  margin-bottom: 8px;
}
.ch-label-v { overflow-wrap: anywhere; }
.ch-label-addr { font-family: var(--font-hand); font-size: 19px; color: var(--fg); margin-bottom: 0; border-bottom: 0; padding-bottom: 0; }

/* The page: Seyès with the margin, the counter written on the lines. */
.ch-page {
  position: relative;
  background-color: var(--paper);
  background-image: var(--seyes);
  /* Rows are 32px from a 20px top, so the strong line lands under each
     baseline: the offset puts it there (20 - 5, see the note on .p-head). */
  padding: 20px 18px 104px calc(var(--margin) + 14px);
  background-position: 0 0, 0 15px, 0 0, 0 15px;
  border-radius: 0 0 4px 4px;
  box-shadow: 0 1px 0 var(--border), 0 12px 24px -16px rgba(20, 30, 50, .35);
}
.ch-note {
  font-family: var(--font-hand); color: var(--accent);
  font-size: 24px; line-height: 32px; margin: 0;
  text-decoration: underline; text-decoration-thickness: 2px; text-underline-offset: 5px;
}
.ch-list { list-style: none; margin: 0 0 20px; padding: 0; }
.ch-list li {
  font-family: var(--font-hand); color: var(--primary);
  font-size: 19px; line-height: 32px;
  display: flex; gap: 8px; align-items: baseline;
}
.ch-list li::before { content: "–"; color: var(--fg-soft); }
.ch-list .sa-l { flex: 1 1 auto; border-bottom: 2px dotted color-mix(in srgb, var(--primary) 30%, transparent); }
.ch-list .sa-p { font-family: var(--font-typed); font-size: 15px; }

/* The week, typed on a slip clipped over the page. */
.ch-slip {
  position: relative;
  background: #FBF6E6;
  border: 1px solid #E4D9B8;
  padding: 16px 16px 12px;
  transform: rotate(-1.5deg);
  box-shadow: 0 6px 14px -10px rgba(20, 30, 50, .5);
}
/* The paper clip: two nested rounded rectangles, drawn, not a picture of stock. */
.ch-slip::before {
  content: ""; position: absolute; top: -14px; left: 22px;
  width: 14px; height: 40px; border: 2px solid #8C95A3; border-radius: 8px;
}
.ch-slip::after {
  content: ""; position: absolute; top: -8px; left: 26px;
  width: 6px; height: 26px; border: 2px solid #8C95A3; border-radius: 5px; border-top-color: transparent;
}
.ch-slip-t { display: block; font-family: var(--font-typed); font-size: 14px; letter-spacing: .12em; text-transform: uppercase; color: var(--accent); margin: 0 0 6px 30px; }
.ch-week { list-style: none; margin: 0; padding: 0; font-family: var(--font-typed); font-size: 15px; }
.ch-week li { display: flex; justify-content: space-between; gap: 12px; padding: 3px 0; border-bottom: 1px dashed color-mix(in srgb, var(--fg) 18%, transparent); }
.ch-week li:last-child { border-bottom: 0; }
.ch-week .sa-d { color: var(--fg-soft); }
.ch-week .sa-h { color: var(--fg); }

/* The postmark: over the page corner, slightly off true, in ink. */
.ch-stamp {
  position: absolute; right: 10px; bottom: -22px;
  width: 118px; height: 118px;
  color: color-mix(in srgb, var(--primary) 78%, transparent);
  transform: rotate(-14deg);
  overflow: visible;
}
.ch-stamp text { fill: currentColor; font-family: var(--font-typed); }
.ch-stamp-ring { font-size: 15px; letter-spacing: .05em; }
.ch-stamp-mid { font-size: 27px; letter-spacing: .04em; }

/* Phone: the notebook comes first, closed down to its cover label and the
   open page with the counter written on it, so the first screen reads as a
   stationer's before the headline. The typed week slip goes: #horaires
   carries the same days a scroll below. */
@media (max-width: 899.98px) {
  .hero-sig { padding-top: var(--s5); }
  .hero-sig-grid { gap: var(--s5); }
  .hero-sig .hero-art { order: -1; }
  .cahier { padding-bottom: 14px; }
  .ch-cover { padding: 14px 14px 16px; }
  .ch-label { padding: 10px 14px 8px; column-gap: 10px; }
  .ch-label-v { font-size: 1.3rem; padding: 0 0 4px; margin-bottom: 6px; }
  .ch-label-addr { font-size: 17px; }
  .ch-page { padding: 20px 14px 22px calc(var(--margin) + 12px); }
  .ch-note { font-size: 22px; }
  .ch-list { margin: 0; padding-right: 88px; }
  .ch-list li { font-size: 18px; }
  .ch-slip { display: none; }
  .ch-stamp { width: 104px; height: 104px; right: 4px; bottom: -18px; }
  .hero .eyebrow { margin-bottom: var(--s2); }
}

/* ---- sections ---- */
section + section { border-top: 0; }
.section-title, .menu-group h3 { text-align: left; }
.section-title {
  color: var(--primary);
  /* Underlined twice, in red, with a ruler: the schoolroom title. It follows
     the text on each line when a title wraps, which a pseudo-element would not. */
  text-decoration: underline double var(--margin-red);
  text-decoration-thickness: 2px;
  text-underline-offset: .22em;
  text-decoration-skip-ink: none;
  margin-bottom: var(--s6);
  /* The double rule takes room under each line; at 1.15 it all but touched
     the next line of a wrapped title. */
  line-height: 1.35;
}
.section-title::after { content: none; }
.section-intro { text-align: left; margin-left: 0; }

/* The vitrine: three frames taped to the wall, each a little off true. */
#photos .section-intro { font-size: 16.5px; }
.gallery { gap: 22px 16px; }
.gallery .photo-slot {
  position: relative;
  border: 0;
  background: var(--paper);
  box-shadow: 0 0 0 1px var(--border), 0 10px 18px -14px rgba(20, 30, 50, .45);
  border-radius: 2px;
  padding: 14px;
  outline: 1px dashed color-mix(in srgb, var(--fg) 25%, transparent);
  outline-offset: -14px;
  color: var(--fg-soft);
  font-family: var(--font-hand); font-size: 17px;
}
.gallery .photo-slot:nth-child(3n+1) { transform: rotate(-1.4deg); }
.gallery .photo-slot:nth-child(3n+2) { transform: rotate(1.1deg); }
.gallery .photo-slot:nth-child(3n) { transform: rotate(-.6deg); }
.gallery .photo-slot::before,
.gallery .photo-slot::after {
  content: ""; position: absolute; width: 58px; height: 20px; background: var(--tape);
  box-shadow: 0 1px 1px rgba(0, 0, 0, .06);
}
.gallery .photo-slot::before { top: -8px; left: -14px; transform: rotate(-38deg); }
.gallery .photo-slot::after { bottom: -8px; right: -14px; transform: rotate(-38deg); }
/* No camera glyph: the handwritten caption is enough to say what goes here. */
.gallery .photo-slot svg { display: none; }
.gallery .photo-slot span { font-size: 19px; color: var(--fg-soft); }

/* The counter, written on a ruled page. */
#specialites .wrap > .products {
  background-color: var(--paper);
  background-image: var(--seyes);
  /* 24px top, so the strong line sits at 24 - 5 (baseline of a 32px row). */
  background-position: 0 0, 0 19px, 0 0, 0 19px;
  padding: 24px 20px 24px calc(var(--margin) + 16px);
  /* Body text sits on this page, so the fine ruling steps back a little. */
  --seyes-fine: rgba(150, 140, 222, .20);
  --seyes-vert: rgba(150, 140, 222, .14);
  box-shadow: 0 0 0 1px var(--border), 0 14px 26px -20px rgba(20, 30, 50, .4);
  max-width: 720px;
}
.product { border-bottom: 0; padding: 0 0 32px; }
.product:last-child { padding-bottom: 0; }
.p-head { line-height: 32px; }
.p-name { font-family: var(--font-display); font-weight: 400; font-size: 1.3rem; color: var(--primary); line-height: 32px; }
.p-desc { font-size: 16px; line-height: 32px; margin: 0; color: var(--fg-soft); }
.products + .hours-note, #specialites .hours-note, #specialites .wrap > p:last-child {
  font-family: var(--font-hand); font-size: 19px; color: var(--accent); max-width: 44ch;
}

/* The hours: a lined bristol card, its head typed on the red rule, one day
   per blue line. */
#horaires .hours-layout > div:first-child {
  background: var(--paper);
  box-shadow: 0 0 0 1px var(--border), 0 14px 26px -20px rgba(20, 30, 50, .4);
  padding: 14px 20px 20px;
}
#horaires .hours-layout > div:first-child::before {
  content: "Semaine"; display: block;
  font-family: var(--font-typed); font-size: 14px; letter-spacing: .12em; text-transform: uppercase;
  color: var(--accent); line-height: 1.3;
  padding-bottom: 6px; border-bottom: 2px solid var(--margin-red);
}
/* Days in the body face: Special Elite ends its 'i' in an ink blot that read
   as a full stop ('Lundi.'), so the typewriter keeps only the times. */
.hours { font-size: 16px; }
.hours th { font-family: var(--font-body); }
.hours td { font-family: var(--font-typed); }
.hours th, .hours td { border-bottom: 1px solid rgba(112, 100, 206, .32); padding: 0; height: 46px; vertical-align: bottom; padding-bottom: 6px; }
.hours tr:last-child th, .hours tr:last-child td { border-bottom: 1px solid rgba(112, 100, 206, .32); }
.hours tr.today th, .hours tr.today td { color: var(--primary); font-weight: 400; }
.hours tr.today th::before { content: "→ "; color: var(--accent); }
#horaires .hours-note { font-size: 15px; margin-top: var(--s5); }
.addr .label, .site-foot h4 { font-family: var(--font-typed); font-weight: 400; text-transform: none; letter-spacing: .04em; font-size: 15px; color: var(--accent); }
.addr { font-family: var(--font-display); font-size: 19px; color: var(--primary); }
.map-frame { border-radius: 2px; }

/* The contact form rides in an airmail envelope: the red and blue edge. */
#contact form {
  background: var(--paper);
  padding: 22px 20px 20px;
  border: 8px solid transparent;
  border-image: repeating-linear-gradient(-45deg, var(--margin-red) 0 12px, var(--paper) 12px 20px, var(--primary) 20px 32px, var(--paper) 32px 40px) 8;
}
.field label { font-family: var(--font-typed); font-weight: 400; font-size: 15px; letter-spacing: .02em; }
.field .hint { font-family: var(--font-body); letter-spacing: 0; }
.field input, .field textarea {
  background: transparent; border: 0; border-bottom: 1px solid color-mix(in srgb, var(--primary) 45%, var(--border));
  border-radius: 0; padding-left: 0;
  font-family: var(--font-hand); font-size: 19px; color: var(--primary);
}
/* A line on a form: the handwriting sits right under its typed label. */
.field input { padding: 4px 0 6px; line-height: 1.3; min-height: 44px; }
.field textarea {
  background-image: repeating-linear-gradient(180deg, transparent 0 31px, color-mix(in srgb, var(--primary) 22%, transparent) 31px 32px);
  line-height: 32px;
}
.site-foot { border-top: 1px solid var(--border); }
.colophon { font-family: var(--font-typed); }

/* From 900px the counter changes sides: title and note on the left, the ruled
   page on the right, so the page does not read as one left-aligned column. */
@media (min-width: 900px) {
  /* Title and note stack at the top; the spare height goes to the last row. */
  #specialites .wrap { display: grid; grid-template-columns: minmax(0, .8fr) minmax(0, 1.2fr); grid-template-rows: auto auto 1fr; column-gap: var(--s8); align-items: start; }
  #specialites .wrap > * { grid-column: 1; }
  #specialites .wrap > .products { grid-column: 2; grid-row: 1 / span 3; max-width: none; }
  #specialites .wrap > .section-title { margin-bottom: var(--s4); }
  /* The counter sits close under the vitrine, the hours close under the counter. */
  #specialites, #horaires { padding-top: 48px; }
}

/* ---- sections other trades on this signature bring (services, brands,
   reviews, band, faq, carte, steps, trust). None appear on every page, and
   none may fall back to the icon-in-a-square card. ---- */

/* Services: bristol index cards, red head rule, typed title, no icon tile. */
.cards { gap: var(--s5); }
.card {
  position: relative;
  background: var(--paper);
  background-image:
    linear-gradient(180deg, transparent 0 58px, var(--margin-red) 58px 60px, transparent 60px),
    repeating-linear-gradient(180deg, transparent 0 27px, rgba(112, 100, 206, .22) 27px 28px);
  background-position: 0 0, 0 4px;
  border: 0; border-radius: 1px;
  box-shadow: 0 0 0 1px var(--border), 0 12px 22px -18px rgba(20, 30, 50, .45);
  padding: 22px 20px 20px;
}
.card .icon { display: none; }
.card h3 { font-family: var(--font-display); color: var(--primary); font-size: 1.2rem; line-height: 1.3; min-height: 36px; margin-bottom: 18px; }
.card p { line-height: 28px; font-size: 16px; }
.card-price { font-family: var(--font-typed); font-weight: 400; color: var(--accent); }
.cards > .card:nth-child(odd) { transform: rotate(-.5deg); }
.cards > .card:nth-child(even) { transform: rotate(.4deg); }

/* Brands: typed labels, each held by a strip of tape. */
.brands { gap: 18px 14px; }
.brands li {
  position: relative;
  font-family: var(--font-typed); font-weight: 400; font-size: 15px;
  background: var(--paper); border: 1px solid var(--border); border-radius: 0;
  padding: 10px 16px 9px; min-height: 44px; display: flex; align-items: center;
}
.brands li::before {
  content: ""; position: absolute; top: -7px; left: 50%; width: 34px; height: 12px;
  margin-left: -17px; background: var(--tape); transform: rotate(-4deg);
}

/* Reviews: a note on a ruled leaf, written by hand, with the margin. */
.quote {
  background-color: var(--paper);
  background-image:
    linear-gradient(90deg, transparent 0 30px, var(--margin-red) 30px 32px, transparent 32px),
    repeating-linear-gradient(180deg, transparent 0 31px, rgba(112, 100, 206, .30) 31px 32px);
  border: 0; border-radius: 1px;
  box-shadow: 0 0 0 1px var(--border);
  padding: 20px 20px 20px 48px;
}
.quote blockquote { font-family: var(--font-hand); color: var(--primary); font-size: 19px; line-height: 32px; }
.quote figcaption { font-family: var(--font-typed); }
.stars { color: var(--accent); }

/* Band: kraft card stock, the one warm brown block on the page. */
.cta-band {
  background: #C9A877;
  background-image: repeating-linear-gradient(90deg, rgba(90, 60, 20, .05) 0 1px, transparent 1px 4px),
    repeating-linear-gradient(0deg, rgba(255, 255, 255, .06) 0 1px, transparent 1px 3px);
  color: #1B1916; text-align: left;
}
.cta-band h2 { color: #14243B; }
.cta-band p { margin-left: 0; opacity: 1; }
.cta-band .cta-num { margin-left: 0; font-family: var(--font-typed); color: #14243B; }
.btn-oncta { background: var(--primary); color: var(--primary-ink); border-color: var(--primary); }
.btn-oncta:hover { background: color-mix(in srgb, var(--primary) 88%, #000); }

/* Faq: questions typed, answers on the lines. */
.faq-item { border-bottom: 1px solid rgba(112, 100, 206, .35); }
.faq-item summary { font-family: var(--font-display); font-weight: 400; color: var(--primary); min-height: 44px; }
.faq-mark, .faq-mark::after { background: var(--accent); }

/* Carte: a Seyès page, if a trade here ever has one. */
.sig-cahier #carte .menu {
  background-color: var(--paper);
  background-image: repeating-linear-gradient(180deg, transparent 0 31px, rgba(112, 100, 206, .35) 31px 32px);
  box-shadow: 0 0 0 1px var(--border);
  padding: 20px;
}
.menu-group h3 { font-family: var(--font-hand); color: var(--accent); font-size: 1.5rem; border-bottom: 0; }
.mi-price { font-family: var(--font-typed); font-weight: 400; color: var(--primary); }

/* Steps and trust: numbered like an exercise, the badge a typed circle. */
.step-n { font-family: var(--font-typed); font-weight: 400; border-color: var(--accent); color: var(--accent); background: var(--paper); }
.t-icon { background: var(--paper); border: 1px solid var(--border); color: var(--primary); border-radius: 50%; }

/* ---- the map, a print taped into the notebook. ---- */
.map-frame { position: relative; overflow: visible; border: 0; padding: 8px; background: var(--paper);
  box-shadow: 0 2px 10px rgba(20, 30, 50, .18); transform: rotate(-.8deg); }
.map-frame::before { content: ""; position: absolute; top: -10px; left: 50%; width: 90px; height: 22px; margin-left: -45px;
  background: color-mix(in srgb, #E8D9A8 80%, transparent); transform: rotate(3deg); z-index: 1; }
.map-frame iframe { filter: grayscale(.35) sepia(.15); }

/* ---- 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, pressed like a stamp ----
   Pointing at a call button (only where there is a pointer) tilts it a
   degree, the stamp lined up; pressing it pushes it down onto its own
   shadow and leaves a dashed ink ring inside. Keyboard focus shows the
   ring. Nothing moves until touched. */
.btn-primary, .btn-oncta { position: relative; -webkit-tap-highlight-color: transparent; }
.btn-primary::after, .btn-oncta::after {
  content: ""; position: absolute; inset: 4px; border-radius: 2px; pointer-events: none;
  border: 1.5px dashed currentColor; opacity: 0;
}
@media (hover: hover) {
  .btn-primary:hover, .btn-oncta:hover { transform: rotate(-1.2deg); }
}
.btn-primary:focus-visible::after, .btn-oncta:focus-visible::after { opacity: .55; }
.btn-primary:active, .btn-oncta:active { transform: translate(3px, 3px); box-shadow: none; }
.btn-primary:active::after, .btn-oncta:active::after { opacity: .55; }
@media (prefers-reduced-motion: no-preference) {
  .btn-primary::after, .btn-oncta::after { transition: opacity .2s ease-out; }
  .btn-primary:active::after, .btn-oncta:active::after { animation: cahier-ink .3s ease-out; }
  @keyframes cahier-ink { from { opacity: 0; transform: scale(1.06); } to { opacity: .55; transform: scale(1); } }
}

/* ---- the lines move (owner, fb-0097) ----
   The tape on each gallery frame is pressed on once as the frames scroll
   in: it lands a little large and flattens. */
@media (prefers-reduced-motion: no-preference) {
  .gallery.reveal .photo-slot::before, .gallery.reveal .photo-slot::after { opacity: 0; scale: 1.35; }
  .gallery.reveal.in .photo-slot::before, .gallery.reveal.in .photo-slot::after {
    opacity: 1; scale: 1; transition: scale .45s cubic-bezier(.3, .7, .3, 1) .3s, opacity .25s ease-out .3s;
  }
  .gallery.reveal.in .photo-slot:nth-child(2)::before, .gallery.reveal.in .photo-slot:nth-child(2)::after { transition-delay: .5s; }
  .gallery.reveal.in .photo-slot:nth-child(3)::before, .gallery.reveal.in .photo-slot:nth-child(3)::after { transition-delay: .7s; }
}
