/* Astrid & Matthieu — shared site styles. Mobile-first; built on tokens.css.
   Sept 2026 refresh: rebuilt to match the artistic director's Canva design
   (design_system/reference/A&M SITE MARIAGE - Desktop version preview.pdf).
   Visual language only — every id/class/data-attribute the JS relies on
   (gate.js, save-the-date.js, i18n.js) is preserved; see each file's own
   comments for the audit. */

*, *::before, *::after { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
/* Several elements below set their own `display` (flex/grid); without this,
   that declaration outranks the UA stylesheet's [hidden]{display:none} at
   equal specificity and the element stays visible despite `hidden`. */
[hidden] { display: none !important; }
body {
  background: var(--color-cream);
  color: var(--color-navy);
  font-family: var(--font-body);
  font-size: var(--text-body);
  line-height: var(--leading-body);
  min-height: 100vh;
  -webkit-font-smoothing: antialiased;
}
img { max-width: 100%; display: block; }
a { color: inherit; }
button, input, select { font-family: inherit; font-size: inherit; }

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

/* Focus visibility — accessibility */
a:focus-visible, button:focus-visible, input:focus-visible, select:focus-visible {
  outline: 2px solid var(--color-terracotta);
  outline-offset: 2px;
}

/* ---------- Language switcher: globe button that slides open ----------
   Fixed position, so it sits over whatever background is currently in
   view — photo on the gate page, then cream / navy / forest-green / white
   bands as a guest scrolls the save-the-date page. Each chip carries its
   own translucent cream pill so it stays legible over all of them, rather
   than relying on one text color that would disappear against a dark
   section. */
.lang-switcher {
  position: fixed;
  top: var(--space-3);
  right: var(--space-3);
  z-index: 50;
  display: flex;
  align-items: center;
  gap: 0;
}
.lang-switcher.is-open { gap: var(--space-1); }

.lang-toggle {
  flex: 0 0 auto;
  width: 40px;
  height: 40px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(255,248,234,0.92);
  border: 1.5px solid var(--color-navy);
  border-radius: var(--radius-pill);
  cursor: pointer;
  color: var(--color-navy);
  box-shadow: var(--shadow-card);
}
.globe-icon {
  width: 18px;
  height: 18px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.3;
  stroke-linecap: round;
}

.lang-options {
  display: flex;
  gap: 4px;
  max-width: 0;
  opacity: 0;
  overflow: hidden;
  transition: max-width var(--duration-standard) var(--ease-standard),
              opacity var(--duration-standard) var(--ease-standard);
}
.lang-switcher.is-open .lang-options {
  max-width: 280px;
  opacity: 1;
  overflow: visible;
}
.lang-options button,
.lang-options a {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 4px;
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 11px;
  letter-spacing: var(--tracking-button);
  text-decoration: none;
  background: rgba(255,248,234,0.92);
  border: 1.5px solid transparent;
  color: var(--color-navy);
  padding: 8px 10px;
  border-radius: var(--radius-pill);
  cursor: pointer;
  white-space: nowrap;
  box-shadow: var(--shadow-card);
}
.lang-options .flag { font-size: 13px; }
.lang-options button[aria-current="true"],
.lang-options a[aria-current="true"] {
  background: var(--color-navy);
  color: var(--color-cream);
  border-color: var(--color-navy);
}
.lang-options button:hover,
.lang-options a:hover { border-color: var(--color-navy); }

/* Events (save-the-date) page only, phone widths only: stack the language
   chips vertically below the globe toggle instead of spreading horizontally
   to its left. The gate page keeps the default horizontal layout above. */
@media (max-width: 759px) {
  .save-the-date-page .lang-switcher {
    flex-direction: column-reverse;
    align-items: flex-end;
  }
  .save-the-date-page .lang-options {
    flex-direction: column;
    align-items: flex-end;
    max-width: none;
    max-height: 0;
    transition: max-height var(--duration-standard) var(--ease-standard),
                opacity var(--duration-standard) var(--ease-standard);
  }
  .save-the-date-page .lang-switcher.is-open .lang-options {
    max-width: none;
    max-height: 240px;
  }
}

/* ---------- Scroll hint (save-the-date page only) ----------
   A quiet nudge that there's more below the fold — fixed at the bottom
   center so it reads correctly over every band the page scrolls through
   (cream header, blue-light/green-olive event blocks, white footer),
   using the same translucent-cream-pill treatment as .lang-toggle so it
   stays legible on all of them. JS (save-the-date.js) adds .is-hidden
   once the guest reaches the bottom of the page. */
.scroll-hint {
  position: fixed;
  left: 50%;
  /* env() clears the home-indicator / rounded-corner safe area on phones
     (populated because the save-the-date pages set viewport-fit=cover);
     falls back to plain --space-4 on browsers without env() support. */
  bottom: calc(var(--space-4) + env(safe-area-inset-bottom, 0px));
  transform: translateX(-50%);
  z-index: 40;
  width: 40px;
  height: 40px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(255,248,234,0.92);
  border: 1.5px solid var(--color-navy);
  border-radius: var(--radius-pill);
  color: var(--color-navy);
  box-shadow: var(--shadow-card);
  cursor: pointer;
  opacity: 1;
  visibility: visible;
  transition: opacity var(--duration-standard) var(--ease-standard),
              visibility 0s linear 0s;
  animation: scroll-hint-bounce 1.8s ease-in-out infinite;
}
.scroll-hint svg {
  width: 18px;
  height: 18px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
  stroke-linecap: round;
}
.scroll-hint.is-hidden {
  opacity: 0;
  visibility: hidden;
  transition: opacity var(--duration-standard) var(--ease-standard),
              visibility 0s linear var(--duration-standard);
}
@keyframes scroll-hint-bounce {
  0%, 100% { transform: translateX(-50%) translateY(0); }
  50% { transform: translateX(-50%) translateY(5px); }
}
@media (prefers-reduced-motion: reduce) {
  .scroll-hint { animation: none; }
}

/* ---------- Shared page shell ---------- */
.page {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-9) var(--space-4) var(--space-7);
}

/* Identification / hero page: a soft, blurred heliconia flower photo fills
   the viewport behind the form. The photo is already almost entirely pale
   cream, so only a very light wash is added — just enough to guarantee the
   navy/terracotta ink stays comfortably readable if the source photo is
   ever swapped for something busier. */
.gate-page {
  background-image: linear-gradient(rgba(255,248,234,0.25), rgba(255,248,234,0.45)),
                     url('/assets/images/photos/hero-background-flower.png');
  background-size: cover;
  background-position: center top;
  background-repeat: no-repeat;
  background-color: var(--color-cream);
}

.card {
  width: 100%;
  max-width: 480px;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: var(--space-4);
}

/* Identification page layout: the form card plus the photobooth collage.
   Stacked on mobile; from ~900px up they sit side by side, text left,
   photos right, matching the desktop mockup. */
.gate-stage {
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
}
.hero-photos {
  margin-top: var(--space-8);
  display: flex;
  justify-content: center;
}
.hero-collage {
  width: clamp(200px, 42vw, 320px);
  height: auto;
  filter: drop-shadow(0 16px 32px rgba(7,19,103,0.18));
}
@media (min-width: 900px) {
  .gate-stage {
    flex-direction: row;
    align-items: center;
    justify-content: center;
    gap: var(--space-9);
    width: min(1120px, 94vw);
  }
  .gate-stage .card { flex: 0 0 auto; max-width: 460px; align-items: flex-start; text-align: left; }
  .hero-photos { margin-top: 0; flex: 0 0 auto; }
}

/* Name + eyebrow: the "Astrid & Matthieu" wordmark is the couple's actual
   logo asset (recolored blue-slate per their instruction), not styled
   text — it's a proper-noun lockup, not a translated string, so an <img>
   with a static alt is correct here and doesn't fight the i18n rule that
   forbids hardcoded *copy*. "se marient !" / "are getting married" etc.
   underneath IS translated copy, so that one stays real text
   (data-i18n="gate.eyebrow"), styled as a script accent line.

   The block is sized to the wordmark image (width: fit-content) rather
   than stretched to the card, and the eyebrow line is right-aligned
   within it — so "se marient !" lines up under the right end of
   "Matthieu", matching the PDF, instead of centering under the whole
   lockup. */
.name-block {
  display: flex;
  flex-direction: column;
  width: fit-content;
  max-width: 100%;
  gap: var(--space-1);
}
h1.brand-name {
  margin: 0;
}
h1.brand-name .wordmark {
  width: clamp(230px, 34vw, 380px);
  max-width: 100%;
  height: auto;
  display: block;
}
.eyebrow-accent {
  font-family: var(--font-display);
  font-style: italic;
  font-weight: 400;
  font-size: clamp(1.4rem, 4vw, var(--text-accent-script));
  line-height: var(--leading-snug);
  color: var(--color-terracotta);
  text-align: right;
  margin: 0;
  margin-right: 3%;
}

/* ---------- Identification gate ---------- */
.gate-intro {
  font-size: var(--text-body);
  color: var(--color-navy);
  max-width: 38ch;
  margin: 0;
}
.gate-form {
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-4);
  margin-top: var(--space-3);
  text-align: left;
}
@media (min-width: 900px) {
  .gate-form { align-items: flex-start; }
}
.field { display: flex; flex-direction: column; gap: var(--space-1); width: 100%; }
.field label {
  font-size: 11px;
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  color: var(--color-navy);
  opacity: 0.65;
}

/* Phone combo: a single pill — country button (flag + dial code + chevron)
   and number field share one rounded outline, divided by a hairline —
   rather than a plain native <select>, so the flags render as crisp
   inline SVGs instead of relying on emoji flag support. */
.phone-combo {
  position: relative;
  display: flex;
  align-items: stretch;
  width: 100%;
  background: var(--color-cream);
  border: 1.5px solid var(--color-navy);
  border-radius: var(--radius-pill);
  /* No overflow:hidden here — the country dropdown panel below is an
     absolutely-positioned child that needs to escape this box. Each end
     rounds itself instead (see .phone-country-btn and
     .phone-number-input) so the pill still reads as one seamless shape. */
}
.phone-country-btn {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 6px;
  border: none;
  border-right: 1.5px solid rgba(7,19,103,0.18);
  background: transparent;
  border-top-left-radius: var(--radius-pill);
  border-bottom-left-radius: var(--radius-pill);
  padding: 0 var(--space-3) 0 var(--space-4);
  color: var(--color-navy);
  font-family: var(--font-body);
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
}
.phone-country-btn .chevron {
  width: 14px;
  height: 14px;
  color: var(--color-navy);
  opacity: 0.6;
  transition: transform var(--duration-standard) var(--ease-standard);
}
.phone-country-btn[aria-expanded="true"] .chevron { transform: rotate(180deg); }

.flag-circle {
  flex: 0 0 auto;
  display: inline-flex;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  overflow: hidden;
  box-shadow: 0 0 0 1px rgba(7,19,103,0.15);
}
.flag-circle svg { width: 100%; height: 100%; display: block; }

.field input[type="tel"].phone-number-input {
  flex: 1 1 auto;
  min-width: 0;
  border: none;
  background: transparent;
  border-top-right-radius: var(--radius-pill);
  border-bottom-right-radius: var(--radius-pill);
  padding: 15px var(--space-4);
  color: var(--color-navy);
  width: 100%;
}

/* Shown only when "Other" is picked from the country panel — a manual
   dial-code entry, sitting between the country button and the number
   field so a guest whose country isn't in the short list can still supply
   it. The "+" is printed statically so they just type digits. */
.phone-code-field {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 3px;
  border-right: 1.5px solid rgba(7,19,103,0.18);
  padding: 0 4px 0 var(--space-3);
}
.phone-code-plus {
  color: var(--color-navy);
  opacity: 0.6;
  font-weight: 600;
  font-size: 14px;
}
#gate-country-code.phone-code-input {
  width: 32px;
  border: none;
  border-radius: 0;
  background: transparent;
  padding: 15px 0;
  color: var(--color-navy);
  font-family: inherit;
  /* 16px (not 14px) avoids the automatic zoom-on-focus mobile Safari/Chrome
     trigger for inputs under that size; the field only ever holds 1-3
     digits so the size bump is unnoticeable. */
  font-size: 16px;
  font-weight: 600;
}

.phone-country-panel {
  position: absolute;
  top: calc(100% + var(--space-2));
  left: 0;
  z-index: 30;
  min-width: 230px;
  max-height: 280px;
  overflow-y: auto;
  background: var(--color-white);
  border: 1px solid rgba(7,19,103,0.15);
  border-radius: 16px;
  box-shadow: var(--shadow-card);
  padding: var(--space-1);
}
.phone-country-option {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  width: 100%;
  border: none;
  background: none;
  text-align: left;
  padding: var(--space-2);
  border-radius: 10px;
  cursor: pointer;
  font-family: var(--font-body);
  font-size: 14px;
  color: var(--color-navy);
}
.phone-country-option:hover,
.phone-country-option[aria-selected="true"] { background: rgba(125,153,180,0.16); }
.phone-country-option .country-name { flex: 1 1 auto; }
.phone-country-option .dial {
  flex: 0 0 auto;
  font-family: var(--font-body);
  font-size: 12px;
  color: var(--color-navy);
  opacity: 0.6;
}

/* Outline pill button — reused as-is for the "add to calendar" action once
   that feature is built (see design_system/readme.md open items). */
.btn-outline {
  border: var(--border-button);
  background: transparent;
  color: var(--color-navy);
  border-radius: var(--radius-button);
  padding: 15px var(--space-6);
  font-family: var(--font-body);
  font-size: var(--text-button);
  font-weight: 600;
  letter-spacing: var(--tracking-button);
  text-transform: uppercase;
  cursor: pointer;
  transition: background-color var(--duration-standard) var(--ease-standard),
              color var(--duration-standard) var(--ease-standard);
}
.btn-outline:hover { background: var(--color-navy); color: var(--color-cream); }
.btn-outline[disabled] { opacity: 0.6; cursor: default; }
.btn-outline[disabled]:hover { background: transparent; color: var(--color-navy); }

.gate-submit {
  align-self: center;
  margin-top: var(--space-2);
}
@media (min-width: 900px) {
  .gate-submit { align-self: flex-start; }
}

.gate-status {
  min-height: 1.4em;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  font-size: 13px;
  color: var(--color-navy);
  opacity: 0.75;
}
@media (min-width: 900px) {
  .gate-status { justify-content: flex-start; }
}
.gate-status[data-state="error"] { color: var(--color-terracotta); opacity: 1; }
.gate-status[hidden] { display: none; }

.spinner {
  display: none;
  flex: 0 0 auto;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  border: 2px solid rgba(7,19,103,0.2);
  border-top-color: var(--color-navy);
  animation: am-spin 0.8s linear infinite;
}
.gate-status[data-state="loading"] .spinner { display: inline-block; }

@keyframes am-spin {
  to { transform: rotate(360deg); }
}
@media (prefers-reduced-motion: reduce) {
  .spinner { animation-duration: 2s; }
}

.contact-fallback {
  font-size: 13px;
  color: var(--color-navy);
  opacity: 0.75;
  margin-top: var(--space-2);
}

/* ---------- Save the date ---------- */
.page.page-std {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-start;
  padding: 0;
  gap: 0;
  background: var(--color-cream);
}

/* Cream header band: plain text lockup (not the logo image — kept short
   on purpose so the header doesn't eat too much of the first screen) +
   "Save the Date" caption, no card/box — the band itself is the
   full-width container. */
.std-header {
  width: 100%;
  max-width: none;
  padding: var(--space-6) var(--space-4) var(--space-5);
  background: var(--color-cream);
  gap: var(--space-2);
}
.std-header .brand-name-text {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(1.75rem, 4.5vw, var(--text-h2));
  line-height: var(--leading-tight);
  color: var(--color-blue-light);
  margin: 0;
}
.eyebrow-label {
  font-family: var(--font-body);
  font-size: var(--text-eyebrow);
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  font-weight: 600;
  color: var(--color-terracotta);
  margin: 0;
}

/* Guests invited to both weddings get both sections, Bretagne then Rio,
   stacked full-width — never side by side, on phone or desktop. */
.event-blocks {
  width: 100%;
  display: flex;
  flex-direction: column;
}

/* Each event is a full-bleed color block: a framed photo (the "A&M"
   monogram is overlaid on it in CSS — see .event-monogram — rather than
   baked into the image, so it stays correctly centered regardless of the
   source photo) on one side, the date / location / countdown on the
   other, each taking half the width on a wide screen and the full width
   on a phone.

   Brittany always runs photo-left, text-right (in markup and on screen,
   at every width). Rio is deliberately mirrored on desktop — text/
   countdown first, photo second — but the markup keeps that same
   text-then-photo order at every width, so on a phone (where the block
   stacks vertically) it would show the countdown above the photo. Since
   the couple wants the photo to land first on a phone regardless, the
   mobile breakpoint below flips it back with `order`. */
.event-block {
  position: relative;
  width: 100%;
  display: flex;
  flex-direction: column;
  background-repeat: no-repeat;
  background-position: center;
  background-size: cover;
}
@media (min-width: 760px) {
  .event-block { flex-direction: row; min-height: 700px; }
}
@media (max-width: 759px) {
  .event-block[data-event="rio"] .event-photo { order: 1; }
  .event-block[data-event="rio"] .event-text { order: 2; }
}

.event-block[data-event="brittany"] {
  background-color: var(--color-blue-light);
  background-image: url('/assets/images/patterns/overlay-bretagne-pattern.png');
}
.event-block[data-event="rio"] {
  background-color: var(--color-green-olive);
  background-image: url('/assets/images/patterns/overlay-rio-pattern.png');
}

/* The photo sits inset within its half, at a fixed size, so the section's
   color and pattern show all around it instead of the photo filling the
   half edge-to-edge. */
.event-photo {
  position: relative;
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-7) var(--space-6);
}
@media (min-width: 760px) {
  .event-photo { width: 50%; min-height: 100%; }
}
.event-photo-frame {
  position: relative;
  width: min(500px, 100%);
  aspect-ratio: 4 / 5;
  overflow: hidden;
  box-shadow: var(--shadow-card);
}
.event-photo-frame .event-photo-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
/* The couple's "A&M" monogram, centered over the photo — a separate,
   correctly-cropped SVG (not part of the photo file), so it always lands
   dead center no matter how the photo itself is cropped.
   NOTE: this rule used to lose the cascade to the bare `.event-photo-frame
   img` selector above (a class+tag compound beats a single class), which
   forced the monogram to stretch to 100%/100% cover-fit. The photo image
   now carries its own .event-photo-img class so this rule applies. */
.event-monogram {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 33%;
  height: auto;
}

.event-text {
  position: relative;
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-8) var(--space-5);
  padding-top: var(--space-4);
  text-align: center;
}
@media (min-width: 760px) {
  .event-text { width: 50%; padding: var(--space-8); }
}
.event-text-inner { max-width: 480px; display: flex; flex-direction: column; align-items: center; }

.event-date {
  display: block;
  font-family: var(--font-display);
  font-weight: 500;
  font-size: var(--text-h1);
  line-height: var(--leading-tight);
}
.event-location {
  margin: var(--space-2) 0 var(--space-6);
  font-family: var(--font-body);
  font-size: var(--text-h2);
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  opacity: 0.92;
}
.event-block[data-event="brittany"] .event-date,
.event-block[data-event="brittany"] .event-location { color: var(--color-gold); }
.event-block[data-event="rio"] .event-date,
.event-block[data-event="rio"] .event-location { color: var(--color-cream); }

/* Countdown as quiet serif numerals, matching the date's display font
   rather than a monospace UI digit — closer to a printed caption than a
   UI widget. */
.countdown {
  display: flex;
  align-items: flex-start;
  gap: var(--space-4);
  justify-content: center;
}
.count-block {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  min-width: 38px;
}
.count-num {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(1.3rem, 3vw, 1.85rem);
  line-height: 1;
}
.count-label {
  font-family: var(--font-body);
  font-size: 9px;
  font-weight: 600;
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  opacity: 0.75;
}
.count-sep {
  align-self: flex-start;
  margin-top: 2px;
  font-family: var(--font-display);
  font-size: clamp(1.3rem, 3vw, 1.85rem);
  opacity: 0.5;
}
.event-block[data-event="brittany"] .count-num,
.event-block[data-event="brittany"] .count-sep,
.event-block[data-event="brittany"] .count-label { color: var(--color-gold); }
.event-block[data-event="rio"] .count-num,
.event-block[data-event="rio"] .count-sep,
.event-block[data-event="rio"] .count-label { color: var(--color-cream); }

/* A small decorative mark (shell / coconut) under the countdown — its own
   image now, not baked into the background pattern, so it always sits in
   the same spot relative to the countdown instead of drifting or
   disappearing at odd aspect ratios. */
.event-icon {
  width: 40px;
  height: auto;
  margin: var(--space-4) 0 0;
  display: block;
}

/* On a wide screen the text half is far bigger than the 480px column it
   was designed at, leaving it looking sparse next to the photo. Scale the
   date, location, countdown and icon up (and loosen the column's max
   width) so the text actually fills more of its half instead of just
   growing whitespace around it. */
@media (min-width: 1200px) {
  .event-text-inner { max-width: 640px; }
  .event-date { font-size: 3.4rem; }
  .event-location { font-size: 1.35rem; }
  .count-num,
  .count-sep { font-size: clamp(1.85rem, 2.4vw, 2.75rem); }
  .count-label { font-size: 11px; }
  .event-icon { width: 56px; }
}

/* Closing note: white band, title + short sign-off + the couple's pink
   signature lockup. */
.more-info {
  width: 100%;
  padding: var(--space-6) var(--space-4);
  text-align: center;
  background: var(--color-white);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-4);
}
.more-info-title {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(1.5rem, 4vw, var(--text-h2));
  color: var(--color-navy);
  margin: 0;
  padding-top: 2%;
  max-width: 32ch;
  white-space: pre-line;
}
.more-info-body {
  font-family: var(--font-body);
  font-size: var(--text-body);
  color: var(--color-navy);
  opacity: 0.75;
  margin: 0;
  white-space: pre-line;
  max-width: 46ch;
}
.footer-signature {
  width: clamp(150px, 26vw, 210px);
  height: auto;
  margin-top: var(--space-2);
}

/* ---------- Responsive: tablet and up ---------- */
@media (min-width: 720px) {
  .card { max-width: 560px; }
}
