/* 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: #1E6B4A;
  --primary-ink: #FFFFFF;
  --accent: #B23A2E;
  --bg: #FBF8F2;
  --surface: #FFFFFF;
  --fg: #1E2419;
  --fg-soft: #5C6455;
  --border: #E4DFD0;
  /* 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); }

/* Maison — the bistro and artisan skin.
   Device: the page reads like a printed menu. Section titles sit centred over a
   short double rule, and every priced line runs to a dotted leader. */

:root {
  --h1: clamp(2.4rem, 9vw, 4.2rem);
  --h1-lh: 1.05;
  --h2: clamp(1.6rem, 6vw, 2.4rem);
  --display-weight: 600;
  --display-tracking: -0.01em;
  --body-size: 17px;
  --body-lh: 1.65;
  --radius: 10px;
  --btn-radius: 999px;
  --sec-pad: 56px;
  --sec-pad-wide: 72px;
  --card-shadow: 0 1px 2px rgba(64, 34, 12, .05);
  --eyebrow-tracking: .14em;
}

/* Centred titles over a double rule. The ornament is the strongest single cue
   that this is a carte and not a card grid. */
.section-title {
  text-align: center;
  margin-bottom: var(--s6);
  padding-bottom: var(--s4);
  position: relative;
}
.section-title::after {
  content: "";
  position: absolute; left: 50%; bottom: 0;
  width: 64px; height: 3px;
  transform: translateX(-50%);
  border-top: 1px solid var(--accent);
  border-bottom: 1px solid var(--accent);
}
.section-intro { text-align: center; margin-left: auto; margin-right: auto; }
/* Except in the contact column, where the intro sits over a left-aligned phone
   button: centred text above a flush-left button read as two layouts. */
.contact-layout .section-intro { text-align: left; margin-left: 0; }
/* A single-group carte is centred at 620px (.menu-1), so its note follows it
   instead of hanging off the left edge of the section. */
.menu-1 ~ .hours-note { max-width: 620px; margin-inline: auto; text-align: center; }

.card { box-shadow: var(--card-shadow); }
.menu-group h3 { text-align: center; }
.mi-price { color: var(--primary); }

/* Comptoir uses the editorial hero: the eyebrow carries the "depuis" line, so
   it gets room to breathe. */
.hero-editorial .eyebrow { margin-bottom: var(--s3); }

/* Signature: Trattoria. A neighbourhood pizzeria told in two places: the
   shopfront (striped awning, the name painted on a green fascia, the week
   lettered on the glass) and the table (a red and white gingham cloth with
   the printed carta laid on it). The gingham is the one device, and it comes
   back as a cloth edge on the header, the booking card and the footer.
   Section titles are DM Serif italic, flush left, with no rule under them. */

@font-face { font-family: 'Trattoria Display'; font-style: normal; font-weight: 400; font-display: swap;
  src: url('fonts/dm-serif-display-400.woff2') format('woff2'); }
@font-face { font-family: 'Trattoria Display'; font-style: italic; font-weight: 400; font-display: swap;
  src: url('fonts/dm-serif-display-400i.woff2') format('woff2'); }
@font-face { font-family: 'Trattoria Sans'; font-style: normal; font-weight: 400; font-display: swap;
  src: url('fonts/karla-400.woff2') format('woff2'); }
@font-face { font-family: 'Trattoria Sans'; font-style: normal; font-weight: 600; font-display: swap;
  src: url('fonts/karla-600.woff2') format('woff2'); }

:root {
  --font-display: 'Trattoria Display', Georgia, 'Times New Roman', serif;
  --font-body: 'Trattoria Sans', system-ui, -apple-system, 'Segoe UI', sans-serif;
  /* DM Serif ships one weight. 600 from the maison skin would be faked. */
  --display-weight: 400;
  --display-tracking: -0.005em;
  --h1: clamp(2.7rem, 11.5vw, 4.5rem);
  --h1-lh: 1.1;
  --h2: clamp(2.1rem, 8.5vw, 3.2rem);
  --radius: 3px;
  --radius-sm: 2px;
  --btn-radius: 4px;
  --sec-pad: 60px;
  --sec-pad-wide: 96px;
  --shadow-1: none;
  --shadow-2: none;
  --eyebrow-tracking: .16em;

  /* Painted-sign cream, on the green fascia and the green band (5.4:1). */
  --tt-cream: #F7EDD6;
  /* Window glass, and the gold leaf lettered on it (8:1 and more). */
  --tt-glass: #14201A;
  --tt-gold: #E2BE74;
  --tt-paper: #FFFDF8;
  /* Gingham: two half-transparent red bands crossing. Where they cross the
     square goes deep red, where one passes it goes pink, elsewhere white.
     Never under text: everything written sits on paper laid over it. */
  --tt-check: color-mix(in srgb, var(--accent) 46%, transparent);
  --tt-gingham:
    linear-gradient(90deg, var(--tt-check) 50%, transparent 50%),
    linear-gradient(0deg, var(--tt-check) 50%, transparent 50%);
}

h1, h2, h3, .brand, .mi-price, .card-price, .cta-band .cta-num { font-synthesis: none; }
.mi-price, .card-price, .cta-band .cta-num { font-weight: 400; }

/* ---- ribbon and header ---- */
.preview-note { background: #1c1a15; }
.site-head { border-bottom: 0; background: color-mix(in srgb, var(--bg) 94%, transparent); }
.site-head::after {
  /* One full row of checks, 11px each: reads as the cloth's hem, not a rule. */
  content: ""; display: block; height: 11px;
  background-color: #fff; background-image: var(--tt-gingham); background-size: 22px 22px;
  background-position: 0 11px;
}
.brand {
  font-family: var(--font-display); font-style: italic; font-weight: 400;
  font-size: 25px; letter-spacing: 0; color: var(--accent);
}
.nav a { color: var(--fg); }
.nav a:hover { color: var(--accent); }

/* ---- buttons: square-shouldered, like a painted board ---- */
.btn { letter-spacing: .01em; }
.btn-primary { box-shadow: 0 3px 0 0 color-mix(in srgb, var(--primary) 60%, #000); }
.btn-primary:active { box-shadow: none; }
.btn-ghost { background: transparent; color: var(--fg); border: 1.5px solid var(--fg); }
.btn-ghost:hover { border-color: var(--accent); color: var(--accent); }

/* ---- hero ---- */
.hero-sig { padding-top: var(--s7); padding-bottom: var(--s8); overflow: hidden; }
.hero .eyebrow { color: var(--accent); font-weight: 600; }
.hero h1 { font-weight: 400; }
.hero .lede { color: var(--fg-soft); max-width: 36ch; }

/* The shopfront. Awning on top, fascia, window. It stands a little narrower
   than the column so the awning can overhang it, as awnings do. */
.tt-front { margin: 0; position: relative; max-width: 460px; margin-inline: auto; }
.tt-awning {
  position: relative; z-index: 2; height: 46px;
  margin: 0 -10px;
  /* Centred, so both ends stop on the same half stripe. */
  background: repeating-linear-gradient(90deg, var(--accent) 0 28px, var(--tt-paper) 28px 56px) center / 56px 100% repeat-x;
  box-shadow: inset 0 -10px 12px -8px rgba(40, 10, 5, .28), inset 0 1px 0 rgba(0, 0, 0, .12);
  border-radius: 3px 3px 0 0;
}
/* The valance: one scallop per stripe, same colours, so it reads as cloth. */
.tt-awning::after {
  content: ""; position: absolute; left: 0; right: 0; top: 100%; height: 14px;
  background:
    radial-gradient(circle at 14px 0, var(--accent) 13.5px, transparent 14px) center top / 56px 14px repeat-x,
    radial-gradient(circle at 42px 0, var(--tt-paper) 13.5px, transparent 14px) center top / 56px 14px repeat-x;
  filter: drop-shadow(0 3px 2px rgba(40, 10, 5, .18));
}
.tt-fascia {
  position: relative;
  display: grid; justify-items: center; text-align: center;
  padding: 34px 20px 20px;
  background: var(--primary);
  /* A pinstripe inside the board, the sign-painter's frame. */
  box-shadow: inset 0 0 0 7px var(--primary), inset 0 0 0 8px color-mix(in srgb, var(--tt-cream) 70%, transparent);
  color: var(--tt-cream);
}
.tt-a {
  font-family: var(--font-display); font-style: italic;
  font-size: clamp(1.7rem, 7vw, 2.3rem); line-height: 1.1;
  color: var(--tt-gold);
}
.tt-b {
  font-family: var(--font-display);
  font-size: clamp(3rem, 15vw, 5.4rem); line-height: 1.05;
  letter-spacing: .02em; margin-top: -2px;
  max-width: 100%; overflow-wrap: anywhere; hyphens: auto;
  color: var(--tt-cream);
  text-shadow: 0 2px 0 color-mix(in srgb, var(--primary) 55%, #000);
}
/* A one-word name leaves the second half empty: the first then takes the
   big roman, so the board never shows a lone small italic. */
.tt-b:empty { display: none; }
.tt-a:has(+ .tt-b:empty) {
  font-style: normal; color: var(--tt-cream);
  font-size: clamp(3rem, 15vw, 5.4rem); line-height: 1.05; overflow-wrap: anywhere;
}
.tt-a { max-width: 100%; }
.tt-street {
  margin-top: 10px; padding-top: 10px;
  border-top: 1px solid color-mix(in srgb, var(--tt-cream) 45%, transparent);
  font-size: 12.5px; font-weight: 600; letter-spacing: .2em;
  color: var(--tt-cream);
}
.tt-st { text-transform: uppercase; }
.tt-dot { margin: 0 .2em; }
/* The district in the serif italic, as a sign-writer adds the quarter: «Lyon 2e»
   keeps its lowercase ordinal. */
.tt-dist {
  font-family: var(--font-display); font-style: italic; font-weight: 400;
  font-size: 15px; letter-spacing: .02em; text-transform: none; white-space: nowrap;
}
/* The window: dark glass in the same green frame, a sheen across it, and the
   week lettered in gold leaf. A real photo, when there is one, hangs here. */
.tt-window {
  display: block;
  border: 10px solid var(--primary); border-top-width: 8px;
  padding: 22px 22px 20px;
  background:
    linear-gradient(115deg, transparent 0 34%, rgba(255, 255, 255, .07) 34% 44%, transparent 44% 58%, rgba(255, 255, 255, .04) 58% 62%, transparent 62%),
    var(--tt-glass);
  color: var(--tt-cream);
}
.tt-window .sa-photo { margin: -8px -8px 18px; width: calc(100% + 16px); max-width: none; }
.tt-label {
  display: block; text-align: center; margin-bottom: 10px;
  font-family: var(--font-display); font-style: italic; font-size: 1.5rem; line-height: 1.2;
  color: var(--tt-gold);
}
.tt-week { list-style: none; margin: 0 auto; padding: 0; max-width: 320px; font-size: 15px; font-variant-numeric: tabular-nums; }
.tt-week li {
  display: flex; flex-wrap: wrap; justify-content: space-between; column-gap: 12px;
  padding: 6px 0; border-bottom: 1px solid color-mix(in srgb, var(--tt-gold) 28%, transparent);
}
.tt-week li:last-child { border-bottom: 0; }
.tt-week .sa-d { color: var(--tt-gold); font-weight: 600; }
.tt-week .sa-h { color: var(--tt-cream); margin-left: auto; text-align: right; }

/* Phone: the shopfront is the first thing the owner sees, above the headline,
   small enough that the name, the street and the buttons share one screen.
   The window (the week) drops out: #horaires has it in full, and the status
   line under the buttons says today's. A real photo keeps the window. */
@media (max-width: 899.98px) {
  .hero-sig { padding-top: var(--s5); }
  .hero-sig-grid { gap: var(--s5); }
  .hero-sig .hero-art { order: -1; }
  .tt-front { max-width: 420px; padding-inline: 10px; }
  .tt-awning { height: 34px; }
  .tt-fascia { padding: 24px 16px 16px; }
  .tt-a { font-size: clamp(1.4rem, 6vw, 1.9rem); }
  .tt-b, .tt-a:has(+ .tt-b:empty) { font-size: clamp(2.5rem, 13vw, 3.4rem); }
  .tt-window .tt-label, .tt-window .tt-week { display: none; }
  .tt-window:not(:has(.sa-photo)) { display: none; }
  .tt-window:has(.sa-photo) { padding: 8px; }
  .tt-window .sa-photo { margin: 0; width: 100%; }
  .hero .eyebrow { margin-bottom: var(--s2); }
}
@media (min-width: 900px) {
  .hero-sig { padding-top: var(--s8); padding-bottom: var(--s9); }
  .tt-front { margin-right: 10px; }
}

/* ---- sections ---- */
section + section { border-top: 0; }
.section-title {
  font-style: italic; text-align: left;
  padding-bottom: 0; margin-bottom: var(--s5);
}
.section-title::after { content: none; }
.section-intro { text-align: left; margin-left: 0; }

/* The table: the carte section is the cloth, the carta is paper laid on it. */
#carte {
  background-color: #fff; background-image: var(--tt-gingham); background-size: 36px 36px;
  padding: var(--s8) 0;
  box-shadow: inset 0 12px 16px -12px rgba(60, 20, 10, .25), inset 0 -12px 16px -12px rgba(60, 20, 10, .25);
}
#carte .wrap {
  width: calc(100% - 32px); max-width: 640px;
  background: var(--tt-paper);
  padding: 44px 30px 36px;
  text-align: center;
  /* A double green rule printed inside the card, then the card's shadow. */
  box-shadow:
    inset 0 0 0 10px var(--tt-paper), inset 0 0 0 11px var(--primary),
    inset 0 0 0 14px var(--tt-paper), inset 0 0 0 15px var(--primary),
    0 22px 40px -20px rgba(60, 20, 10, .55), 0 2px 4px rgba(60, 20, 10, .15);
}
#carte .section-title {
  text-align: center; color: var(--accent);
  font-size: clamp(2.4rem, 10vw, 3.4rem); margin-bottom: var(--s3);
}
#carte .section-intro { text-align: center; margin: 0 auto var(--s6); font-size: 15px; max-width: 40ch; }
#carte .menu, #carte .menu-1 { max-width: none; grid-template-columns: 1fr; gap: var(--s6); }
#carte .menu-group h3 {
  display: flex; align-items: center; gap: 12px;
  font-family: var(--font-body); font-weight: 600; font-size: 12.5px;
  letter-spacing: .24em; text-transform: uppercase; color: var(--primary);
  border-bottom: 0; padding-bottom: 0; margin-bottom: var(--s2);
}
#carte .menu-group h3::before, #carte .menu-group h3::after {
  content: ""; flex: 1 1 auto; height: 1px; background: color-mix(in srgb, var(--primary) 45%, transparent);
}
#carte .menu-item { text-align: left; padding: 14px 0; border-bottom: 1px dotted color-mix(in srgb, var(--fg) 22%, transparent); }
#carte .menu-item:last-child { border-bottom: 0; }
.mi-name { font-family: var(--font-display); font-weight: 400; font-size: 1.5rem; line-height: 1.2; }
.mi-leader { border-bottom: 2px dotted color-mix(in srgb, var(--accent) 45%, transparent); }
.mi-price { color: var(--accent); font-size: 1.3rem; }
.mi-desc { font-size: 15.5px; }
#carte .hours-note {
  text-align: center; margin: var(--s5) auto 0;
  font-family: var(--font-display); font-style: italic; font-size: 17px; color: var(--fg-soft);
}
@media (min-width: 900px) {
  #carte { padding: var(--s9) 0; background-size: 44px 44px; }
  /* #carte holds the stacking context, so the sheet at z -1 paints under
     the carta's own paper and not over it. */
  #carte { position: relative; z-index: 0; }
  #carte .wrap { padding: 60px 64px 52px; position: relative; }
  /* A second sheet under the carta, skewed, so the card looks laid down by
     hand while every printed line stays upright and sharp. */
  #carte .wrap::before {
    content: ""; position: absolute; inset: 6px -8px -10px 4px; z-index: -1;
    background: #F3EBDA; transform: rotate(-1.6deg);
    box-shadow: 0 18px 34px -18px rgba(60, 20, 10, .55);
  }
}

/* Photos: an album page. White-bordered prints held by four black corners,
   the print itself still blank, waiting for the restaurant's own. */
/* The page of the album: a dark bottle-green board with a fine grain, so
   the black corners visibly hold a print to something. */
/* On the section, not on .gallery: a grid that paints its own ground shows a
   solid block in any cell with no tile (fb-0023, layout_test). */
#photos .gallery { gap: var(--s5); }
#photos {
  background:
    repeating-linear-gradient(90deg, rgba(255, 255, 255, .025) 0 1px, transparent 1px 5px),
    #23342B;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .25), inset 0 0 40px rgba(0, 0, 0, .35);
}
.photo-slot, .planche-slot, .hero-slot {
  position: relative;
  border: 0; border-radius: 0;
  padding: var(--s3);
  background:
    linear-gradient(135deg, var(--fg) 0 11px, transparent 11px) top left / 22px 22px no-repeat,
    linear-gradient(225deg, var(--fg) 0 11px, transparent 11px) top right / 22px 22px no-repeat,
    linear-gradient(45deg, var(--fg) 0 11px, transparent 11px) bottom left / 22px 22px no-repeat,
    linear-gradient(315deg, var(--fg) 0 11px, transparent 11px) bottom right / 22px 22px no-repeat,
    var(--tt-paper);
  /* No inset shadow: it would paint over the four corners. */
  box-shadow: 0 12px 20px -10px rgba(0, 0, 0, .55);
  color: var(--fg-soft);
}
.photo-slot { aspect-ratio: 4 / 3; min-height: 0; height: auto; }
.photo-slot svg, .planche-slot svg, .hero-slot svg { display: none; }
.photo-slot span, .planche-slot span, .hero-slot span {
  font-family: var(--font-display); font-style: italic; font-size: clamp(1.05rem, 4vw, 1.25rem); line-height: 1.25;
  color: var(--fg-soft);
}
.gallery > .photo-slot:nth-child(1) { transform: rotate(-1deg); }
.gallery > .photo-slot:nth-child(2) { transform: rotate(.8deg); }
.gallery > .photo-slot:nth-child(3) { transform: rotate(-.5deg); }
.gallery figure { border-radius: 0; padding: var(--s3); background: #fff; box-shadow: 0 10px 18px -12px rgba(60, 20, 10, .4); }

/* The band: a second painted board, the fascia again, cream on green. */
.cta-band {
  background: transparent; color: var(--fg);
  padding: var(--s7) 0;
}
.cta-band .wrap {
  width: calc(100% - 32px); max-width: 760px;
  background: var(--primary); color: var(--tt-cream);
  padding: clamp(36px, 7vw, 56px) clamp(20px, 5vw, 48px);
  box-shadow: inset 0 0 0 8px var(--primary), inset 0 0 0 9px color-mix(in srgb, var(--tt-cream) 70%, transparent);
}
.cta-band { text-align: left; }
.cta-band h2 { font-style: italic; font-size: clamp(2.2rem, 9vw, 3.2rem); color: var(--tt-cream); line-height: 1.15; }
.cta-band p { opacity: 1; color: var(--tt-cream); margin-left: 0; }
/* Phone: the button is the call, so the number is not printed a fifth time. */
.cta-band .cta-num { display: none; }
/* Wide: the board is lettered like the fascia. Title and line on the left,
   the number painted large on the right as the thing the board is for; the
   button goes, the painted number is the link's twin in the hero. */
@media (min-width: 900px) {
  .cta-band .wrap {
    display: grid; grid-template-columns: minmax(0, 1fr) auto; column-gap: 48px; align-items: center;
    max-width: 980px; padding: 56px 60px;
  }
  .cta-band h2, .cta-band p { grid-column: 1; }
  .cta-band p { margin-bottom: 0; }
  .cta-band .btn-oncta { display: none; }
  .cta-band .cta-num {
    display: block; grid-column: 2; grid-row: 1 / span 2; margin: 0;
    padding-left: 48px; border-left: 1px solid color-mix(in srgb, var(--tt-cream) 45%, transparent);
    font-size: clamp(2.6rem, 4.2vw, 3.6rem); line-height: 1.1; white-space: nowrap;
    color: var(--tt-gold);
    text-shadow: 0 2px 0 color-mix(in srgb, var(--primary) 55%, #000);
  }
}
.btn-oncta { background: var(--tt-cream); color: var(--primary); border-color: var(--tt-cream); box-shadow: 0 3px 0 0 color-mix(in srgb, var(--primary) 55%, #000); }
.btn-oncta:hover { background: #fff; }

/* Hours: the day names set in the serif, today's line marked in red. */
.hours th { font-family: var(--font-display); font-size: 1.15rem; color: var(--fg); font-weight: 400; }
.hours td { font-weight: 600; }
.hours th, .hours td { border-bottom: 1px dotted color-mix(in srgb, var(--fg) 25%, transparent); }
.hours tr.today th, .hours tr.today td { color: var(--accent); }
.hours tr.today th { font-style: italic; }
.addr { font-family: var(--font-display); font-size: 1.35rem; line-height: 1.35; }
.addr .label { font-family: var(--font-body); color: var(--accent); letter-spacing: .2em; }
/* The map as a postcard pinned beside the hours. */
.map-frame { border: 0; border-radius: 0; padding: 8px; background: #fff; box-shadow: inset 0 0 0 1px var(--border), 0 12px 22px -14px rgba(60, 20, 10, .45); }

/* Booking: the form on a card with the cloth's edge along its top. */
#contact form {
  position: relative; background: var(--surface);
  padding: 40px clamp(18px, 4vw, 32px) clamp(20px, 4vw, 32px);
  box-shadow: inset 0 0 0 1px var(--border), 0 16px 30px -20px rgba(60, 20, 10, .4);
}
#contact form::before {
  content: ""; position: absolute; left: 0; right: 0; top: 0; height: 11px;
  background-color: #fff; background-image: var(--tt-gingham); background-size: 22px 22px;
  background-position: 0 11px;
}
/* Wide: the left column is the table the booking is for. The cloth runs the
   full height of the form, and the intro and the call sit on a paper card. */
@media (min-width: 880px) {
  #contact .contact-layout { align-items: stretch; }
  #contact .contact-layout > div:first-child {
    /* The same cloth, washed paler: the carte above already has the loud one.
       Spelled out, since --tt-gingham resolved its colour on :root. */
    --tt-wash: color-mix(in srgb, var(--accent) 22%, transparent);
    background-color: #fff; background-size: 44px 44px;
    background-image:
      linear-gradient(90deg, var(--tt-wash) 50%, transparent 50%),
      linear-gradient(0deg, var(--tt-wash) 50%, transparent 50%);
    padding: 40px 32px;
    box-shadow: inset 0 0 0 1px var(--border), inset 0 12px 16px -12px rgba(60, 20, 10, .25);
  }
  #contact .contact-layout > div:first-child > * {
    background: var(--tt-paper); margin: 0; padding: 28px 28px 0;
  }
  #contact .contact-layout > div:first-child > .section-intro {
    font-family: var(--font-display); font-style: italic; font-size: 1.45rem; line-height: 1.35; color: var(--fg);
  }
  #contact .contact-layout > div:first-child > .hero-actions {
    padding: 20px 28px 28px;
    box-shadow: 0 18px 28px -18px rgba(60, 20, 10, .5);
  }
}
.field input, .field textarea { border-color: color-mix(in srgb, var(--fg) 35%, var(--border)); border-radius: 2px; background: var(--tt-paper); }
.field label { font-weight: 600; }


/* Sections this page does not have yet, but the next pizzeria may: the same
   idiom, so none of them falls back to a card grid with icon squares. */
.cards { gap: var(--s5); }
.card {
  background: var(--tt-paper); border: 0; border-radius: 0;
  border-top: 5px double var(--primary);
  box-shadow: inset 0 0 0 1px var(--border);
  padding: var(--s5);
}
.card .icon { width: auto; height: auto; background: none; border-radius: 0; display: block; color: var(--accent); margin-bottom: var(--s3); }
.card h3 { font-size: 1.45rem; line-height: 1.2; }
.card .card-price { color: var(--accent); font-size: 1.35rem; margin-top: var(--s3); }
.quote {
  background: var(--tt-paper); border: 0; border-radius: 0;
  border-left: 4px solid var(--accent); box-shadow: inset 0 0 0 1px var(--border);
}
.quote { margin: 0; padding: var(--s5); }
.quote blockquote { font-family: var(--font-display); font-style: italic; font-size: 1.25rem; line-height: 1.45; }
.stars { color: var(--accent); }
.p-name { font-family: var(--font-display); font-weight: 400; font-size: 1.35rem; }
.product { border-bottom: 1px dotted color-mix(in srgb, var(--fg) 25%, transparent); }
.p-badge { border-radius: 2px; text-transform: uppercase; letter-spacing: .12em; font-size: 11px; background: transparent; box-shadow: inset 0 0 0 1px var(--accent); }
.t-icon { background: transparent; border: 1.5px solid var(--accent); border-radius: 50%; }
.step-n { font-family: var(--font-display); font-weight: 400; font-size: 1.2rem; border-color: var(--accent); }
.faq-item { border-bottom: 1px dotted color-mix(in srgb, var(--fg) 30%, transparent); }
.faq-item summary { font-family: var(--font-display); font-weight: 400; font-size: 1.25rem; line-height: 1.3; }
.planche { gap: var(--s3); }
.planche-slot:nth-child(even) { transform: rotate(.6deg); }
.planche-slot:nth-child(odd) { transform: rotate(-.6deg); }

/* Footer sits under one more strip of the cloth. */
.site-foot { border-top: 0; position: relative; }
.site-foot::before {
  content: ""; position: absolute; left: 0; right: 0; top: 0; height: 11px;
  background-color: #fff; background-image: var(--tt-gingham); background-size: 22px 22px;
  background-position: 0 11px;
}
.site-foot h4 { color: var(--accent); }
.action-bar { border-top: 0; }

/* The album page is dark, so its title and intro are printed in cream. */
#photos .section-title { color: #F6EFE0; }
#photos .section-intro { color: rgba(246, 239, 224, .82); }

/* ---- the map, as a print pinned in the trattoria: warm, a little faded. ---- */
.map-frame iframe { filter: sepia(.28) saturate(.85); }

/* ---- the call, under the awning ----
   Pointing at a call button (only where there is a pointer), tabbing to it
   or pressing it slides the awning's stripe along its top edge, a short
   nudge; a press sinks the button onto its 3px step. Nothing moves until
   touched. */
.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; left: -20px; right: 0; height: 6px;
  pointer-events: none; opacity: 0;
  background: repeating-linear-gradient(90deg, color-mix(in srgb, var(--tt-cream) 70%, transparent) 0 10px, transparent 10px 20px);
  transform: translateX(0);
}
@media (hover: hover) {
  .btn-primary:hover::after, .btn-oncta:hover::after { opacity: 1; transform: translateX(10px); }
}
.btn-primary:focus-visible::after, .btn-oncta:focus-visible::after,
.btn-primary:active::after, .btn-oncta:active::after { opacity: 1; transform: translateX(10px); }
.btn-primary:active { transform: translateY(3px); }
@media (prefers-reduced-motion: no-preference) {
  .btn-primary::after, .btn-oncta::after { transition: opacity .25s ease-out, transform .5s cubic-bezier(.3, .7, .3, 1); }
}

/* ---- the lines move (owner, fb-0097) ----
   Light crosses the shop window now and then, a pane catching the street.
   The sheen passes over the glass; the week lettered on it stays put. (The
   valance sway was too small to see: owner, 2026-09-30.) */
.tt-window { position: relative; overflow: hidden; }
@media (prefers-reduced-motion: no-preference) {
  .tt-window::after {
    content: ""; position: absolute; top: 0; bottom: 0; left: 0; width: 38%; pointer-events: none;
    background: linear-gradient(90deg, transparent, rgba(255, 255, 255, .16) 45%, rgba(255, 255, 255, .22) 50%, rgba(255, 255, 255, .16) 55%, transparent);
    animation: tt-pane 7s ease-in-out infinite;
  }
  @keyframes tt-pane {
    0%, 55% { transform: translateX(-160%) skewX(-18deg); }
    85%, 100% { transform: translateX(360%) skewX(-18deg); }
  }
}
