/**
 * components.css
 * Reusable UI components — buttons (.porta-btn), cards, badges, trust bar,
 * and other shared patterns used across multiple pages.
 *
 * @package astra-child
 */

/* ── Buttons ─────────────────────────────────────────────────────────────── */

/* Base button — all variants extend this */
.porta-btn {
  display: inline-block;
  padding: var(--btn-padding);
  font-family: var(--font-body);
  font-size: var(--btn-font-size);
  font-weight: var(--btn-font-weight);
  letter-spacing: var(--btn-tracking);
  text-transform: uppercase;
  border: var(--btn-border-width) solid transparent;
  border-radius: var(--border-radius);
  cursor: pointer;
  text-decoration: none;
  /* 0.3s matches design.md §6.1 — all interactive elements use 0.3s ease */
  transition: background-color var(--duration) ease, color var(--duration) ease, border-color var(--duration) ease;
}

/* Primary — burgundy fill, white text */
.porta-btn--primary {
  background-color: var(--color-accent);
  color: var(--color-white);
  border-color: var(--color-accent);
}

.porta-btn--primary:hover {
  background-color: var(--color-accent-dark);
  border-color: var(--color-accent-dark);
  color: var(--color-white);
}

/*
 * Retired 2026-09-11 in the site-wide button consolidation — all recoverable
 * from git history, none of them used by any template any more:
 *   --secondary (gold fill)  — was already dead, referenced by no template
 *   --outline   (2px burgundy) → replaced by --hairline (1px)
 *   --light     (2px white)    → replaced by --overlay (1px)
 * The site now has three roles: --primary (solid, conversion actions),
 * --hairline (secondary on light) and --overlay (secondary on photography),
 * plus --white as the one primary action inside a burgundy band.
 */

/*
 * Overlay — transparent, hairline white outline, for buttons sitting directly
 * on photography (homepage hero and .porta-famille).
 *
 * Differs from --light deliberately: a 1px hairline instead of 2px, wider
 * letter-spacing and roomier padding read as lighter and more contemporary
 * over an image, where a heavy border competes with the photograph. The faint
 * white wash + backdrop blur keep the label legible over a busy or bright
 * region without resorting to a solid fill. Blur is cheap here — it applies to
 * a handful of small elements, unlike a full-viewport filter.
 */
.porta-btn--overlay {
  background-color: rgba(255, 255, 255, 0.08);
  color: var(--color-white);
  border: 1px solid rgba(255, 255, 255, 0.75);
  padding: 0.9rem 2.25rem;
  letter-spacing: var(--tracking-widest);
  -webkit-backdrop-filter: blur(4px);
  backdrop-filter: blur(4px);
}

/* Before :hover — equal specificity (0,2,0), so source order decides which
   colour wins when a visited link is hovered. */
.porta-btn--overlay:visited {
  color: var(--color-white);
}

/* :focus-visible rather than :focus — a mouse click would otherwise leave the
   button stuck in its filled state until it loses focus. */
.porta-btn--overlay:hover,
.porta-btn--overlay:focus-visible {
  background-color: var(--color-white);
  color: var(--color-text);
  border-color: var(--color-white);
}

/* The global focus ring is burgundy, which measures ~1.75:1 against a dark
   photograph — below WCAG 2.4.11's 3:1 minimum for focus indicators. White
   reaches ~20:1 here. Specificity (0,2,0) beats base.css's a:focus-visible. */
.porta-btn--overlay:focus-visible {
  outline-color: var(--color-white);
}

/*
 * Hairline — the light-background twin of --overlay. Same 1px rule, same wide
 * tracking and roomy padding, in burgundy, so a button reads identically
 * whether it sits on a photograph or on the page background. Use this instead
 * of --outline (2px, tighter) wherever it needs to match the hero's buttons.
 */
.porta-btn--hairline {
  background-color: transparent;
  color: var(--color-accent);
  border: 1px solid var(--color-accent);
  padding: 0.9rem 2.25rem;
  letter-spacing: var(--tracking-widest);
}

.porta-btn--hairline:visited {
  color: var(--color-accent);
}

.porta-btn--hairline:hover,
.porta-btn--hairline:focus-visible {
  background-color: var(--color-accent);
  color: var(--color-white);
  border-color: var(--color-accent);
}

/*
 * Contact Form 7 submit button.
 * CF7 outputs <input type="submit" class="wpcf7-submit"> — not a WC button, not
 * inside .woocommerce, so woocommerce.css doesn't cover it. Style here to match
 * .porta-btn--primary appearance. (CF7 itself loads on /contact only —
 * inc/contact.php; the /contact sizing is under "Contact form input styling".)
 */
/*
 * Astra ships contact-form-7-main.min.css which styles .wpcf7-submit with
 * the Customizer accent color (WooCommerce blue by default).
 * !important is required on background/border because Astra's compatibility
 * stylesheet loads after ours and uses the same class specificity.
 */
.wpcf7-submit {
  display: inline-block;
  /* !important for the same reason as background/border below: Astra's CF7
     compatibility sheet also sets padding (it rendered 15px 30px against our
     12px 28px), so without it the submit sits a size apart from every other
     primary button on the site. */
  padding: var(--btn-padding) !important;
  background-color: var(--color-accent) !important;
  color: var(--color-white) !important;
  border: var(--btn-border-width) solid var(--color-accent) !important;
  border-radius: var(--border-radius);
  font-family: var(--font-body);
  font-size: var(--btn-font-size);
  font-weight: var(--btn-font-weight);
  letter-spacing: var(--btn-tracking);
  text-transform: uppercase;
  cursor: pointer;
  transition: background-color var(--duration) ease, border-color var(--duration) ease;
}

.wpcf7-submit:hover {
  background-color: var(--color-accent-dark) !important;
  border-color: var(--color-accent-dark) !important;
  color: var(--color-white) !important;
}

/*
 * White — solid white fill for very dark backgrounds (e.g. --color-earth CTA).
 * The one primary action allowed inside a dark band, where it pairs with
 * --overlay as the secondary. It therefore borrows --overlay's proportions
 * (1px rule, roomier padding, wider tracking) rather than the base button's:
 * the two sit side by side in /domaine's CTA band, and a 2px solid next to a
 * 1px hairline reads as two unrelated components.
 */
.porta-btn--white {
  background-color: var(--color-white);
  color: var(--color-accent);
  border: 1px solid var(--color-white);
  padding: 0.9rem 2.25rem;
  letter-spacing: var(--tracking-widest);
}

/* :visited — prevent browser default blue from overriding button colours.
   Class + pseudo-class specificity (0,2,0) beats a:visited (0,1,1). */
.porta-btn--primary:visited  { color: var(--color-white); }
.porta-btn--white:visited    { color: var(--color-accent); }

/* :focus — Astra ships `button:focus { border-color: … }` (0,1,1); restate each
   variant's own border at (0,2,0) so <button>-based porta-btns keep their color.
   The visible focus indicator is the global :focus-visible ring in base.css. */
.porta-btn--primary:focus   { border-color: var(--color-accent); }
.porta-btn--white:focus     { border-color: var(--color-white); }

.porta-btn--white:hover {
  background-color: transparent;
  color: var(--color-white);
  border-color: var(--color-white);
}

/*
 * ── Primary button state set (design review B2, audit 09-DR-3) ──────────────
 * One set for every solid burgundy button — theme buttons, the product page
 * add-to-cart, the CF7 submit, « Passer la commande » and « Commander »:
 *   rest       burgundy, white label
 *   hover      --color-accent-dark (09-006)
 *   pressed    --color-accent-pressed, 1px down
 *   after a mouse click  back to rest — Astra paints a focused button with
 *              its palette slot 1 and base.css colours focused links
 *              burgundy, which left the button gold (then dark) or turned
 *              the label of « Choisir le format » burgundy on burgundy
 *   keyboard   rest colours + the 2px burgundy ring, 3px away
 *   disabled   beige, grey label, no pointer (« not yet »)
 *   loading    .is-loading: pressed colours, not clickable twice
 * !important: Astra's customizer CSS prints after ours with the same reach.
 */
.porta-btn--primary:focus,
.porta-btn--primary:focus-visible,
.wpcf7-submit:focus,
.porta-product__cart .single_add_to_cart_button:focus,
.woocommerce-cart .porta-cart-summary a.checkout-button:focus,
.woocommerce #payment #place_order:focus {
  background-color: var(--color-accent) !important;
  border-color: var(--color-accent) !important;
  color: var(--color-white) !important;
}

.porta-btn--primary:hover,
.wpcf7-submit:hover,
.porta-product__cart .single_add_to_cart_button:hover,
.woocommerce-cart .porta-cart-summary a.checkout-button:hover,
.woocommerce #payment #place_order:hover {
  background-color: var(--color-accent-dark) !important;
  border-color: var(--color-accent-dark) !important;
  color: var(--color-white) !important;
}

.porta-btn--primary:active,
.porta-btn--primary.is-loading,
.wpcf7-submit:active,
.porta-product__cart .single_add_to_cart_button:active,
.porta-product__cart .single_add_to_cart_button.loading,
.woocommerce-cart .porta-cart-summary a.checkout-button:active,
.woocommerce #payment #place_order:active {
  background-color: var(--color-accent-pressed) !important;
  border-color: var(--color-accent-pressed) !important;
  color: var(--color-white) !important;
  transform: translateY(1px);
}

.porta-btn--primary.is-loading,
.porta-product__cart .single_add_to_cart_button.loading {
  pointer-events: none;
  cursor: progress;
}

.porta-btn--primary:focus-visible,
.wpcf7-submit:focus-visible,
.porta-product__cart .single_add_to_cart_button:focus-visible,
.woocommerce-cart .porta-cart-summary a.checkout-button:focus-visible,
.woocommerce #payment #place_order:focus-visible {
  outline: 2px solid var(--color-accent) !important;
  outline-offset: 3px !important;
}

.porta-btn--primary:disabled,
.porta-btn--primary[aria-disabled="true"],
.porta-product__cart .single_add_to_cart_button:disabled,
.porta-product__cart .single_add_to_cart_button.disabled {
  background-color: var(--color-bg-alt) !important;
  border-color: var(--color-bg-alt) !important;
  color: var(--color-text-light) !important;
  opacity: 1 !important;
  cursor: not-allowed;
  transform: none;
}

/* ── Full-bleed sections ─────────────────────────────────────────────────── */

/*
 * Sections with colored backgrounds must span the full viewport, but Astra Free
 * wraps all content in .ast-container (max-width: ~1240px, margin: auto).
 * Negative margins push each section's edges to the viewport boundary — the same
 * technique Astra uses internally for .alignfull Gutenberg blocks.
 * Requires overflow-x: hidden on body (set in base.css).
 */
.porta-hero,
.porta-famille,
.porta-featured,
.porta-degustation__header,
.porta-degustation-cta,
.porta-pro,
.porta-newsletter--band {
  margin-left: calc(50% - 50vw);
  margin-right: calc(50% - 50vw);
}

/* ── Hero ─────────────────────────────────────────────────────────────────── */

.porta-hero {
  position: relative;
  min-height: calc(100svh - var(--header-height));   /* the real header: 80 / 92px (audit 09-018) */
  display: flex;
  align-items: flex-end;
  justify-content: center;
  text-align: center;
  /* Fallback color if the hero image fails to load */
  background-color: var(--color-accent);
  overflow: hidden;
}

/* Media layer: static photograph revealed from black (see keyframes below).
   Reveal timing knobs — tune after client review:
     veil fade-out    1.4s, delay 0.2s  (black lifting)
     image brightness 2.2s, delay 0.2s  (lights coming fully up, outlasts veil)
     image scale      1.05 → 1, same animation as brightness
     text entrance    0.9s, delay 1.2s  (.porta-hero__content below) */
.porta-hero__media {
  position: absolute;
  inset: 0;
  z-index: 0;
}

.porta-hero__image {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  /* object-position: center matches the previous background-position: center crop */
  object-fit: cover;
  object-position: center;
  /* Reveal darkens via brightness(), never opacity: 0 — the image is painted
     immediately, so LCP is not delayed by the animation. */
  filter: brightness(0);
  transform: scale(1.05);
  animation: portaHeroImageIn 2.2s cubic-bezier(0.22, 1, 0.36, 1) 0.2s forwards;
}

@keyframes portaHeroImageIn {
  from { filter: brightness(0); transform: scale(1.05); }
  to   { filter: brightness(1); transform: scale(1); }
}

/* Black veil above the image; fades out faster than the brightness ramp so
   the reveal reads in two phases: black lifting, then lights coming up. */
.porta-hero__veil {
  position: absolute;
  inset: 0;
  z-index: var(--z-raised);
  /* Pure-black alpha overlay — same exemption as the rgba() legibility layer */
  background-color: rgba(0, 0, 0, 1);
  pointer-events: none;
  animation: portaHeroVeilOut 1.4s ease-out 0.2s forwards;
}

@keyframes portaHeroVeilOut {
  from { opacity: 1; }
  to   { opacity: 0; }
}

/*
 * Portrait fallback framing. famille-caveau.jpg is a landscape composition, so
 * a tall phone shows only ~34% of its width — and the three of them stand left
 * of the frame's centre, so a plain centre crop cuts Jean-Daniel out entirely.
 * Biasing to 42% keeps all three in view.
 *
 * This only applies while there is no portrait crop: drop a
 * famille-caveau-mobile.jpg into assets/images/ and the <picture> source in
 * front-page.php takes over automatically, at which point this rule is moot
 * (it would frame an already-portrait file that needs no horizontal crop).
 * Landscape viewports are unaffected — there the photo is narrower than the
 * hero box, so it fills the width and only the height is cropped.
 */
@media (orientation: portrait) {
  .porta-hero__image {
    object-position: 42% center;
  }
}

/* No prefers-reduced-motion handling on the hero — deliberate client decision
   (2026-07-14): the reveal is a minor one-shot 2.4s effect, within WCAG 2.2.2's
   5s threshold. Do not re-add a reduced-motion override without asking. */

/* Dark overlay for text legibility over photography.
   rgba() is used intentionally — CSS custom properties cannot express alpha alone. */
.porta-hero::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: var(--z-raised);
  background-color: rgba(0, 0, 0, 0.28);
}

.porta-hero__content {
  position: relative;
  z-index: var(--z-raised-2);
  padding-inline: 1.5rem;
  padding-bottom: var(--space-section);
  max-width: var(--max-width-text);
  /* Fades/slides in as the image reveal is ~70% done (veil gone at 1.6s,
     brightness still ramping) — text lands on an already-readable photo. */
  opacity: 0;
  transform: translateY(16px);
  animation: portaHeroContentIn 0.9s ease-out 1.2s forwards;
}

@keyframes portaHeroContentIn {
  from { opacity: 0; transform: translateY(16px); }
  to   { opacity: 1; transform: translateY(0); }
}

/*
 * Hero wordmark. The source PNG is the black mark on transparency (the same
 * asset the footer uses), so it is recoloured rather than shipped twice:
 * brightness(0) crushes every opaque pixel to black, invert(1) flips that to
 * pure white. Same technique documented for the footer logo.
 *
 * height: auto is required, not optional — the <img> carries width/height
 * attributes for CLS, and without it the 187px height attribute would survive
 * the CSS width and squash the mark.
 */
.porta-hero__logo {
  display: block;
  width: 80px;
  height: auto;
  margin-inline: auto;
  margin-bottom: 1.5rem;
  filter: brightness(0) invert(1);
}

.porta-hero__title {
  font-family: var(--font-heading);
  font-size: var(--text-3xl);
  color: var(--color-white);
  margin-bottom: 1rem;
}

/*
 * Tagline. Carries the small uppercase treatment the "Villette, Lavaux —
 * Patrimoine mondial UNESCO" eyebrow used before it was removed (2026-08-04):
 * under a wordmark it reads as a caption rather than a sentence, and it keeps
 * the widely-tracked caps that set the tone elsewhere on the site.
 * Full opacity, not 0.9 — small caps over photography need every bit of
 * contrast they can get.
 */
.porta-hero__tagline {
  font-size: var(--text-xs);
  font-weight: 500;
  letter-spacing: var(--tracking-wider);
  text-transform: uppercase;
  color: var(--color-white);
  margin-bottom: 2rem;
}

.porta-hero__actions {
  display: flex;
  gap: 1rem;
  justify-content: center;
  flex-wrap: wrap;
}

@media (min-width: 768px) {
  .porta-hero__title {
    font-size: var(--text-5xl);
  }

  .porta-hero__logo {
    width: 110px;
  }
}

/* ── Famille & terroir (homepage section 2) ──────────────────────────────── */

/*
 * Centred text block on the page background, then a full-bleed photographic
 * band with the two CTAs centred over its lower edge.
 *
 * Restructured 2026-08-17. The heading and text used to be overlaid on a
 * full-viewport photo, which made the section a second wall of imagery right
 * after the hero. Lifting the text onto the page background gives the page
 * room to breathe and lets the photograph read as a picture rather than a
 * backdrop. One layout at every width now: the earlier stacked/overlaid split
 * at 900px only existed to stop `object-fit: cover` cropping the family out
 * from behind the text, and there is no text on the photo any more.
 */
.porta-famille {
  background-color: var(--color-bg);
  padding-top: var(--space-section-sm);
}

.porta-famille__intro {
  text-align: center;
  padding-bottom: var(--space-section-sm);
}

.porta-famille__title {
  font-size: var(--text-3xl);
  margin-bottom: 1.25rem;
}

.porta-famille__body {
  color: var(--color-text-light);
  line-height: 1.7;
  /* Centred prose column — margin-inline: auto is what centres it inside the
     wider .porta-container, text-align on the parent only centres the lines. */
  max-width: var(--max-width-text);
  margin-inline: auto;
}

/* The buttons now sit in the intro block, so nothing overlays the photo — no
   scrim, no absolute positioning. The band is a clean picture on its own. */
.porta-famille__actions {
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
  gap: 1rem;
  margin-top: 2.25rem;
}

/*
 * Below 768px the two CTAs stop fitting on one row, and content-width buttons of
 * different lengths ("Nous rendre visite" is ~35px wider than "Notre domaine")
 * read as ragged once stacked and centred.
 *
 * flex-basis 14rem gives one rule both behaviours: where a row can hold two
 * 14rem buttons they sit side by side at equal width, and where it cannot they
 * each grow to the full row. Either way their edges line up.
 *
 * True side-by-side at 390px was tried and rejected: two buttons plus the gap
 * leave ~163px each, and the longer label alone is ~158px before padding, so it
 * would need the type and padding cut far enough to look cramped and to stop
 * matching the hero's button proportions. Desktop is untouched — content-width
 * buttons there already sit side by side and centred.
 */
@media (max-width: 767px) {
  .porta-famille__actions .porta-btn {
    flex: 1 1 14rem;
    text-align: center;
  }
}

/*
 * Clips the surplus from the scaled-up image in the scroll effect below.
 *
 * MUST be `clip`, not `hidden`. `overflow: hidden` makes this element a scroll
 * container, and a view() timeline measures its subject against the nearest
 * scrollport — so the image would be measured against this box rather than the
 * page, giving it no scroll range at all and pinning the animation at 50%
 * progress forever (verified: the drift silently stopped working).
 * `overflow: clip` clips without creating a scrollport.
 */
/* This element is the <a> wrapping the band — see front-page.php for why the
   link is the media element itself rather than a wrapper inside it. */
.porta-famille__media {
  display: block;
  position: relative;
  overflow: clip;
  text-decoration: none;
  color: var(--color-white);
}

/*
 * Focus ring drawn INSIDE the band: the section is full-bleed, so an outside
 * ring would sit against the viewport edge. White because the global burgundy
 * ring measures ~1.75:1 over a photograph, under WCAG 2.4.11's 3:1.
 */
/*
 * The focus ring goes on the CAPTION, not on the <a>.
 *
 * Astra owns outline and box-shadow on links so thoroughly that neither could
 * be set here — verified by injecting `outline: 5px dashed magenta !important`
 * at runtime, which changed only outline-style while width and colour stayed at
 * their initial values, and by an inset box-shadow coming back zeroed. Astra
 * also sets `transition: all` on links, and transitions sit above author
 * !important in the cascade.
 *
 * The caption is a <span>, so none of that reaches it. Ringing the caption is
 * also better UX than ringing the band: the indicator lands on the text that
 * names the destination rather than tracing a full-bleed edge that runs off the
 * side of the viewport.
 */
.porta-famille__media:focus-visible .porta-famille__cta {
  outline: 2px solid var(--color-white);
  outline-offset: 8px;
}

/*
 * KNOWN LIMITATION — the caption's legibility varies with scroll position, and
 * is deliberately left untreated.
 *
 * Its backdrop moves with the drift, passing over both the dark table and the
 * bright bottle wall. Measured across the section's travel, mean contrast runs
 * 4.48:1 → 14.44:1 — dipping just under the 4.5:1 AA threshold — and against
 * the brightest green highlights individual letters reach ~1.05:1.
 *
 * Two fixes were built and both removed (2026-09-07): a text-shadow made no
 * visible difference at this size against a pattern that busy, and a radial
 * corner vignette helped at some scroll positions but not convincingly at
 * others. Neither was reliable enough to justify the code, so the photograph is
 * left clean.
 *
 * If this needs revisiting, the honest options are structural rather than
 * cosmetic: move the caption off the photograph, or pick a calmer image. Do not
 * reach for another shadow — that ground has been covered.
 */

/*
 * Discreet caption in the band's bottom-right corner. Deliberately not a
 * button: no border, no fill, just tracked caps and an arrow.
 *
 * Inset from the BAND's edge, not from the page's 1200px text grid. Aligning it
 * to that grid was the first attempt and it fell apart as screens widened: the
 * grid stops growing at 1200px while the band stays full-bleed, so the caption
 * drifted inward — roughly 700px from the edge at 2560px, where it no longer
 * read as a corner caption at all. A plain inset keeps it anchored to the
 * photograph it belongs to, at every width.
 */
.porta-famille__cta {
  position: absolute;
  z-index: var(--z-raised);
  right: clamp(1.5rem, 3vw, 3rem);
  bottom: clamp(1rem, 2.5vw, 2rem);
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  font-size: var(--text-xs);
  font-weight: 500;
  letter-spacing: var(--tracking-widest);
  text-transform: uppercase;
  color: var(--color-white);
  /* The whole band is the link, so the caption never needs to catch the cursor. */
  pointer-events: none;
}

/* Hairline that draws itself in on hover — the affordance for a band that is
   otherwise just a photograph. */
.porta-famille__cta-label {
  position: relative;
}

.porta-famille__cta-label::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: -0.35em;
  height: 1px;
  background-color: currentColor;
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 0.35s ease;
}

.porta-famille__cta-arrow {
  transition: transform 0.35s ease;
}

.porta-famille__media:hover .porta-famille__cta-label::after,
.porta-famille__media:focus-visible .porta-famille__cta-label::after {
  transform: scaleX(1);
}

.porta-famille__media:hover .porta-famille__cta-arrow,
.porta-famille__media:focus-visible .porta-famille__cta-arrow {
  transform: translateX(0.3rem);
}

/*
 * Hover lift on the photo uses filter, NOT transform. scroll-drift.js writes an
 * inline transform on this image on every scroll frame, so a CSS transform here
 * would be overridden and look broken. Same applies to any future hover zoom.
 */
.porta-famille__media:hover .porta-famille__image,
.porta-famille__media:focus-visible .porta-famille__image {
  filter: brightness(1.06);
}

.porta-famille__image {
  /*
   * ── The three knobs for this band. Edit here and nowhere else. ───────────
   *
   *   --focus        which point of the photo the band centres on. LOWER means
   *                  higher up the frame. The bottle display sits in the upper
   *                  half, so this stays well above 50% — it trims the empty
   *                  foreground tables from the bottom.
   *   --drift        how far the photo travels on scroll, ± of its own height.
   *   --drift-scale  headroom so that travel never exposes a bare edge.
   *                  MUST be >= 1 + (2 × drift): 12% needs >= 1.24.
   *
   * scroll-drift.js reads all of these off this element with getComputedStyle,
   * so the effect has exactly one source of truth.
   */
  --focus: 30%;
  --drift: 12%;
  --drift-scale: 1.28;

  display: block;
  width: 100%;
  /*
   * Height tracks the viewport WIDTH (40vw ≈ a 2.5:1 band), not the height, so
   * the crop stays put instead of shifting with window height.
   */
  height: clamp(220px, 40vw, 660px);
  /*
   * Never taller than the photo's own 16:9 ratio at this width (1/1.78 =
   * 56vw). Only bites on very narrow screens, where the 220px floor would
   * otherwise make the band taller than the frame and crop its width.
   */
  max-height: 56vw;
  object-fit: cover;
  object-position: center var(--focus);
}

/*
 * Scroll effect — the photograph drifts slowly as the section crosses the
 * viewport, a restrained parallax that gives the band some life.
 *
 * The motion itself lives entirely in assets/js/scroll-drift.js. This was a CSS
 * scroll-driven animation (animation-timeline: view()) with the script as a
 * Firefox fallback, but carrying both paths cost more than it bought: Firefox
 * 155 still has no animation-timeline, Safari's support is recent, and the two
 * implementations drifted apart twice in one session — once on the fill: both
 * resting state, once on a transform-feedback bug that only showed in the JS
 * path. One path means one behaviour to reason about and to test.
 *
 * The trade-off, honestly: a scroll-driven animation runs on the compositor and
 * cannot be stuttered by a busy main thread, which this cannot match. For a
 * single rAF-throttled transform on one element it is not a difference anyone
 * sees, and the page already loads this script.
 */
.porta-famille__image {
  /* Promoted once — the element is transformed on nearly every scroll frame. */
  will-change: transform;
  transition: filter 0.4s ease;
}

@media (min-width: 768px) {
  .porta-famille {
    padding-top: var(--space-section);
  }

  .porta-famille__intro {
    padding-bottom: var(--space-section);
  }

  .porta-famille__title {
    font-size: var(--text-4xl);
  }
}

/* ── Featured wines (homepage section 3) ─────────────────────────────────── */

/*
 * Warm tint separates the product block from the white sections either side —
 * without it the page runs white → white → beige footer and the wines have no
 * edge of their own. The cards themselves are --color-bg, so they lift off it.
 * (Whether the events section below should also carry a tint is still an open
 * decision — see "Pending design decisions" in CLAUDE.md.)
 *
 * The grid is .porta-catalog__grid, borrowed from woocommerce.css rather than
 * redefined: 1 column, 3 across from 768px.
 */
.porta-featured {
  background-color: var(--color-bg-alt);
}

/*
 * Two bottles per row on a phone — one per row makes the section an endless
 * scroll of oversized bottles.
 *
 * Explicit columns here rather than auto-fit: with a definite maximum (280px)
 * the auto-fit repetition count is worked out from that maximum, not the
 * minimum, so `minmax(140px, 280px)` yields a single 280px track on a 342px
 * phone container instead of the two it looks like it should.
 */
.porta-featured__grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  justify-content: center;
  gap: 1.5rem;
}

/* Phones show two bottles, one row (owner, 2026-10-26): the third wrapped
   alone onto a second row. Homepage « Quelques cuvées à découvrir » and the
   wine page's « À découvrir aussi » both use this grid. Back from 768px. */
.porta-featured__grid > :nth-child(n + 3) {
  display: none;
}

.porta-featured__more {
  margin-top: 3rem;
  text-align: center;
}

/* One discreet line of proof under the bottles (audit 06-013) — small grey
   text, not a band: the homepage keeps its photograph / wines / events rhythm. */
.porta-featured__proof {
  max-width: var(--max-width-text);
  margin: 2.5rem auto 0;
  font-size: var(--text-sm);
  line-height: 1.6;
  color: var(--color-text-light);
  text-align: center;
}

/* Underlined at rest (audit 09-021, DS § 6.4): burgundy against the grey
   line is 1.7:1 — colour alone does not mark it as a link (WCAG 1.4.1). */
.porta-featured__proof a {
  color: var(--color-accent);
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
  white-space: nowrap;
}

.porta-featured__proof a:hover,
.porta-featured__proof a:focus-visible {
  text-decoration-thickness: 2px;
}

/*
 * Bottle card — the photograph and the name, nothing else. The whole card is
 * the link; price, tasting notes and add-to-cart live on the product page.
 * Deliberately not .porta-wine-card (the /nos-vins catalogue card): a homepage
 * row of badges, descriptions, prices and buttons reads as a shop shelf rather
 * than an invitation.
 */
.porta-bottle-card {
  display: block;
  text-decoration: none;
  color: inherit;
}

/*
 * The bottle shots are JPEGs with a baked-in white background
 * (…_fond_blanc.jpg), so they cannot float directly on the warm section tint —
 * the white rectangle would show. A white panel turns that limitation into the
 * design: the bottle stands on a clean plinth, and the tint frames it.
 */
.porta-bottle-card__image {
  display: grid;
  place-items: center;
  aspect-ratio: 3 / 4;
  padding: 1.5rem;
  background-color: var(--color-white);
  border-radius: var(--border-radius);
  overflow: hidden;
}

.porta-bottle-card__image img {
  width: 100%;
  height: 100%;
  object-fit: contain; /* never crop a bottle */
  transition: transform 0.4s ease;
}

.porta-bottle-card__name {
  margin-top: 1.25rem;
  font-family: var(--font-heading);
  font-size: var(--text-lg);
  font-weight: 400;
  text-align: center;
  color: var(--color-text);
  transition: color var(--duration) ease;
}

.porta-bottle-card:hover .porta-bottle-card__image img,
.porta-bottle-card:focus-visible .porta-bottle-card__image img {
  transform: scale(1.04);
}

.porta-bottle-card:hover .porta-bottle-card__name,
.porta-bottle-card:focus-visible .porta-bottle-card__name {
  color: var(--color-accent);
}

@media (min-width: 768px) {
  /* Capped tracks so three bottles never balloon on a wide screen; auto-fit
     collapses the unused track when only one or two wines are featured, and
     justify-content keeps whatever remains centred. */
  .porta-featured__grid {
    grid-template-columns: repeat(auto-fit, minmax(0, 280px));
    gap: 3rem;
  }

  .porta-featured__grid > :nth-child(n + 3) {
    display: block;
  }
}

/* ── Section headings (shared pattern) ───────────────────────────────────── */

.porta-section-header {
  text-align: center;
  margin-bottom: 3rem;
}

.porta-section-header__label {
  display: block;
  font-size: var(--eyebrow-size);
  font-weight: var(--eyebrow-weight);
  letter-spacing: var(--eyebrow-tracking);
  text-transform: uppercase;
  color: var(--color-accent);   /* kickers are burgundy (DS § 2.1, audit 00-043) */
  margin-bottom: 0.5rem;
}

/*
 * Narrative tier (the default) — see "Section heading tiers" further down.
 * Centred by .porta-section-header; carries no gold rule.
 */
.porta-section-header__title {
  font-size: var(--text-3xl);
}

@media (min-width: 768px) {
  .porta-section-header__title {
    font-size: var(--text-4xl);
  }
}

/*
 * Collection tier — one rung down, left-aligned, gold rule beneath (the rule
 * itself is declared with the other tier styles further down). Alignment is
 * restated here rather than left to the container so the modifier works
 * wherever it is used.
 */
.porta-section-header__title--index {
  font-size: var(--text-2xl);
  text-align: left;
}

@media (min-width: 768px) {
  .porta-section-header__title--index {
    font-size: var(--text-3xl);
  }
}

/* ── Featured wines grid ─────────────────────────────────────────────────── */

/* ── Events carousel ─────────────────────────────────────────────────────── */

/* Header row: title left, arrow buttons right */
.porta-events__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 2rem;
}

.porta-events__title {
  font-family: var(--font-heading);
  font-size: var(--text-2xl);
  margin: 0;
}

@media (min-width: 768px) {
  .porta-events__title {
    font-size: var(--text-3xl);
  }
}

/* Arrow buttons — circular, burgundy outline */
.porta-events__arrows {
  display: flex;
  gap: 0.5rem;
  flex-shrink: 0;
}

.porta-events__arrow {
  width: 44px;
  height: 44px;
  border: 1px solid var(--color-accent);
  border-radius: 50%;
  background: transparent;
  color: var(--color-accent);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: background var(--duration-fast), color var(--duration-fast);
  padding: 0;
}

.porta-events__arrow:hover:not(:disabled) {
  background: var(--color-accent);
  color: var(--color-white);
}

.porta-events__arrow:disabled {
  opacity: 0.3;
  cursor: default;
}

/* Viewport clips overflow — shows only the visible card(s) */
.porta-events__viewport {
  overflow: hidden;
}

/* Track slides horizontally via JS transform */
.porta-events__track {
  display: flex;
  gap: 2rem;
  transition: transform 0.35s ease;
  will-change: transform;
}

/* Mobile: 1 card fills the full viewport */
.porta-events__track .porta-event-card {
  flex: 0 0 100%;
  min-width: 0;
}

/* Desktop: 2 cards side by side — each half minus half the gap */
@media (min-width: 768px) {
  .porta-events__track .porta-event-card {
    flex: 0 0 calc(50% - 1rem);
  }
}

/* ── Single evenement page ───────────────────────────────────────────────── */
/* Hide "By [author] / [date]" — not relevant context for event posts */
.single-evenement .entry-meta {
  display: none;
}

/* ── Wine card ───────────────────────────────────────────────────────────── */

.porta-wine-card {
  /* relative: anchors the distinction medal (.porta-medal--card) */
  position: relative;
  background-color: var(--color-bg);
  border-radius: var(--border-radius);
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

/*
 * Distinction medal over the bottle photo — template-parts/product-medal.php.
 *
 * It is a SIBLING of .porta-wine-card__image, not a child: the hover rule
 * `.porta-wine-card:hover .porta-wine-card__image img` zooms every image inside
 * the photo link, and a medal in there would scale with the bottle. Being
 * first in the card, the photo occupies the card's top edge, so offsets from
 * the card's corner land on the photo's corner.
 *
 * Top-LEFT, matching the product page, where the gallery's magnifier icon
 * already owns the top-right corner.
 *
 * pointer-events: none — the medal sits over the photo link, and a click on it
 * must still reach the product page.
 */
.porta-medal {
  position: absolute;
  z-index: var(--z-raised-2);
  display: block;
  height: auto;
  pointer-events: none;
  /* a soft lift so the gold disc separates from a white bottle background */
  filter: drop-shadow(0 1px 2px rgba(26, 26, 26, 0.18));
}

.porta-medal--card {
  top: 0.75rem;
  left: 0.75rem;
  width: 56px;
}

@media (min-width: 768px) {
  .porta-medal--card {
    width: 64px;
  }
}

/* Highlighted treatment for homepage featured products */
.porta-wine-card--featured {
  box-shadow: 0 4px 24px rgba(0, 0, 0, 0.08);
}

.porta-wine-card__image {
  /*
   * Fixed height rather than aspect-ratio keeps the card compact at any column
   * width. With aspect-ratio: 3/4, a 580px desktop column produces a 773px-tall
   * image — card body (name, price, CTA) falls below the fold.
   * object-fit: contain on the img shows the full bottle without cropping
   * (correct for tall product images on a white background).
   * White background (not --color-bg-alt) so the bottle photo blends cleanly.
   */
  height: 280px;
  background-color: var(--color-white);
  overflow: hidden;
}

@media (min-width: 768px) {
  .porta-wine-card__image {
    height: 320px;
  }
}

.porta-wine-card__image img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  /* padding gives the bottle visual breathing room on the white background */
  padding: 0.75rem;
  box-sizing: border-box;
  transition: transform 0.4s ease;
}

.porta-wine-card:hover .porta-wine-card__image img {
  transform: scale(1.03);
}

.porta-wine-card__body {
  padding: 1.25rem;
  display: flex;
  flex-direction: column;
  flex: 1;
}

.porta-wine-card__badge {
  display: inline-block;
  font-size: var(--eyebrow-size);
  font-weight: var(--eyebrow-weight);
  letter-spacing: var(--eyebrow-tracking);
  text-transform: uppercase;
  color: var(--color-accent);
  margin-bottom: 0.5rem;
}

.porta-wine-card__title {
  font-size: var(--text-xl);
  margin-bottom: 0.5rem;
}

/* Translated descriptor under the name — German and English only (audit 07-003). */
.porta-wine-card__descriptor {
  margin: -0.25rem 0 0.5rem;
  font-size: var(--text-sm);
  font-style: italic;
  color: var(--color-text-light);
}

/* "Millésime 2024" under the name (wine sheet, inc/wine-sheet.php). Pulled up
   against the title it qualifies; burgundy like the vintage chip on the product page. */
.porta-wine-card__vintage {
  margin: -0.25rem 0 0.5rem;
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--color-accent);
}

.porta-wine-card__desc {
  font-size: var(--text-sm);
  color: var(--color-text-light);
  line-height: 1.6;
  margin-bottom: 1rem;
  flex: 1;
}

.porta-wine-card__footer {
  /*
   * Always stack price above a full-width button. With the previous
   * row layout + flex-wrap, cards with a single price (e.g. "CHF 12.00")
   * kept price and button side-by-side, while cards with a price range
   * (variable products: "CHF 12.00 – CHF 18.00") wrapped the button to
   * a new line — so adjacent cards in the grid had mismatched footers.
   * Stacking uniformly costs nothing in vertical rhythm and guarantees
   * a consistent look regardless of price format.
   */
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 0.75rem;
  margin-top: auto;
}

.porta-wine-card__price {
  font-size: var(--text-lg);
  font-weight: 700;
  color: var(--color-accent);
}

/* Stretch the cart button (and "indisponible" fallback) to full footer
   width so every card in the grid has identical edge alignment. */
.porta-wine-card__footer .porta-btn,
.porta-wine-card__footer .porta-wine-card__unavailable {
  width: 100%;
  text-align: center;
}

/* One height for both buttons of a row (audit 09-012): « Ajouter au panier »
   is a form <button> (Astra line-height 1 → 39–42px) and « Choisir le
   format » a link (body line-height → 46–50px). A flex box with one
   min-height and line-height makes both 46px — above the 44px touch target. */
.porta-wine-card__footer .porta-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 46px;
  line-height: 1.3;
}

/* ── Event card ──────────────────────────────────────────────────────────── */

.porta-event-card {
  background-color: var(--color-bg-alt);
  border-radius: var(--border-radius);
  overflow: hidden;             /* image respects border-radius at top */
  display: flex;
  flex-direction: column;
  position: relative;           /* anchor for the stretched link ::after */
}

/* Thumbnail — 16:6 (≈ 16:9 height reduced by 1/3) */
.porta-event-card__image {
  aspect-ratio: 16 / 6;
  overflow: hidden;
  background-color: var(--color-bg);
}

/* No-photo placeholder — beige field with a muted grape icon, same ratio
   so card heights stay even with photographed neighbours (design.md §4.3) */
.porta-event-card__image--placeholder {
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: var(--color-bg-alt);
  color: color-mix(in srgb, var(--color-gold) 55%, transparent);
}

.porta-event-card__image img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  transition: transform 0.4s ease;
}

.porta-event-card:hover .porta-event-card__image img {
  transform: scale(1.03);
}

/* Padded text content below the image */
.porta-event-card__body {
  padding: 1.5rem;
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  flex: 1;
}

.porta-event-card__date {
  font-size: var(--eyebrow-size);
  font-weight: var(--eyebrow-weight);
  letter-spacing: var(--eyebrow-tracking);
  text-transform: uppercase;
  color: var(--color-gold-text);
}

.porta-event-card__title {
  font-size: var(--text-xl);
}

/* Stretched link: ::after covers the whole card, making it fully clickable.
   Screen readers see only the title text — no duplicate links. */
.porta-event-card__link::after {
  content: '';
  position: absolute;
  inset: 0;
}

.porta-event-card__lieu {
  font-size: var(--text-sm);
  color: var(--color-text-light);
  margin: 0;
}

.porta-event-card__excerpt {
  font-size: var(--text-sm);
  color: var(--color-text-light);
  line-height: 1.6;
}

/* ── Page intro band (template-parts/page-intro.php) ────────────────────────
 * The tint band opening /actualites, /contact, /degustation and the legal
 * pages — one rule instead of four copies (audit 02-012). Height rules live
 * in base.css. /degustation overrides the background with its photo further
 * down (.porta-degustation__header, same specificity, later in the file).
 * ───────────────────────────────────────────────────────────────────────── */
.porta-page-band {
  background-color: var(--color-bg-alt);
  text-align: center;
  margin-left: calc(50% - 50vw);
  margin-right: calc(50% - 50vw);
}

.porta-page-band__intro {
  max-width: var(--max-width-text);
  margin-inline: auto;
  margin-top: 1rem;
  color: var(--color-text-light);
  font-size: var(--text-lg);
  line-height: 1.7;
}

/* ── Contact page ────────────────────────────────────────────────────────── */

/* The intro band is .porta-page-band (see "Page intro band" below). */

/*
 * Panel + form. The panel comes first in the markup, so on a phone the three
 * one-tap actions (call, write, directions) sit right under the title — most
 * visitors on a phone want one of those, not the form. On desktop the panel
 * is the narrow left column, so the visual order still matches the markup.
 */
.porta-contact__grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 2.5rem;
  align-items: start;
}

@media (min-width: 768px) {
  .porta-contact__grid {
    grid-template-columns: 2fr 3fr;
    gap: 3rem;
  }
}

@media (min-width: 1280px) {
  .porta-contact__grid {
    gap: 4rem;
  }
}

/* Column headings ("Nous joindre", "Écrivez-nous"). Bespoke on purpose: these
   head a column, not a section, so they stay outside the section heading
   tiers and carry no gold rule. */
.porta-contact__title {
  font-family: var(--font-heading);
  font-size: var(--text-2xl);
  line-height: 1.2;
  color: var(--color-text);
  margin: 0 0 1.25rem;
}

/* "Nous joindre" panel — the same beige as the page header band */
.porta-contact__panel {
  background-color: var(--color-bg-alt);
  border-radius: var(--border-radius);
  padding: 1.5rem;
}

@media (min-width: 768px) {
  .porta-contact__panel {
    padding: 2rem;
  }
}

/* Call / write / directions — white tiles, 56px+ tall: comfortable thumb targets */
.porta-contact__actions {
  list-style: none;
  margin: 0 0 2rem;
  padding: 0;
  display: grid;
  gap: 0.5rem;
}

.porta-contact__action {
  display: flex;
  align-items: center;
  gap: 0.875rem;
  min-height: 56px;
  padding: 0.75rem 1rem;
  background-color: var(--color-white);
  border: 1px solid rgba(26, 26, 26, 0.08);
  border-radius: var(--border-radius);
  color: var(--color-text);
  text-decoration: none;
  transition: border-color var(--duration) ease, box-shadow var(--duration) ease;
}

.porta-contact__action:hover,
.porta-contact__action:focus-visible {
  border-color: var(--color-accent);
  box-shadow: 0 0 0 1px var(--color-accent);
  color: var(--color-text);
}

.porta-contact__icon {
  flex-shrink: 0;
  color: var(--color-accent);
}

.porta-contact__action-text {
  display: flex;
  flex-direction: column;
  min-width: 0; /* lets a long e-mail wrap instead of widening the tile */
}

.porta-contact__action-label {
  font-size: var(--eyebrow-size);
  font-weight: var(--eyebrow-weight);
  letter-spacing: var(--eyebrow-tracking);
  text-transform: uppercase;
  color: var(--color-accent);
}

.porta-contact__action-value {
  font-size: var(--text-base);
  font-style: normal; /* reset browser italic on <address> */
  margin: 0;          /* and Astra's 1.5em bottom margin on it */
  line-height: 1.45;
  overflow-wrap: anywhere;
}

/* Hours and access — label + short list, separated by a hairline */
.porta-contact__block + .porta-contact__block {
  margin-top: 1.75rem;
  padding-top: 1.75rem;
  border-top: 1px solid rgba(26, 26, 26, 0.1);
}

/* Burgundy, not gold: gold small caps on this beige fail contrast (~2:1). */
.porta-contact__label {
  font-family: var(--font-body);
  font-size: var(--eyebrow-size);
  font-weight: var(--eyebrow-weight);
  letter-spacing: var(--eyebrow-tracking);
  line-height: 1.4;
  text-transform: uppercase;
  color: var(--color-accent);
  margin: 0 0 0.75rem;
}

.porta-contact__hours,
.porta-contact__access {
  list-style: none;
  margin: 0;
  padding: 0;
  line-height: 1.7;
  color: var(--color-text);
}

.porta-contact__hours li + li,
.porta-contact__access li + li {
  margin-top: 0.375rem;
}

.porta-contact__access a {
  color: var(--color-accent);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.porta-contact__hours .porta-hours__when {
  font-weight: 500;
}

.porta-contact__hours .porta-hours__note {
  color: var(--color-text-light);
}

.porta-contact__more {
  display: inline-block;
  margin-top: 1rem;
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--color-accent);
  text-decoration: none;
}

/* Underline rather than gold on hover — gold text on beige is unreadable. */
.porta-contact__more:hover,
.porta-contact__more:focus-visible {
  color: var(--color-accent);
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* Form column: note under the heading, privacy line under the form */
.porta-contact__form-note {
  margin: -0.5rem 0 1.5rem;
  font-size: var(--text-sm);
  color: var(--color-text-light);
}

.porta-contact__privacy {
  margin: 1.25rem 0 0;
  font-size: var(--text-sm);
  line-height: 1.6;
  color: var(--color-text-light);
}

.porta-contact__privacy a {
  color: var(--color-accent);
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* Full-bleed map — no section padding, tiles fill edge to edge */
.porta-contact__map {
  margin-left: calc(50% - 50vw);
  margin-right: calc(50% - 50vw);
}

.porta-contact__map iframe {
  display: block;
  width: 100%;
  /* 300px mobile / 400px desktop — design.md §5.5 */
  height: 300px;
  border: none;
}

@media (min-width: 768px) {
  .porta-contact__map iframe {
    height: 400px;
  }
}

/* ── Degustation page ────────────────────────────────────────────────────── */

/* Full-bleed photo header — same negative-margin technique as .porta-hero.
   Drop assets/images/hero-degustation.jpg to activate the photo.
   Fallback background-color shows until the image is present. */
/* No min-height of its own: it uses the 190px shared by every page intro band
   in base.css, so this band matches /nos-vins, /actualites and /contact instead
   of being sized by the viewport. It carried min-height: 36vh until 2026-09-11,
   which made it the tallest band on the site and a different height on every
   screen — the photo does not need the extra room to read. */
/*
 * Photo page bands — page-intro.php adds .porta-page-band--photo when it is
 * given a photo: /degustation, /actualites (audit 09-DR-13) and /contact
 * (09-DR-O1). Same height as every band (270px, base.css); a 40 % veil and
 * white text over the photo. Each page sets only its photo's focus below.
 */
.porta-page-band--photo {
  position: relative;
  background-color: var(--color-earth);  /* fallback until the image is present */
}

.porta-page-band--photo::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: var(--z-raised); /* above the photo, which comes earlier in the tree */
  background-color: rgba(0, 0, 0, 0.4);
}

.porta-page-band--photo .porta-container {
  position: relative;
  z-index: var(--z-raised-2);
}

.porta-page-band--photo .porta-section-header__title {
  color: var(--color-white);
  text-shadow: 0 1px 12px rgba(0, 0, 0, 0.45);
}

.porta-page-band--photo .porta-page-band__intro {
  color: rgba(255, 255, 255, 0.88);
  text-shadow: 0 1px 12px rgba(0, 0, 0, 0.45);
}

/* /actualites — harvesters carrying crates on the terraces above the lake
   (211010-ILCE-9M2-0030); /contact — terraces and a village with its church
   (211010-ILCE-9M2-0188). The desktop files are already cut to the band. */
.porta-actualites__header .porta-bg-photo img {
  object-position: center 18%;
}

.porta-contact__header .porta-bg-photo img {
  object-position: center 50%;
}

.porta-degustation__header {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: var(--color-earth);  /* fallback until image is dropped in */
  text-align: center;
}

/* The photo is a <picture> printed by porta_bg_photo() (audit 03-009), no
   longer a CSS background: found in the HTML, it loads at once. Photo _DSC7766
   (July 2026 shoot). Positioned low: the very wide desktop band then shows the
   lake, the terraced vines with a village and a terrace table, rather than a
   strip of open water. Cache-busting is automatic (filemtime). */
.porta-degustation__header .porta-bg-photo img {
  object-position: center 70%;
}

/* Overlay for text legibility: the terrace photo is bright (sky, lake), so
   white text still needs it, a little lighter than for the old night shot.
   The intro line also gets a soft shadow — it runs over busy vine leaves. */
.porta-degustation__header .porta-section-header__title,
.porta-degustation__intro {
  text-shadow: 0 1px 12px rgba(0, 0, 0, 0.45);
}

.porta-degustation__header::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: var(--z-raised); /* above the photo, which comes later in the tree */
  background-color: rgba(0, 0, 0, 0.4);
}

/* Content sits above the overlay */
.porta-degustation__header .porta-container {
  position: relative;
  z-index: var(--z-raised);
}

/* White text on photo background */
.porta-degustation__header .porta-section-header__label {
  color: var(--color-bg-alt);   /* light on photographs (design review B5) */
}

.porta-degustation__header .porta-section-header__title {
  color: var(--color-white);
}

.porta-degustation__intro {
  max-width: var(--max-width-text);
  margin-inline: auto;
  margin-top: 1rem;
  color: rgba(255, 255, 255, 0.88);
  /* --text-lg like every page intro band (.porta-page-band__intro,
     .porta-catalog__intro); repeated here only for the white colour above. */
  font-size: var(--text-lg);
  line-height: 1.7;
}

/* ── In-page menu (anchor-nav.js) ── */

/*
 * Sticky just under the site header; --anchor-nav-top is the header's
 * measured bottom (anchor-nav.js). Same look as the /domaine menu: frosted
 * white bar, pill links, burgundy pill for the section in view. Four short
 * links fit on one row down to ~360px; below that the row scrolls sideways.
 * z-index 99 keeps it under the header (100, header.css).
 */
.porta-anchor-nav {
  position: sticky;
  top: var(--anchor-nav-top, 80px);
  z-index: var(--z-anchor-nav);
  margin-left: calc(50% - 50vw);
  margin-right: calc(50% - 50vw);
  background-color: rgba(255, 255, 255, 0.94);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--color-bg-alt);
}

.porta-anchor-nav ul {
  display: flex;
  gap: 0.125rem;
  list-style: none;
  margin: 0 auto;
  /* One bar for both pages: 0.375rem + 44px links = 56px (design review
     B7-2/3, audit 09-DR-12; /domaine's bar was 68px, /degustation's 55px). */
  padding: 0.375rem 0.5rem;
  max-width: var(--max-width);
  overflow-x: auto;
  scrollbar-width: none;
}

.porta-anchor-nav ul::-webkit-scrollbar {
  display: none;
}

.porta-anchor-nav li {
  flex-shrink: 0;
}

/* Centred with auto margins rather than justify-content: center — when the row
   overflows, a centred flex row clips its first link out of scroll reach;
   auto margins collapse to 0 instead and the row scrolls from its start. */
.porta-anchor-nav li:first-child { margin-left: auto; }
.porta-anchor-nav li:last-child  { margin-right: auto; }

.porta-anchor-nav a {
  display: flex;
  align-items: center;
  min-height: var(--tap-size);   /* 44px on every screen (audit 09-DR-12) */
  padding: 0 0.625rem;
  border-radius: var(--radius-pill);
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--color-text-light);
  text-decoration: none;
  white-space: nowrap;
  transition: color 0.15s ease, background-color 0.15s ease;
}

.porta-anchor-nav a:hover {
  color: var(--color-accent);
  background-color: var(--color-bg-alt);
}

.porta-anchor-nav a.is-active,
.porta-anchor-nav a.is-active:hover {
  color: var(--color-white);
  background-color: var(--color-accent);
}

@media (min-width: 768px) {
  .porta-anchor-nav ul {
    gap: 0.25rem;
    padding-inline: 1rem;
  }
  .porta-anchor-nav a {
    padding-inline: 1.125rem;
  }
}

/* ── Au domaine — slim beige band under the menu ── */

.porta-visit-band {
  background-color: var(--color-bg-alt);
  margin-left: calc(50% - 50vw);
  margin-right: calc(50% - 50vw);
  padding-block: 1.75rem;
}

.porta-visit-band__grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1.25rem;
}

@media (min-width: 768px) {
  .porta-visit-band__grid {
    grid-template-columns: 1fr 1fr;
    gap: 1.5rem 2.5rem;
  }
  .porta-visit-band__cta {
    grid-column: 1 / -1;
  }
}

@media (min-width: 1280px) {
  .porta-visit-band__grid {
    grid-template-columns: 1fr 1fr auto;
    align-items: center;
  }
  .porta-visit-band__cta {
    grid-column: auto;
  }
}

.porta-visit-band__hours {
  list-style: none;
  margin: 0;
  padding: 0;
  line-height: 1.7;
}

.porta-visit-band__hours .porta-hours__when {
  font-weight: 500;
}

.porta-visit-band__hours .porta-hours__note {
  color: var(--color-text-light);
}

.porta-visit-band__text {
  margin: 0;
  line-height: 1.7;
}

.porta-visit-band__text a {
  color: var(--color-accent);
  font-weight: 500;
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* ── Shared bits (formules, entreprises, offrir) ── */

/* Small-caps label for secondary headings — burgundy, never gold (contrast on
   beige). Replaces the burgundy-underlined block titles that repeated 13
   times on the first version and diluted the accent. */
.porta-tastings__label {
  font-family: var(--font-body);
  font-size: var(--eyebrow-size);
  font-weight: var(--eyebrow-weight);
  letter-spacing: var(--eyebrow-tracking);
  line-height: 1.4;
  text-transform: uppercase;
  color: var(--color-accent);
  margin: 0 0 0.75rem;
}

/* Lead line under a centred section heading */
.porta-tastings__lead {
  max-width: var(--max-width-text);
  margin: 1.25rem auto 0;
  color: var(--color-text-light);
  font-size: var(--text-lg);
  line-height: 1.7;
}

.porta-tastings__fine {
  margin: 1.25rem 0 0;
  font-size: var(--text-sm);
  color: var(--color-text-light);
  text-align: center;
}

/* Short dash-led list (included, seminar details, access) */
.porta-tastings__included {
  list-style: none;
  margin: 0;
  padding: 0;
}

.porta-tastings__included li {
  position: relative;
  padding: 0 0 0 1.375rem;
  margin-bottom: 0.625rem;
  line-height: 1.7;
  color: var(--color-text);
}

.porta-tastings__included li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0.75em;
  width: 0.75rem;
  height: 2px;
  background-color: var(--color-gold);
}

.porta-tastings__included a {
  color: var(--color-accent);
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* Name (+ description) left, price right — snacks and vouchers */
.porta-price-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.porta-price-list li {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 1rem;
  padding-block: 0.5rem;
  border-bottom: 1px solid rgba(26, 26, 26, 0.08);
}

.porta-price-list__name {
  font-weight: 500;
  color: var(--color-text);
}

.porta-price-list__desc {
  display: block;
  font-weight: 400;
  font-size: var(--text-sm);
  color: var(--color-text-light);
}

.porta-price-list__price {
  font-weight: 500;
  color: var(--color-text);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* ── Formules: Découverte / Lavaux / Héritage ── */

.porta-formats__grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1.5rem;
}

@media (min-width: 768px) {
  .porta-formats__grid {
    grid-template-columns: repeat(3, 1fr);
    gap: 2rem;
  }
}

.porta-format-card {
  background-color: var(--color-bg-alt);
  border-radius: var(--border-radius);
  padding: 2rem 1.5rem 1.5rem;
  display: flex;
  flex-direction: column;
}

/* "3 vins · 45 min" — burgundy, not gold: gold small caps fail contrast on beige */
.porta-format-card__meta {
  font-size: var(--eyebrow-size);
  font-weight: var(--eyebrow-weight);
  letter-spacing: var(--eyebrow-tracking);
  text-transform: uppercase;
  color: var(--color-accent);
  margin: 0 0 0.5rem;
}

.porta-format-card__title {
  font-family: var(--font-heading);
  font-size: var(--text-2xl);
  color: var(--color-text);
  margin: 0 0 0.5rem;
}

.porta-format-card__desc {
  font-size: var(--text-base);
  color: var(--color-text-light);
  line-height: 1.7;
  flex: 1; /* pushes the price block to the bottom, so the three cards align */
  margin: 0 0 1.5rem;
}

.porta-format-card__price {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0.25rem 0.5rem;
  margin: 0 0 1rem;
}

.porta-format-card__amount {
  font-family: var(--font-heading);
  font-size: var(--text-3xl);
  line-height: 1;
  color: var(--color-accent);
  font-variant-numeric: tabular-nums;
}

.porta-format-card__unit {
  font-size: var(--text-sm);
  color: var(--color-text-light);
}

/* Small-group and with-snack prices: label left, price right */
.porta-format-card__rows {
  margin: 0;
  border-top: 1px solid color-mix(in srgb, var(--color-accent) 15%, transparent);
  padding-top: 0.75rem;
  font-size: var(--text-sm);
}

.porta-format-card__rows > div {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  padding-block: 0.25rem;
}

.porta-format-card__rows dt {
  color: var(--color-text-light);
}

.porta-format-card__rows dd {
  margin: 0;
  font-weight: 500;
  color: var(--color-text);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* Booking button + phone, centred under the cards */
.porta-tastings__actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: 0.75rem 1.5rem;
  margin-top: 2rem;
}

.porta-tastings__actions > a:not(.porta-btn) {
  color: var(--color-accent);
  font-weight: 500;
  text-decoration: none;
}

/* Purchase credit — the offer's hook, so it gets its own framed note */
.porta-tastings__credit {
  max-width: var(--max-width-text);
  margin: 2.5rem auto 0;
  padding: 1.5rem 1.5rem 1.25rem;
  border: 1px solid var(--color-accent);
  border-radius: var(--border-radius);
  text-align: center;
}

.porta-tastings__credit-title {
  font-family: var(--font-heading);
  font-size: var(--text-2xl);
  line-height: 1.25;
  color: var(--color-accent);
  margin: 0 0 0.5rem;
}

.porta-tastings__credit-text {
  color: var(--color-text-light);
  line-height: 1.7;
  margin: 0;
}

/* Included + snacks, side by side from tablet up */
.porta-tastings__extras {
  display: grid;
  grid-template-columns: 1fr;
  gap: 2.5rem;
  margin-top: 3rem;
}

@media (min-width: 768px) {
  .porta-tastings__extras {
    grid-template-columns: repeat(2, 1fr);
    gap: 3rem;
  }
}

/* ── Photo band — full-bleed, between the formules and the companies ── */

/*
 * Phone: the family photo full width, the two others side by side below.
 * 768px+: three photos in one row, the family one slightly wider.
 */
.porta-photo-band {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 4px;
  margin-left: calc(50% - 50vw);
  margin-right: calc(50% - 50vw);
}

.porta-photo-band__img {
  display: block;
  width: 100%;
  height: 160px;
  object-fit: cover;
}

.porta-photo-band__img--wide {
  grid-column: 1 / -1;
  height: 240px;
  object-position: center 35%; /* keeps the family's faces in the crop */
}

@media (min-width: 768px) {
  .porta-photo-band {
    grid-template-columns: 1.4fr 1fr 1fr;
  }
  .porta-photo-band__img,
  .porta-photo-band__img--wide {
    grid-column: auto;
    height: 340px;
  }
}

@media (min-width: 1280px) {
  .porta-photo-band__img,
  .porta-photo-band__img--wide {
    height: 420px;
  }
}

/* ── Photo + text split (entreprises, offrir) ── */

.porta-split {
  display: grid;
  grid-template-columns: 1fr;
  gap: 2rem;
  align-items: start;
}

@media (min-width: 768px) {
  .porta-split {
    grid-template-columns: 5fr 7fr;
    gap: 3rem;
    align-items: stretch;
  }
  .porta-split--reverse {
    grid-template-columns: 7fr 5fr;
  }
  .porta-split--reverse .porta-split__media {
    order: 2;
  }
}

@media (min-width: 1280px) {
  .porta-split {
    gap: 4rem;
  }
}

.porta-split__media {
  min-width: 0;
}

/* Phone: 3:2 frame. Side by side: the photo fills the column height, so it
   matches the text beside it whatever its length. */
.porta-split__img {
  display: block;
  width: 100%;
  aspect-ratio: 3 / 2;
  height: auto;
  object-fit: cover;
  border-radius: var(--border-radius);
}

@media (min-width: 768px) {
  .porta-split__img {
    aspect-ratio: auto;
    height: 100%;
    min-height: 360px;
  }
}

.porta-split__body {
  min-width: 0;
}

.porta-split__body > .porta-btn {
  margin-top: 1.75rem;
}

.porta-split__lead {
  color: var(--color-text-light);
  font-size: var(--text-lg);
  line-height: 1.7;
  margin: 0 0 1.75rem;
}

/* Left-aligned narrative heading: alignment follows the text column below it
   (CLAUDE.md, "Section heading tiers"), so the gold rule goes flush left. */
.porta-section-header--left {
  text-align: left;
  margin-bottom: 1.5rem;
}

.porta-section-header--left h2.porta-section-header__title::after {
  margin-inline: 0;
}

/* ── Entreprises — beige band (full-bleed, see the list at the top) ── */

.porta-pro {
  background-color: var(--color-bg-alt);
}

.porta-pro__title {
  font-family: var(--font-heading);
  font-size: var(--text-2xl);
  color: var(--color-text);
  margin: 0 0 0.25rem;
}

/* The seminar offers (half day / day) — the shared price list, a little
   space before the included lines (client, 2026-10-26). */
.porta-pro__offers {
  margin: 0.75rem 0 1rem;
}

/* Company gifts + catered events: two short notes under the seminar */
.porta-pro__more {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1.25rem 2rem;
  margin-top: 1.75rem;
  padding-top: 1.5rem;
  border-top: 1px solid color-mix(in srgb, var(--color-accent) 15%, transparent);
}

@media (min-width: 1280px) {
  .porta-pro__more {
    grid-template-columns: 1fr 1fr;
  }
}

.porta-pro__more p,
.porta-gifts__row p {
  margin: 0;
  color: var(--color-text-light);
  line-height: 1.7;
}

/* ── À offrir ── */

.porta-gifts__note {
  margin: 0.75rem 0 0;
  font-size: var(--text-sm);
  color: var(--color-text-light);
}

.porta-gifts__row {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1.5rem 2rem;
  margin-top: 1.75rem;
}

@media (min-width: 1280px) {
  .porta-gifts__row {
    grid-template-columns: 1fr 1fr;
  }
}

.porta-gifts__link {
  display: inline-block;
  margin-top: 0.75rem;
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--color-accent);
  text-decoration: none;
}

.porta-gifts__link:hover,
.porta-gifts__link:focus-visible {
  color: var(--color-accent);
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* Amount tags — plain sans-serif figures, easier to read than a serif line */
.porta-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  list-style: none;
  margin: 0.75rem 0 0;
  padding: 0;
}

.porta-chips li {
  padding: 0.25rem 0.75rem;
  border: 1px solid var(--color-accent);
  border-radius: var(--radius-pill);
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--color-accent);
  font-variant-numeric: tabular-nums;
}

/* ── Practical info / booking ── */

/* White, not beige: it follows the beige gallery band, and two beige blocks
   in a row read as one. The burgundy CTA band below closes it. */
.porta-booking {
  background-color: var(--color-bg);
}

.porta-booking__grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 2rem;
  margin-top: 2.5rem;
}

@media (min-width: 768px) {
  .porta-booking__grid {
    grid-template-columns: repeat(2, 1fr);
    gap: 3rem;
  }
}

.porta-booking__block-title {
  font-family: var(--font-heading);
  font-size: var(--text-xl);
  color: var(--color-text);
  margin-bottom: 1.25rem;
  padding-bottom: 0.75rem;
  border-bottom: 2px solid var(--color-accent);
}

.porta-booking__desc {
  font-size: var(--text-base);
  color: var(--color-text-light);
  line-height: 1.7;
  margin-bottom: 1.25rem;
}

/* Contact links (phone + email) */
.porta-booking__contact {
  list-style: none;
  padding: 0;
  margin: 0 0 1.25rem;
}

.porta-booking__contact li {
  margin-bottom: 0.35rem;
}

.porta-booking__contact a {
  color: var(--color-accent);
  font-weight: 500;
  text-decoration: none;
  font-size: var(--text-base);
}

.porta-booking__contact a:hover {
  color: var(--color-gold-text);
}

.porta-booking__address {
  font-style: normal;
  font-size: var(--text-sm);
  color: var(--color-text-light);
  line-height: 1.7;
}

/* ── Degustation CTA band ── */

/*
 * Closing bands — one specification for the three (design review B6, audit
 * 09-DR-11): /degustation (.porta-degustation-cta), /domaine (.domaine-section
 * --cta, domaine.css) and the /actualites newsletter band. Burgundy, centred,
 * .porta-section padding, a 32/44px white title, one --text-lg sentence at
 * 85% white, no kicker, the band's own call as the solid --white button.
 * No footer newsletter strip under them (porta_newsletter_show_footer_strip()).
 */

/* Full-bleed burgundy band — negative-margin technique, see the full-bleed
   section list near the top of this file. */
.porta-degustation-cta {
  background-color: var(--color-accent);
  text-align: center;
}

.porta-degustation-cta__title {
  font-size: var(--text-3xl);
  color: var(--color-white);
  margin-bottom: 1rem;
}

.porta-degustation-cta__text {
  color: var(--color-white);
  font-size: var(--text-lg);
  opacity: 0.85;
  max-width: var(--max-width-text);
  margin-inline: auto;
  margin-bottom: 2rem;
  line-height: 1.7;
}

@media (min-width: 768px) {
  .porta-degustation-cta__title {
    font-size: var(--text-4xl);
  }
}

/* ── Newsletter (Infomaniak) ─────────────────────────────────────────────── */

/*
 * template-parts/newsletter-form.php, two variants:
 *   --band    burgundy band closing /actualites (full-bleed, see the list at
 *             the top of this file) — same family as .porta-degustation-cta
 *   --footer  slim strip at the top of the footer, on the footer's beige
 *
 * Fields are underline-only, matching the contact form. The focus indicator is
 * the underline itself thickening (an inset shadow, so the box does not move),
 * which is why the outline is removed on the input.
 */

/* Honeypots: never visible, never focusable. Off-screen rather than
   display:none, which some bots detect and skip. */
.porta-newsletter__trap {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.porta-newsletter__form {
  position: relative; /* anchors the ALTCHA floating panel if it ever shows */
  width: 100%;
}

.porta-newsletter__row {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

@media (min-width: 768px) {
  .porta-newsletter__row {
    flex-direction: row;
    align-items: flex-end;
    gap: 1.25rem;
  }
}

/*
 * SPECIFICITY: the input rules are written as
 * `.porta-newsletter .porta-newsletter__form input.porta-newsletter__input`
 * (0,3,1). On shop pages (wine, cart) woocommerce.css loads later with
 * `.woocommerce input[type="email"]` (0,2,1) — a white boxed field, while
 * content pages showed the underline (audit 09-015). Astra styles
 * input[type="email"] at (0,1,1) — in main.min.css AND in its inline
 * customizer CSS — with a white box, a grey border, 4px radius and 12px 16px
 * padding. A bare class (0,1,0) loses to that and renders as a solid white
 * field; verified on 2026-10-03. Same reason the contact form's field rule is
 * scoped three classes deep.
 */
.porta-newsletter .porta-newsletter__form input.porta-newsletter__input {
  flex: 1 1 auto;
  min-width: 0;
  width: 100%;
  height: auto;
  border: none;
  border-bottom: 1px solid rgba(26, 26, 26, 0.25);
  border-radius: 0;
  background: transparent;
  padding: 0.75rem 0;
  font-family: var(--font-body);
  /* --text-field, never --text-base: under 16px iOS Safari zooms the page on
     focus, and 1rem is 14.6px on phones under Astra (CLAUDE.md § Checkout, 02-018). */
  font-size: var(--text-field);
  line-height: 1.5;
  color: var(--color-text);
  outline: none;
  box-shadow: none;
  transition: border-color var(--duration) ease, box-shadow var(--duration) ease;
  -webkit-appearance: none;
  appearance: none;
}

.porta-newsletter .porta-newsletter__form input.porta-newsletter__input::placeholder {
  color: var(--color-text-light);
  opacity: 1;
}

.porta-newsletter .porta-newsletter__form input.porta-newsletter__input:focus {
  border-bottom-color: var(--color-accent);
  box-shadow: inset 0 -1px 0 var(--color-accent);
}

.porta-newsletter__submit {
  flex: 0 0 auto;
  white-space: nowrap;
}

.porta-newsletter__form.is-busy .porta-newsletter__submit {
  opacity: 0.6;
  cursor: progress;
}

/* ALTCHA renders nothing visible while verification succeeds invisibly; this
   only matters if its floating panel has to appear. */
.porta-newsletter__captcha {
  display: block;
}

.porta-newsletter__consent {
  margin: 1rem 0 0;
  font-size: var(--text-xs);
  line-height: 1.6;
  color: var(--color-text-light);
}

.porta-newsletter__consent a {
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 2px;
}

.porta-newsletter__message:empty {
  display: none;
}

.porta-newsletter__message {
  margin: 1rem 0 0;
  padding: 0.75rem 1rem;
  font-size: var(--text-sm);
  line-height: 1.6;
  border-left: 3px solid var(--color-gold);
  background-color: var(--color-white);
}

.porta-newsletter__message--error {
  border-left-color: var(--color-accent);
}

/* After a successful sign-up only the confirmation remains. */
.porta-newsletter__form.is-done .porta-newsletter__fields {
  display: none;
}

.porta-newsletter__form.is-done .porta-newsletter__message {
  margin-top: 0;
}

.porta-newsletter__label {
  display: block;
  font-family: var(--font-body);
  font-size: var(--eyebrow-size);
  font-weight: var(--eyebrow-weight);
  letter-spacing: var(--eyebrow-tracking);
  text-transform: uppercase;
  color: var(--color-gold-text);
  margin: 0 0 0.5rem;
}

/* ── Band variant ── */

.porta-newsletter--band {
  background-color: var(--color-accent);
  color: var(--color-white);
  text-align: center;
}

.porta-newsletter--band .porta-newsletter__title {
  font-size: var(--text-3xl);
  color: var(--color-white);
  margin: 0 0 1rem;
}

.porta-newsletter--band .porta-newsletter__intro {
  font-size: var(--text-lg);
  line-height: 1.7;
  color: var(--color-white);
  opacity: 0.85;
  max-width: var(--max-width-text);
  margin: 0 auto 2rem;
}

.porta-newsletter--band .porta-newsletter__form {
  max-width: 34rem;
  margin-inline: auto;
  text-align: left;
}

/* (0,3,1) — one class above the base input rule; see its specificity note */
.porta-newsletter--band .porta-newsletter__form input.porta-newsletter__input {
  color: var(--color-white);
  border-bottom-color: rgba(255, 255, 255, 0.5);
}

.porta-newsletter--band .porta-newsletter__form input.porta-newsletter__input::placeholder {
  color: rgba(255, 255, 255, 0.75);
}

.porta-newsletter--band .porta-newsletter__form input.porta-newsletter__input:focus {
  border-bottom-color: var(--color-white);
  box-shadow: inset 0 -1px 0 var(--color-white);
}

/* Browser autofill paints its own pale background, which on burgundy would
   leave white text unreadable. Repaint it in the band colour. */
.porta-newsletter--band .porta-newsletter__form input.porta-newsletter__input:-webkit-autofill {
  -webkit-text-fill-color: var(--color-white);
  box-shadow: inset 0 0 0 100px var(--color-accent);
  caret-color: var(--color-white);
}

.porta-newsletter--band .porta-newsletter__consent {
  color: var(--color-white);
  opacity: 0.8;
}

.porta-newsletter--band .porta-newsletter__message {
  color: var(--color-text);
}

@media (min-width: 768px) {
  .porta-newsletter--band .porta-newsletter__title {
    font-size: var(--text-4xl);
  }
}

/* ── Footer variant ── */

.porta-newsletter--footer {
  padding: 2rem 0;
  border-bottom: 1px solid rgba(26, 26, 26, 0.12);
}

.porta-newsletter__grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1.25rem;
  align-items: center;
}

@media (min-width: 768px) {
  .porta-newsletter__grid {
    grid-template-columns: 1fr minmax(0, 32rem);
    gap: 3rem;
  }
}

.porta-newsletter--footer .porta-newsletter__intro {
  margin: 0;
  font-size: var(--text-sm);
  line-height: 1.6;
  color: var(--color-text-light);
}

@media (min-width: 768px) {
  .porta-newsletter--footer .porta-newsletter__intro {
    font-family: var(--font-heading);
    font-size: var(--text-xl);
    color: var(--color-text);
  }
}

@media (prefers-reduced-motion: reduce) {
  .porta-newsletter__input { transition: none; }
}

/* ── Footer ──────────────────────────────────────────────────────────────── */

/*
 * .porta-footer renders outside .ast-container (after its closing tag in
 * footer.php), so it is a direct child of #page. No negative-margin
 * full-bleed needed — width: 100% fills the flex container (#page uses
 * display:flex; flex-direction:column to stretch to min-height: 100vh).
 */
.porta-footer {
  width: 100%;
  background-color: var(--color-bg-alt);
  color: var(--color-text);
}

/* ── Three-column body ── */

.porta-footer__body {
  padding: 2.5rem 0;   /* tighter on phones (audit 09-008) */
}

@media (min-width: 768px) {
  .porta-footer__body {
    padding: var(--space-section) 0;
  }
}

/*
 * Brand · contact · hours (owner S9-Q7, audit 09-008). Desktop: three columns
 * — the old 2fr 1fr left ~460px of empty beige between brand and contact.
 * Phones: the brand across the top, contact and hours side by side under it,
 * instead of three stacked blocks (the footer was ~1 300px tall on phones).
 */
.porta-footer__grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 2rem 1.25rem;
  align-items: start;
}

.porta-footer__brand {
  grid-column: 1 / -1;
}

@media (min-width: 768px) {
  .porta-footer__grid {
    grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr) minmax(0, 1fr);
    gap: 3rem;
  }

  .porta-footer__brand {
    grid-column: auto;
  }
}

/* ── Col 1 — Brand ── */

.porta-footer__logo img {
  max-height: 48px;
  width: auto;
  display: block;
  margin-bottom: 1.25rem;
}

/* Fallback: text logo when no image logo is set */
.porta-footer__name {
  font-family: var(--font-heading);
  font-size: var(--text-2xl);
  color: var(--color-text);
  margin: 0 0 0.75rem;
}

.porta-footer__tagline {
  font-size: var(--text-sm);
  color: var(--color-gold-text);
  letter-spacing: var(--tracking);
  text-transform: uppercase;
  margin: 0 0 1.5rem;
}

.porta-footer__address {
  font-style: normal;
  font-size: var(--text-sm);
  line-height: 1.9;
  color: var(--color-text-light);
}

.porta-footer__region {
  display: block;
  margin-top: 0.5rem;
  color: var(--color-text-light);
  font-size: var(--text-xs);
  letter-spacing: var(--tracking-tight);
}

/* ── Shared column heading ── */

/* An h2 since audit 08-014 (was h3). Two classes: Astra's WooCommerce sheet
   sets `.woocommerce-js h2 { margin-bottom: 0.7em }` (0,1,1) on shop pages,
   which beat the single class and shrank the gap under the title. */
.porta-footer .porta-footer__col-title {
  font-family: var(--font-body);
  font-size: var(--eyebrow-size);
  font-weight: var(--eyebrow-weight);
  letter-spacing: var(--eyebrow-tracking);
  text-transform: uppercase;
  color: var(--color-gold-text);
  margin: 0 0 1.25rem;
}

/* ── Social links (in brand column) ── */

.porta-footer__social {
  display: flex;
  gap: 1rem;
  margin-top: 1.25rem;
}

@media (min-width: 768px) {
  .porta-footer__social {
    margin-top: 2rem;
  }
}

.porta-footer__social-link {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2.25rem;
  height: 2.25rem;
  border: 1px solid rgba(26, 26, 26, 0.2);
  border-radius: 50%;
  color: var(--color-text-light);
  text-decoration: none;
  transition: border-color var(--duration-fast) ease, color var(--duration-fast) ease;
}

.porta-footer__social-link:hover {
  border-color: var(--color-gold-text);
  color: var(--color-gold-text);
}

/* ── Col 2 — Contact ── */

.porta-footer__contact-list {
  list-style: none;
  margin: 0 0 1.5rem;
  padding: 0;
}

.porta-footer__contact-list li {
  margin-bottom: 0.35rem;
}

.porta-footer__contact-list a {
  color: var(--color-text-light);
  text-decoration: none;
  font-size: var(--text-sm);
  transition: color var(--duration-fast) ease;
}

.porta-footer__contact-list a:hover {
  color: var(--color-gold-text);
}

.porta-footer__hours-label {
  font-size: var(--eyebrow-size);
  font-weight: var(--eyebrow-weight);
  letter-spacing: var(--eyebrow-tracking);
  text-transform: uppercase;
  color: var(--color-gold-text);
  margin: 0 0 0.75rem;
}

.porta-footer__hours {
  list-style: none;
  margin: 0;
  padding: 0;
  font-size: var(--text-sm);
  color: var(--color-text-light);
  line-height: 1;
}

.porta-footer__hours li {
  margin-bottom: 0.45rem;
}

/* ── Quality label strip ── */

/*
 * The four labels sit between the footer columns and the copyright bar.
 *
 * WHY FULL COLOUR AND NOT ONE INK: a single-ink strip via mask-image was built
 * and rejected on 2026-09-11. A CSS mask reads the ALPHA channel, and only the
 * Lavaux mark carries its shape there — Terravin is a solid black disc with
 * knocked-out text, so it masked to a plain grey circle, and the other two
 * masked to solid blocks. filter: grayscale() was the fallback and lost on
 * looks: Terravin goes muddy and Vin Suisse Durable loses its red bottle.
 * The marks turn out to be tonally coherent anyway (black line art, red
 * accents), so they sit fine next to the burgundy and gold.
 *
 * WHY A HEIGHT PER MARK: they range from 0.81:1 to 4.28:1. At one shared
 * height the Lavaux lockup runs 171px wide and swallows the row. Heights are
 * authored per mark instead — dense marks smaller, airy ones larger — from the
 * table in inc/labels.php. Never replace these with a single .porta-labels__logo
 * height rule.
 */
.porta-labels {
  border-top: 1px solid rgba(26, 26, 26, 0.12);
  padding: 1.5rem 0;
}

@media (min-width: 768px) {
  .porta-labels {
    padding: 2rem 0;
  }
}

.porta-labels__title {
  font-family: var(--font-body);
  font-size: var(--eyebrow-size);
  font-weight: var(--eyebrow-weight);
  letter-spacing: var(--eyebrow-tracking);
  text-transform: uppercase;
  color: var(--color-gold-text);
  text-align: center;
  margin: 0 0 1.5rem;
}

/*
 * Mobile is ONE row of four (audit 09-008: a tighter phone footer; it was a
 * 2x2 grid, ~250px tall), never a wrapping row — left to flex-wrap the marks
 * break 3 + 1. With the compact Lavaux mark and heights capped at 48px, the
 * widest mark fits its ~80px cell at 360px.
 */
.porta-labels__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  justify-items: center;
  align-items: center;
  gap: 0.5rem 1rem;
}

@media (min-width: 768px) {
  .porta-labels__list {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 0.5rem 3.5rem;
  }
}

/* Padding rather than a min-height: it lifts the tap target past 44px without
   stretching the row, and gives the focus ring somewhere to sit. */
.porta-labels__link {
  display: flex;
  align-items: center;
  padding: 0.75rem 0.25rem;
  text-decoration: none;
}

.porta-labels__logo {
  display: block;
  width: auto;
  transition: opacity var(--duration) ease, filter var(--duration) ease;
}

/*
 * Per-mark heights — see the block comment above before changing any of these.
 * Scaled 1.5x from the original set on 2026-09-11 at the client's request.
 *
 * Below 768px the Lavaux card is served the compact pictorial mark instead of
 * the full lockup (see the <picture> in labels-strip.php): at this size the
 * 4.28:1 lockup would be 193px wide and overflow the ~159px cells of the
 * 2-column mobile grid. Its height is therefore set per breakpoint, and the
 * media query below and that <source> are one decision in two files.
 *
 * The .porta-labels prefix is load-bearing, not redundant. On WooCommerce
 * pages (cart, checkout, product, account) Astra loads
 * woocommerce-layout-grid.min.css, whose `.woocommerce-page img { height: auto }`
 * (0,1,1) outranks a bare modifier class (0,1,0) — every logo then rendered at
 * its file's natural size (Terravin 603px). Two classes (0,2,0) win cleanly
 * without !important.
 */
.porta-labels .porta-labels__logo--swiss-wine         { height: 48px; }
.porta-labels .porta-labels__logo--lavaux-unesco      { height: 42px; } /* the compact mark, 0.92:1 */
.porta-labels .porta-labels__logo--terravin           { height: 44px; }
.porta-labels .porta-labels__logo--vin-suisse-durable { height: 48px; }

@media (min-width: 768px) {
  .porta-labels .porta-labels__logo--swiss-wine         { height: 66px; }
  .porta-labels .porta-labels__logo--terravin           { height: 60px; }
  .porta-labels .porta-labels__logo--vin-suisse-durable { height: 69px; }
  /* the full 4.28:1 lockup returns here */
  .porta-labels .porta-labels__logo--lavaux-unesco      { height: 45px; }
}

/* The Lavaux mark ships as the reversed (white) artwork, recoloured to
   currentColor in the file, so it inherits the ink of this container. */
.porta-labels__link { color: var(--color-text); }

/* Treatment A — the marks in their own colours, lifted slightly on hover */
.porta-labels--colour .porta-labels__logo {
  opacity: 0.85;
}

.porta-labels--colour .porta-labels__link:hover .porta-labels__logo,
.porta-labels--colour .porta-labels__link:focus-visible .porta-labels__logo {
  opacity: 1;
}

/* Treatment B — greyscale at rest, colour on hover */
.porta-labels--muted .porta-labels__logo {
  filter: grayscale(1);
  opacity: 0.55;
}

.porta-labels--muted .porta-labels__link:hover .porta-labels__logo,
.porta-labels--muted .porta-labels__link:focus-visible .porta-labels__logo {
  filter: grayscale(0);
  opacity: 1;
}

@media (prefers-reduced-motion: reduce) {
  .porta-labels__logo { transition: none; }
}

/* ── Bottom bar ── */

.porta-footer__bottom {
  border-top: 1px solid rgba(26, 26, 26, 0.12);
  padding: 1.25rem 0;
}

.porta-footer__bottom-inner {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  align-items: flex-start;
}

@media (min-width: 768px) {
  .porta-footer__bottom-inner {
    flex-direction: row;
    justify-content: space-between;
    align-items: center;
  }
}

.porta-footer__copyright {
  font-size: var(--text-xs);
  color: var(--color-text-light);
  margin: 0;
}

/* Age notice, above the copyright line (audit 05-003, G2 follow-up):
   main line, then the legal threshold smaller. Text: inc/legal.php. */
.porta-age-notice--footer {
  margin: 0 0 0.75rem;
  line-height: 1.5;
}

.porta-age-notice--footer p {
  margin: 0;
}

.porta-age-notice--footer .porta-age-notice__main {
  font-size: var(--text-sm);
  color: var(--color-text);
}

.porta-age-notice--footer .porta-age-notice__law {
  font-size: var(--text-xs);
  color: var(--color-text-light);
}

.porta-footer__legal {
  display: flex;
  flex-wrap: wrap; /* three links since the CGV (00-004): they wrap on phones */
  gap: 0.5rem 1.5rem;
}

.porta-footer__legal a {
  font-size: var(--text-xs);
  color: var(--color-text-light);
  text-decoration: none;
  transition: color var(--duration-fast) ease;
}

.porta-footer__legal a:hover {
  color: var(--color-accent);
}

/* Language switcher in the bottom bar (audit 07-006): the same small links as
   the legal ones; it stays on the distraction-free checkout, where the header
   menu and its copy of the switcher are hidden. */
.porta-lang--footer {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: var(--text-xs);
  color: var(--color-text-light);
  letter-spacing: var(--tracking);
}

.porta-lang--footer .porta-lang__link {
  color: var(--color-text-light);
  text-decoration: none;
  transition: color var(--duration-fast) ease;
}

.porta-lang--footer .porta-lang__link:hover {
  color: var(--color-accent);
}

.porta-lang--footer .porta-lang__current {
  color: var(--color-text);
  font-weight: 600;
}

/* ── Section heading tiers ──────────────────────────────────────────────── */

/*
 * Two tiers, chosen by what the section holds (settled with the client
 * 2026-09-07, resolving the "heading alignment and size" question):
 *
 *   Narrative  — prose leading to a statement. 32/44px, centred, an optional
 *                gold eyebrow above (.porta-section-header__label).
 *                This is the default .porta-section-header__title.
 *   Collection — a grid or carousel of cards. 24/32px, left-aligned.
 *                Use the --index modifier, or .porta-events__title inside
 *                the events carousel.
 *
 * **Size and alignment carry the distinction — not the gold rule.** Every
 * section h2 keeps its 40×2px gold rule; the rule simply follows the
 * heading's alignment (centred under a centred heading, flush left under a
 * left-aligned one). Dropping it from the narrative tier was tried on
 * 2026-09-11 and reverted the same day: without it those headings read as
 * unpunctuated, and the client preferred the dash. Do not remove it again.
 *
 * Alignment follows the content block the heading sits above, which is why
 * /domaine's two-column sections keep left-aligned 44px headings and are
 * still narrative.
 *
 * The rule is scoped to h2 so page H1s never pick it up.
 *
 * Design reference: design.md §2.3 / §1.3 (gold is a reward color,
 * used here as punctuation — like a wax seal on a letter).
 */
h2.porta-section-header__title::after,
h2.porta-events__title::after {
  content: '';
  display: block;
  width: 40px;
  height: 2px;
  background-color: var(--color-gold);
  margin-top: 0.75rem;
  /* Centred by default — the narrative tier is centred. */
  margin-inline: auto;
}

/* Collection headings sit above a left-aligned grid, so the rule goes flush left. */
h2.porta-section-header__title--index::after,
h2.porta-events__title::after {
  margin-inline: 0;
}

/* ── Card hover effects ──────────────────────────────────────────────────── */

/*
 * Cards lift 2px and deepen their shadow on hover — a subtle cue of
 * interactivity. Matches design.md §6.3.
 * Note: image-level zoom (scale 1.03 on img) is already defined per card type
 * above. These rules add the card-level shadow + lift on top.
 */

/* Wine card */
.porta-wine-card {
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06);
  transition: box-shadow var(--duration) ease, transform var(--duration) ease;
}

.porta-wine-card:hover {
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
  transform: translateY(-2px);
}

/* Event card */
.porta-event-card {
  transition: box-shadow var(--duration) ease, transform var(--duration) ease;
}

.porta-event-card:hover {
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
  transform: translateY(-2px);
}

/* Article card */
.porta-article-card {
  transition: box-shadow var(--duration) ease, transform var(--duration) ease;
}

.porta-article-card:hover {
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
  transform: translateY(-2px);
}

/* Formula card (dégustation) */
.porta-format-card {
  transition: box-shadow var(--duration) ease, transform var(--duration) ease;
}

.porta-format-card:hover {
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
  transform: translateY(-2px);
}

/* ── Contact form input styling ──────────────────────────────────────────── */

/*
 * Boxed 48px fields, matching the checkout (woocommerce.css, "48px tall, 16px
 * text"). The underline-only fields they replace (2026-10-08) read as plain
 * text lines on a phone, and their 14.6px text made iOS zoom in on focus.
 *
 * The markup comes from the CF7 form in WP Admin (WPAdmin-setup.md, "Contact
 * page"): each field is label.porta-cf7__field > span.porta-cf7__label +
 * CF7's control wrap. Auto <p>/<br> is off (inc/contact.php).
 *
 * No !important needed — CF7's and Astra's sheets use lower specificity.
 */
.porta-cf7__row {
  display: grid;
  grid-template-columns: 1fr;
  column-gap: 1.25rem;
  margin: 0; /* CF7/Astra give direct <div>s of the form a bottom margin — the fields carry the rhythm */
}

/* Name and e-mail side by side only when the form column is wide enough */
@media (min-width: 1280px) {
  .porta-cf7__row {
    grid-template-columns: 1fr 1fr;
  }
}

.porta-cf7__field {
  display: block;
  margin: 0 0 1.25rem;
}

.porta-cf7__label {
  display: block;
  margin-bottom: 0.375rem;
  font-size: var(--text-sm);
  font-weight: 500;
  line-height: 1.3;
  color: var(--color-text);
}

.porta-contact__form .wpcf7-form-control-wrap {
  display: block;
}

.porta-contact__form .wpcf7-form-control:not(.wpcf7-submit) {
  display: block;
  width: 100%;
  min-height: 48px;
  margin: 0;
  padding: 0.75rem 0.875rem;
  box-sizing: border-box;
  font-family: var(--font-body);
  font-size: var(--text-field);   /* never below 16px — see style.css */
  line-height: 1.4;
  color: var(--color-text);
  background-color: var(--color-white);
  border: 1px solid rgba(26, 26, 26, 0.22);
  border-radius: var(--border-radius);
  box-shadow: none;
  transition: border-color var(--duration) ease, box-shadow var(--duration) ease;
  -webkit-appearance: none;
  appearance: none;
}

/* Focus: accent border thickened by a 1px ring — no layout shift.
   The border change is the focus indicator, so the outline is dropped.
   `.wpcf7` in the chain (0,5,0): Astra's inline `.wpcf7 input.wpcf7-form-control
   :not([type="submit"]):focus` (0,4,1) painted the e-mail field blue (09-002). */
.porta-contact__form .wpcf7 .wpcf7-form-control:not(.wpcf7-submit):focus {
  border-color: var(--color-accent);
  box-shadow: 0 0 0 1px var(--color-accent);
  outline: none;
}

/* Select: appearance is reset above, so draw the chevron back. Two gradient
   triangles instead of an SVG data URI, so the colour stays a token. */
.porta-contact__form select.wpcf7-form-control {
  padding-right: 2.5rem;
  background-image:
    linear-gradient(45deg, transparent 50%, var(--color-text) 50%),
    linear-gradient(135deg, var(--color-text) 50%, transparent 50%);
  background-position:
    calc(100% - 1.25rem) 50%,
    calc(100% - 0.875rem) 50%;
  background-size: 0.375rem 0.375rem;
  background-repeat: no-repeat;
  cursor: pointer;
}

.porta-contact__form textarea.wpcf7-form-control {
  min-height: 160px;
  resize: vertical;
}

/* Validation — CF7 adds .wpcf7-not-valid to the field and a tip after it */
.porta-contact__form .wpcf7-form-control.wpcf7-not-valid {
  border-color: var(--color-accent);
  box-shadow: 0 0 0 1px var(--color-accent);
}

.porta-contact__form .wpcf7-not-valid-tip {
  display: block;
  margin-top: 0.375rem;
  font-size: var(--text-xs);
  font-weight: 400;
  color: var(--color-accent);
}

/* Submit: full width on a phone, 56px tall. Padding etc. come from the shared
   .wpcf7-submit rule near the top of this file. */
.porta-cf7__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
}

.porta-contact__form .wpcf7-submit {
  width: 100%;
  min-height: 56px;
}

@media (min-width: 768px) {
  .porta-contact__form .wpcf7-submit {
    width: auto;
  }
}

/*
 * Response message after sending. CF7 draws a coloured box around it
 * (green / red / orange); here it becomes a beige note with a left rule —
 * gold when sent, burgundy for anything that needs the visitor's attention.
 * The `.wpcf7 form` part of the selector is needed to outrank CF7's own
 * `.wpcf7 form.sent .wpcf7-response-output` rules.
 */
.porta-contact__form .wpcf7 form .wpcf7-response-output {
  margin: 1.5rem 0 0;
  padding: 1rem 1.25rem;
  border: 0;
  border-left: 3px solid var(--color-accent);
  border-radius: 0;
  background-color: var(--color-bg-alt);
  font-size: var(--text-sm);
  line-height: 1.6;
  color: var(--color-text);
}

.porta-contact__form .wpcf7 form.sent .wpcf7-response-output {
  border-left-color: var(--color-gold);
}

.porta-contact__form .wpcf7 form.invalid .wpcf7-response-output,
.porta-contact__form .wpcf7 form.unaccepted .wpcf7-response-output,
.porta-contact__form .wpcf7 form.payment-required .wpcf7-response-output,
.porta-contact__form .wpcf7 form.failed .wpcf7-response-output,
.porta-contact__form .wpcf7 form.aborted .wpcf7-response-output,
.porta-contact__form .wpcf7 form.spam .wpcf7-response-output {
  border-left-color: var(--color-accent);
}

/* CF7 prints an empty response box until there is something to say */
.porta-contact__form .wpcf7 form.init .wpcf7-response-output,
.porta-contact__form .wpcf7 form.resetting .wpcf7-response-output,
.porta-contact__form .wpcf7 form.submitting .wpcf7-response-output {
  display: none;
}

/*
 * Contact form section — tighter vertical padding than the generic .porta-section.
 * The form has 4 fields + a button; at 5rem padding the button falls below the fold.
 *
 * The :not() is load-bearing. Both the header band and the form section are
 * direct children of .porta-contact, so the bare `.porta-contact > .porta-section`
 * this replaces (specificity 0,2,0) also beat base.css's shared page-intro-header
 * rule (0,1,0) and squeezed /contact's band to 40px, where the identical bands on
 * /nos-vins, /actualites and /degustation sit at 56px. Only the form wants the
 * tighter rhythm; the band must stay on the shared rule.
 */
.porta-contact > .porta-section:not(.porta-contact__header) {
  padding-block: 1.75rem;
}

@media (min-width: 768px) {
  .porta-contact > .porta-section:not(.porta-contact__header) {
    padding-block: 2.5rem;
  }
}

/* ── Notice / dev placeholder ────────────────────────────────────────────── */

/* Generic notice bar used to surface messages within templates */
.porta-notice {
  padding: 1rem 1.5rem;
  border-radius: var(--border-radius);
  font-size: var(--text-sm);
  margin-block: 1rem;
}

/* ── Actualités page ─────────────────────────────────────────────────────── */

/*
 * Agenda → Chroniques gap.
 * On /actualites these two are one continuous editorial flow, not two
 * separate bands, but each carried a full .porta-section padding — 80px
 * bottom plus 80px top left a 160px trench between the last event card and
 * the Chroniques heading. Zeroing the carousel's bottom padding leaves the
 * archive's own top padding as the single gap, so the two read as one page
 * rather than two. Scoped to .porta-actualites: the homepage uses the same
 * carousel partial and its rhythm is correct there.
 */
.porta-actualites .porta-events {
  padding-bottom: 0;
}

/* "Chroniques" subtitle — sizing and the gold rule now come from the
   --index modifier on the heading itself, not from a page-scoped override. */
.porta-actualites__archive-header {
  text-align: left;
  margin-bottom: 2rem;
}

/* ── Articles grid ── */

.porta-articles__grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 2rem;
}

@media (min-width: 768px) {
  .porta-articles__grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

/* 1024px, not 1280px: a content breakpoint — three chronique cards fit from
   1024px, and a laptop window between 1024 and 1279 would otherwise show two
   oversized ones (CLAUDE.md § CSS, audit 02-020). */
@media (min-width: 1024px) {
  .porta-articles__grid {
    grid-template-columns: repeat(3, 1fr);
  }
}

/* ── Article card ── */
/* Same visual treatment as .porta-event-card — bg-alt, no shadow, gold date */

.porta-article-card {
  position: relative;          /* anchor for the stretched link ::after */
  background-color: var(--color-bg-alt);
  border-radius: var(--border-radius);
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

/* Thumbnail — same ratio as event card (16:6) for visual consistency */
.porta-article-card__image {
  aspect-ratio: 16 / 6;
  overflow: hidden;
  background-color: var(--color-bg);
}

.porta-article-card__image img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  transition: transform 0.4s ease;
}

.porta-article-card:hover .porta-article-card__image img {
  transform: scale(1.03);
}

.porta-article-card__body {
  padding: 1.5rem;
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  flex: 1;
}

/* Date + category on the same row */
.porta-article-card__meta {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  flex-wrap: wrap;
}

/* Gold uppercase date — mirrors .porta-event-card__date */
.porta-article-card__date {
  font-size: var(--eyebrow-size);
  font-weight: var(--eyebrow-weight);
  letter-spacing: var(--eyebrow-tracking);
  text-transform: uppercase;
  color: var(--color-gold-text);
}

/* Category label — subtle accent pill */
.porta-article-card__category {
  font-size: var(--eyebrow-size);
  font-weight: var(--eyebrow-weight);
  letter-spacing: var(--eyebrow-tracking);
  text-transform: uppercase;
  color: var(--color-accent);
}

.porta-article-card__title {
  font-size: var(--text-xl);
}

/* Stretched link — ::after covers the whole card, making it fully clickable */
.porta-article-card__link {
  color: inherit;
  text-decoration: none;
}

.porta-article-card__link::after {
  content: '';
  position: absolute;
  inset: 0;
}

/* One-line context under the title (competition, press source…) — replaces
   the excerpt on cards; the excerpt field is kept for SEO meta descriptions. */
.porta-article-card__subtitle {
  font-size: var(--text-sm);
  color: var(--color-text-light);
  line-height: 1.6;
}

/* ── Filter tabs — shared by /nos-vins and /actualites (Chroniques) ── */

/* Moved here from woocommerce.css (2026-10-08) so the Chroniques filter can
   use them. The /nos-vins gold sub-row is still in woocommerce.css. */
.porta-filter {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-bottom: 2.5rem;
}

.porta-filter__btn {
  background-color: transparent;
  color: var(--color-text-light);
  border: 1px solid var(--color-bg-alt);
  border-radius: var(--border-radius);
  font-family: var(--font-body);
  font-size: var(--text-xs);
  font-weight: 500;
  letter-spacing: var(--tracking);
  text-transform: uppercase;
  padding: 0.5rem 1.25rem;
  cursor: pointer;
  transition: background-color 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}

/*
 * Selector specificity note — all hover/active rules below chain
 * `.porta-filter .porta-filter__btn` (specificity 0,2,1) so they beat
 * Astra's inline `button:hover { background: var(--ast-global-color-1) }`
 * rule (specificity 0,1,1, Astra's default blue accent). Without the extra
 * class, Astra's customizer inline CSS would win on ties via source order.
 */
.porta-filter .porta-filter__btn:hover {
  background-color: transparent;
  border-color: var(--color-accent);
  color: var(--color-accent);
}

/* Active top tab — solid accent fill, matches primary button */
.porta-filter .porta-filter__btn--active,
.porta-filter .porta-filter__btn--active:hover {
  background-color: var(--color-accent);
  border-color: var(--color-accent);
  color: var(--color-white);
}

/* ── "Voir plus" batch reveal ── */

/* Wrapper divs keep the card partial untouched; display:grid makes the single
   card child stretch to the full cell height (matches direct grid children). */
.porta-articles__item {
  display: grid;
}

/* Cards outside the active filter, or beyond the revealed batch — both set by
   articles-filter.js. Without JS no card carries it, so every card shows. */
.porta-articles__item--hidden {
  display: none;
}

/* The tabs and "Voir plus" ship with the hidden attribute (they need JS);
   their own display rules would otherwise override it. */
.porta-articles__filter[hidden],
.porta-articles__more[hidden] {
  display: none;
}

/* /actualites/#medailles scrolls the tabs into view below the sticky header. */
.porta-articles__filter {
  scroll-margin-top: 7rem;
}

.porta-articles__more {
  text-align: center;
  margin-top: 3rem;
}

/* ── Empty state ── */

.porta-actualites__empty {
  text-align: center;
  padding-block: 4rem;
}

.porta-actualites__empty-text {
  color: var(--color-text-light);
  font-size: var(--text-lg);
  max-width: var(--max-width-text);
  margin-inline: auto;
  line-height: 1.7;
}

/* Hide Astra's "by author / date" meta on standard post pages accessed via /actualites */
.page-template-templates-page-actualites .entry-meta {
  display: none;
}

/* ── Single post page (single.php) ──────────────────────────────────────── */

/* Full-bleed off-white header — same negative-margin technique as other page headers */
.porta-single-post__header {
  background-color: var(--color-bg-alt);
  margin-left: calc(50% - 50vw);
  margin-right: calc(50% - 50vw);
}

/* Meta row: category badge + date, above the title */
.porta-single-post__meta {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin-bottom: 0.75rem;
  flex-wrap: wrap;
}

.porta-single-post__date {
  font-size: var(--text-sm);
  color: var(--color-text-light);
}

/* Event lieu — sits next to the date in the meta row (single-evenement.php).
   Same treatment as the event card's lieu line. */
.porta-single-post__lieu {
  font-size: var(--text-sm);
  color: var(--color-text-light);
}

/* Past event note under the title (audit 01-017). */
.porta-single-event__past {
  margin: 1.5rem 0 0;
  font-size: var(--text-sm);
  color: var(--color-text-light);
}

.porta-single-event__past a {
  color: var(--color-accent);
  text-decoration: none;
}

.porta-single-event__past a:hover,
.porta-single-event__past a:focus-visible {
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* /actualites/#agenda lands below the sticky header. */
#agenda {
  scroll-margin-top: 5rem;
}

/* Event pages: date styled as the gold uppercase kicker, matching the card */
.porta-single-event .porta-single-post__date {
  font-size: var(--eyebrow-size);
  font-weight: var(--eyebrow-weight);
  letter-spacing: var(--eyebrow-tracking);
  text-transform: uppercase;
  color: var(--color-gold-text);
}

.porta-single-post__title {
  font-family: var(--font-heading);
  font-size: var(--text-3xl);
  line-height: 1.2;
  margin: 0;
}

@media (min-width: 768px) {
  .porta-single-post__title {
    font-size: var(--text-4xl);
  }
}

/* Optional subtitle under the H1 — same meta as the card subtitle */
.porta-single-post__subtitle {
  margin-top: 0.75rem;
  font-size: var(--text-lg);
  color: var(--color-text-light);
}

/* Featured image — the same visual the /actualites card shows (medal
   certificate, press clipping…), displayed at the top of the article body */
.porta-single-post__image {
  margin: 0 0 2rem;
}

.porta-single-post__image img {
  width: 100%;
  height: auto;
  border-radius: var(--border-radius);
}

/* Prose content — generous line-height, paragraph spacing */
.porta-single-post__content {
  margin-top: 1.5rem;
  font-size: var(--text-base);
  line-height: 1.7;
  color: var(--color-text);
}

.porta-single-post__content p {
  margin-bottom: 1.5rem;
}

.porta-single-post__content h2,
.porta-single-post__content h3 {
  font-family: var(--font-heading);
  color: var(--color-text);
  margin-top: 2rem;
  margin-bottom: 0.75rem;
}

.porta-single-post__content a {
  color: var(--color-accent);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.porta-single-post__content a:hover {
  color: var(--color-gold-text);
}

/* Images inside post content — full width of the prose column, rounded */
.porta-single-post__content img {
  width: 100%;
  height: auto;
  display: block;
  border-radius: var(--border-radius);
  margin-block: 1.5rem;
}

/* Back link — subtle, below content */
.porta-single-post__back {
  display: inline-block;
  margin-top: 3rem;
  padding-bottom: 3rem;
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--color-text-light);
  text-decoration: none;
  transition: color var(--duration-fast) ease;
}

.porta-single-post__back:hover {
  color: var(--color-accent);
}

/* The next step after a chronique or an event (audit 06-017), above the back
   link: the wine on sale, or « Nous rendre visite ». */
.porta-single-post__next {
  margin: 3rem 0 0;
  font-weight: 500;
}

.porta-single-post__next a {
  color: var(--color-accent);
  text-decoration: none;
}

.porta-single-post__next a:hover,
.porta-single-post__next a:focus-visible {
  text-decoration: underline;
  text-underline-offset: 3px;
}

.porta-single-post__next + .porta-single-post__back {
  margin-top: 1.5rem;
}

/* ── Scroll-entrance animations (global) ─────────────────────────────────── */
/*
 * Used on /domaine, /nos-vins, /degustation.
 * JS (scroll-entrance.js) adds .scroll-reveal to targets before observing,
 * then adds .scroll-reveal--visible when the element enters the viewport.
 * Animates once only. prefers-reduced-motion: JS exits before adding any class.
 * Page-specific stagger delays live in domaine.css for /domaine targets.
 */

.scroll-reveal {
  opacity: 0;
  transform: translateY(22px);
  transition: opacity 0.65s ease-out, transform 0.65s ease-out;
}

.scroll-reveal--visible {
  opacity: 1;
  transform: translateY(0);
}

/* Stagger wine cards on /nos-vins */
.porta-wine-card:nth-child(2).scroll-reveal { transition-delay: 0.08s; }
.porta-wine-card:nth-child(3).scroll-reveal { transition-delay: 0.16s; }
.porta-wine-card:nth-child(4).scroll-reveal { transition-delay: 0.08s; }
.porta-wine-card:nth-child(5).scroll-reveal { transition-delay: 0.16s; }
.porta-wine-card:nth-child(6).scroll-reveal { transition-delay: 0.24s; }

/* Stagger format cards on /degustation */
.porta-format-card:nth-child(2).scroll-reveal { transition-delay: 0.1s; }
.porta-format-card:nth-child(3).scroll-reveal { transition-delay: 0.2s; }

/* ── Legal pages (Mentions légales, Politique de confidentialité) ─────────── */

/*
 * Content body — prose column constrained to readable width.
 * Sections use generous vertical spacing; no cards, no grid — pure editorial.
 */
.porta-legal__body {
  max-width: var(--max-width-text);
  margin-inline: auto;
}

/* Individual content section — heading + body text */
.porta-legal__section {
  padding-block: 2.5rem;
  border-bottom: 1px solid var(--color-bg-alt);
}

.porta-legal__section:last-of-type {
  border-bottom: none;
}

/* Section heading — heading font, accent color, less dramatic than page h1 */
.porta-legal__section h2 {
  font-family: var(--font-heading);
  font-size: var(--text-2xl);
  color: var(--color-accent);
  margin-bottom: 1rem;
}

/* Sub-heading — used for grouped data categories within a section */
.porta-legal__section h3 {
  font-family: var(--font-body);
  font-size: var(--text-base);
  font-weight: 500;
  color: var(--color-text);
  margin-top: 1.5rem;
  margin-bottom: 0.5rem;
}

/* Paragraph spacing within a section */
.porta-legal__section p {
  line-height: 1.7;
  margin-bottom: 0.875rem;
  color: var(--color-text);
}

.porta-legal__section p:last-child {
  margin-bottom: 0;
}

/* Lists — rights, cookies, CGV payment methods; numbered ordering steps (CGV § 4) */
.porta-legal__section ul,
.porta-legal__section ol {
  list-style: disc;
  padding-left: 1.5rem;
  margin-bottom: 0.875rem;
}

.porta-legal__section ol {
  list-style: decimal;
}

.porta-legal__section ul li,
.porta-legal__section ol li {
  line-height: 1.7;
  margin-bottom: 0.375rem;
  color: var(--color-text);
}

/* Tables on the legal pages — recipients and cookies of the privacy policy
   (audit 00-037 / 05-007). The wrapper scrolls sideways on a narrow phone
   instead of the page. */
.porta-legal__table-wrap {
  overflow-x: auto;
  margin-bottom: 0.875rem;
}

.porta-legal__table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--text-sm);
  line-height: 1.5;
}

.porta-legal__table th,
.porta-legal__table td {
  padding: 0.5rem 0.75rem 0.5rem 0;
  border-bottom: 1px solid var(--color-bg-alt);
  text-align: left;
  vertical-align: top;
}

.porta-legal__table th {
  font-weight: 500;
  color: var(--color-text-light);
}

/* ── Dégustation magazine photo grid (Option A) ───────────────────────────── */

/*
 * Asymmetric 3-col × 2-row CSS Grid.
 * img 1: 1 col × 2 rows (tall portrait — left column)
 * img 2: 2 cols × 1 row (wide landscape — top right)
 * img 3: 1 col × 1 row (square — bottom centre)
 * img 4: 1 col × 1 row (square — bottom right)
 *
 * Images: drop galerie-degustation-1.jpg through galerie-degustation-4.jpg
 * into assets/images/. Section renders only when at least one file is present.
 */
.porta-degustation-grid {
  background-color: var(--color-bg-alt);
  padding-block-start: 1rem;
  padding-block-end: 3rem;
}

.porta-degustation-grid__inner {
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-template-rows: 180px 180px 220px; /* mobile: row1+row2 for img1/2/3, row3 for img4 */
  gap: 0.5rem;
  max-width: var(--max-width);
  margin-inline: auto;
  padding-inline: 1.5rem;
}

/* Each cell clips and covers its image. Cells are <button>s (keyboard access to
   the lightbox, audit 02-004): the bare-button reset in base.css undoes Astra's
   skin; padding and the cell colour are undone here (Astra's :hover/:focus
   rules use !important). */
.porta-degustation-grid__item,
.porta-degustation-grid__item:hover,
.porta-degustation-grid__item:focus,
.porta-degustation-grid__item:active {
  display: block;
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0 !important;
  background-color: var(--color-bg) !important;
  overflow: hidden;
  border-radius: 0 !important;
}

/* Keyboard focus: base.css's ring, drawn OUTSIDE the cell (2px + 2px offset fit
   the 0.5rem grid gap). Not inside: the photo zooms on focus as on hover, and a
   transformed child paints over an inset outline. */
.porta-degustation-grid__item:focus:not(:focus-visible) {
  outline: none;
}

.porta-degustation-grid__item img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  transition: transform 0.5s ease;
}

.porta-degustation-grid__item:hover img,
.porta-degustation-grid__item:focus-visible img {
  transform: scale(1.04);
}

/* Mobile asymmetric placement (max-width guard keeps desktop untouched) */
@media (max-width: 767px) {
  .porta-degustation-grid__item:nth-child(1) { grid-row: 1 / 3; }        /* tall portrait, left col */
  .porta-degustation-grid__item:nth-child(4) { grid-column: 1 / 3; }     /* full width bottom */
}

/* Desktop: switch to 3-column asymmetric layout */
@media (min-width: 768px) {
  .porta-degustation-grid__inner {
    grid-template-columns: 1fr 1fr 1fr;
    grid-template-rows: 280px 280px;
  }

  /* img 1 — tall portrait, spans both rows */
  .porta-degustation-grid__item:nth-child(1) {
    grid-row: 1 / 3;
  }

  /* img 2 — wide landscape, spans last two columns */
  .porta-degustation-grid__item:nth-child(2) {
    grid-column: 2 / 4;
  }

  /* img 3 and img 4 fill the remaining cells automatically */
}

/* "Last updated" notice — small and muted, sits below all sections */
.porta-legal__updated {
  margin-top: 2rem;
  font-size: var(--text-sm);
  color: var(--color-text-light);
  font-style: italic;
}

/* ── Lightbox (reusable — any page) ─────────────────────────────────────────
 *
 * Full-screen overlay opened by a .porta-lightbox-item <button>.
 * Built and controlled by assets/js/lightbox.js.
 * Enqueue the script per-page in inc/enqueue.php. Currently active on /degustation.
 * See lightbox.js header comment for full usage instructions.
 * ───────────────────────────────────────────────────────────────────────── */

/* Page scroll locked while a dialog is open — the lightbox and the /domaine
   detail dialog (dialog.js, portaDialog.lockScroll()). */
body.porta-scroll-locked {
  overflow: hidden;
}

/* Any clickable image wrapper signals interactivity */
.porta-lightbox-item {
  cursor: zoom-in;
}

/* Hidden images — loaded for lightbox navigation, never rendered on the page */
.porta-lightbox-extra {
  display: none;
}

/* Overlay */
.porta-lightbox {
  position: fixed;
  inset: 0;
  z-index: var(--z-lightbox);
  background: rgba(0, 0, 0, 0.92);
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  transition: opacity var(--duration) ease;
  cursor: zoom-out;
}

.porta-lightbox.is-open {
  opacity: 1;
}

/* Image */
.porta-lightbox__img {
  max-width: 90vw;
  max-height: 90vh;
  object-fit: contain;
  display: block;
  cursor: default;
  transform: scale(0.97);
  transition: transform var(--duration) ease;
}

.porta-lightbox.is-open .porta-lightbox__img {
  transform: scale(1);
}

/* Close button */
.porta-lightbox__close {
  position: absolute;
  top: 1.25rem;
  right: 1.5rem;
  color: var(--color-white) !important;
  font-size: 2.25rem;
  line-height: 1;
  cursor: pointer;
  padding: 0.5rem;
  opacity: 0.75;
  transition: opacity var(--duration-fast) ease;
  border-radius: 0 !important;
}

.porta-lightbox__close:hover {
  opacity: 1;
  color: var(--color-white) !important;
}

/* Prev / Next arrows */
.porta-lightbox__prev,
.porta-lightbox__next {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  color: var(--color-white) !important;
  font-size: 3rem;
  line-height: 1;
  cursor: pointer;
  padding: 1rem 1.25rem;
  opacity: 0.65;
  transition: opacity var(--duration-fast) ease;
  user-select: none;
  border-radius: 0 !important;
}

.porta-lightbox__prev:hover,
.porta-lightbox__next:hover {
  opacity: 1;
  color: var(--color-white) !important;
}

.porta-lightbox__prev { left: 0.5rem; }
.porta-lightbox__next { right: 0.5rem; }

/* Counter: "4 / 14" — bottom centre of the overlay */
.porta-lightbox__counter {
  position: absolute;
  bottom: 1.25rem;
  left: 50%;
  transform: translateX(-50%);
  font-family: var(--font-body);
  font-size: var(--text-sm);
  color: rgba(255, 255, 255, 0.65);
  letter-spacing: var(--tracking-wide);
  pointer-events: none;
  white-space: nowrap;
}

/* Grid hint — "Voir les N photos" below the mosaic.
   No outline suppression here: keyboard focus keeps the global burgundy
   ring from base.css (the color change alone is not a focus indicator). */
.porta-degustation-grid__hint {
  display: block;
  min-height: var(--tap-size-link);   /* 24px text-link target (audit 09-011) */
  margin: 0.6rem auto 0;
  padding: 0.25rem 0;
  cursor: pointer;
  font-family: var(--font-body);
  font-size: var(--text-sm);
  color: var(--color-text-light);
  letter-spacing: var(--tracking);
  text-align: center;
  transition: color var(--duration-fast);
}

.porta-degustation-grid__hint::after {
  content: ' →';
}

.porta-degustation-grid__hint:hover,
.porta-degustation-grid__hint:focus,
.porta-degustation-grid__hint:active {
  color: var(--color-accent);
}

/* Quiet on mouse click — Astra's button:focus outline reset needs the bump. */
.porta-degustation-grid__hint:focus:not(:focus-visible) {
  outline: none;
}

@media (prefers-reduced-motion: reduce) {
  .porta-lightbox,
  .porta-lightbox__img {
    transition: none;
  }
}

/* ── 404 error page ──────────────────────────────────────────────────────── */

/* The header is a beige page band (.porta-page-band in 404.php: background,
   full bleed, 270px), like every information page — not burgundy, and a 44px
   H1, not the 56px of the photo heroes (audit 09-005 / 09-DR-2, owner S9-Q3). */
.porta-404__label {
  display: block;
  font-family: var(--font-body);
  font-size: var(--eyebrow-size);
  font-weight: var(--eyebrow-weight);
  letter-spacing: var(--eyebrow-tracking);
  text-transform: uppercase;
  color: var(--color-accent);
  margin-bottom: 0.5rem;
}

.porta-404__title {
  font-family: var(--font-heading);
  font-size: var(--text-3xl);
  color: var(--color-text);
  margin: 0;
}

@media (min-width: 768px) {
  .porta-404__title { font-size: var(--text-4xl); }
}

.porta-404__body {
  text-align: center;
}

.porta-404__message {
  font-size: var(--text-lg);
  color: var(--color-text-light);
  line-height: 1.7;
  max-width: 540px;
  margin: 0 auto 2.5rem;
}

.porta-404__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
  justify-content: center;
}

/* ── Hero background photo (porta_bg_photo(), audit 03-009) ───────────────── */

/* Fills its positioned section like the old cover background did. The section
   keeps its fallback colour; overlays and content stack above it. */
.porta-bg-photo {
  position: absolute;
  inset: 0;
}

.porta-bg-photo img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
}

/* ── Touch targets (owner S9-Q11, audit 09-011 / 09-DR-8) ────────────────────
 * 44px (--tap-size) for every control, at least 24px (--tap-size-link) for
 * text links outside a sentence (links inside a sentence are exempt).
 * Mostly INVISIBLE: a transparent ::after centred on the control extends the
 * area a finger can hit while the drawn shape stays as designed. Where the
 * shape itself grows (pills, buttons) the change is a few pixels. The WooCommerce
 * controls (steppers, selects, add-to-cart, magnifier) are in woocommerce.css,
 * the header's menu button and cart in header.css.
 */
.porta-btn {
  min-height: var(--tap-size);
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.porta-filter__btn,
.porta-footer__social-link,
.porta-lang__link,
.domaine-detail-btn,
.porta-anchor-nav a {
  position: relative;
}

.porta-filter__btn::after,
.porta-footer__social-link::after,
.porta-lang__link::after,
.domaine-detail-btn::after,
.porta-anchor-nav a::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: max(100%, var(--tap-size));
  height: max(100%, var(--tap-size));
  transform: translate(-50%, -50%);
}

/* Filter pills (/nos-vins, /actualites): 36px drawn on touch screens (was 28),
   the ::after above makes the tap area 44px. Desktop keeps its 28px pills. */
@media (pointer: coarse) {
  .porta-filter__btn {
    min-height: 36px;
  }

  /* The /domaine « detail » buttons: 44px drawn (the in-page menu links are
     44px at every width, see .porta-anchor-nav). */
  .domaine-detail-btn {
    min-height: var(--tap-size);
  }
}

/* Footer language links: more space between the letters so the 44px areas
   do not overlap. */
.porta-lang--footer {
  gap: 1.25rem;
}

/* Text links outside a sentence: at least 24px high, padding only. */
.porta-footer__legal a,
.porta-footer__contact-list a,
.porta-tastings__included a,
.porta-tastings__actions a:not(.porta-btn),
.porta-booking__contact a,
.porta-contact__more,
.porta-wine-card__title a,
.porta-gifts__link,
.porta-catalog__note a,
.porta-featured__proof a {
  /* inline-block, not inline-flex: a flex box drops the space before an
     arrow (« Nos distinctions→ »). The padding centres one line in 24px. */
  display: inline-block;
  min-height: var(--tap-size-link);
  padding-block: max(0px, calc((var(--tap-size-link) - 1lh) / 2));
}

