/* ==========================================================================
   JOVI — Design System & Homepage Styles
   "Give something that stays."

   Table of contents:
   1.  Fonts
   2.  Reset
   3.  Design tokens
   4.  Base / typography
   5.  Layout helpers
   6.  Accessibility helpers
   7.  Buttons
   8.  Concept banner
   9.  Header / navigation
   10. Mobile menu
   11. Opening
   12. Section heading pattern
   13. Origin
   14. The Material
   15. The Objects (curated edits + product list)
   16. Personalisation
   17. Gift It (gift finder / what's in the bag / packaging)
   18. JOVI Wall
   19. Visit & Close
   20. Footer
   21. Reveal animation
   22. Responsive tweaks
   ========================================================================== */

/* 1. Fonts
   Instrument Serif — the structural editorial display voice. Upright by
   default; italic is reserved for genuine emotional emphasis (an <em> word,
   a pull-quote), never the default treatment for labels or prices.
   Hanken Grotesk — body copy, navigation, UI.
   Loaded via <link> in the <head> so the browser fetches them in parallel
   with this stylesheet.
   ========================================================================== */

/* 2. Reset
   ========================================================================== */
*,
*::before,
*::after {
  box-sizing: border-box;
}

* {
  margin: 0;
}

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

img,
picture,
svg {
  display: block;
  max-width: 100%;
}

button,
input {
  font: inherit;
  color: inherit;
}

button {
  background: none;
  border: none;
  cursor: pointer;
}

a {
  color: inherit;
  text-decoration: none;
}

ul,
ol {
  list-style: none;
  padding: 0;
}

blockquote {
  margin: 0;
}

/* 3. Design tokens
   ========================================================================== */
:root {
  /* Two canvases. Everything else is a surface tint of one of these two. */
  --jovi-paper: #F7F1E4;
  --jovi-paper-alt: #FCF9F2;
  --jovi-espresso: #241712;
  --jovi-espresso-soft: #4A362B;

  /* The one accent. */
  --jovi-maroon: #8C232E;
  --jovi-maroon-deep: #6E1B24;

  /* Literal leather/thread colours — used ONLY inside swatch dots to
     represent a real product colourway. Never a section or card fill. */
  --jovi-terracotta: #C1663B;
  --jovi-pistachio: #A7B98C;
  --jovi-black: #221D1A;

  /* Semantic tokens */
  --color-bg: var(--jovi-paper);
  --color-bg-soft: var(--jovi-paper-alt);
  --color-ink: var(--jovi-espresso);
  --color-ink-soft: var(--jovi-espresso-soft);
  --color-accent: var(--jovi-maroon);
  --color-line: rgba(36, 23, 18, 0.14);

  --color-on-dark: var(--jovi-paper);
  --color-on-dark-soft: rgba(247, 241, 228, 0.82);
  --color-on-dark-tertiary: rgba(247, 241, 228, 0.64);
  --color-line-on-dark: rgba(247, 241, 228, 0.2);

  --font-display: 'Instrument Serif', Georgia, 'Times New Roman', serif;
  --font-sans: 'Hanken Grotesk', 'Helvetica Neue', Arial, sans-serif;

  --container-w: 1280px;

  /* Two radii: one functional, one for photographs/large surfaces. */
  --radius-sm: 6px;
  --radius-img: 20px;
  --radius-pill: 999px;

  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);

  --space-section: clamp(5rem, 10vw, 9rem);

  --grain: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.5'/%3E%3C/svg%3E");
}

/* 4. Base / typography
   ========================================================================== */
body {
  background: var(--color-bg);
  color: var(--color-ink);
  font-family: var(--font-sans);
  font-size: 1rem;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: 400;
  font-style: normal;
  line-height: 1.02;
  letter-spacing: -0.01em;
}

h1 { font-size: clamp(3.25rem, 6vw + 1.5rem, 7.5rem); }
h2 { font-size: clamp(2.25rem, 3.4vw + 1.1rem, 4.25rem); }
h3 { font-size: clamp(1.5rem, 1.2vw + 1rem, 2rem); }
h4 { font-family: var(--font-sans); font-weight: 700; font-size: clamp(1.1rem, 0.6vw + 0.9rem, 1.35rem); }

em {
  font-style: italic;
  color: var(--jovi-maroon);
}

p {
  max-width: 60ch;
}

.no-scroll {
  overflow: hidden;
}

/* 5. Layout helpers
   ========================================================================== */
.container {
  max-width: var(--container-w);
  margin-inline: auto;
  padding-inline: clamp(1.25rem, 4vw, 3rem);
}

section {
  padding-block: var(--space-section);
}

/* 6. Accessibility helpers
   ========================================================================== */
.skip-link {
  position: absolute;
  left: 1rem;
  top: -3rem;
  background: var(--jovi-espresso);
  color: var(--jovi-paper);
  padding: 0.75rem 1.25rem;
  border-radius: var(--radius-sm);
  z-index: 200;
  transition: top 0.2s var(--ease);
}

.skip-link:focus {
  top: 1rem;
}

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

a[aria-disabled="true"],
button[aria-disabled="true"] {
  cursor: not-allowed;
  opacity: 0.6;
}

:focus-visible {
  outline: 2px solid var(--jovi-maroon);
  outline-offset: 3px;
}

/* 7. Buttons
   Two shapes only: the pill CTA, and a plain text link. No outline/ghost
   variants are needed once "Add to Bag"-style secondary actions are gone.
   ========================================================================== */
.btn {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-family: var(--font-sans);
  font-weight: 700;
  font-size: 0.95rem;
  padding: 0.95rem 1.85rem;
  border-radius: var(--radius-pill);
  transition: transform 0.25s var(--ease), background-color 0.25s var(--ease);
}

.btn--primary {
  background: var(--jovi-maroon);
  color: var(--jovi-paper);
}

.btn--primary:hover {
  background: var(--jovi-maroon-deep);
  transform: translateY(-2px);
}

.btn--sm {
  padding: 0.55rem 1.25rem;
  font-size: 0.85rem;
}

.btn--lg {
  padding: 1.15rem 2.4rem;
  font-size: 1.05rem;
}

.link-underline {
  display: inline-block;
  font-weight: 700;
  border-bottom: 1.5px solid var(--jovi-maroon);
  padding-bottom: 0.15rem;
}

/* 8. Concept banner
   ========================================================================== */
.concept-banner {
  background: var(--jovi-espresso);
  color: var(--jovi-paper);
  text-align: center;
  font-size: 0.78rem;
  padding: 0.55rem 1rem;
  letter-spacing: 0.01em;
}

.concept-banner a {
  text-decoration: underline;
  text-underline-offset: 2px;
}

.banner-text-short { display: none; }

/* 9. Header / navigation
   No search / account / cart icons — those weren't functional, and a
   disabled affordance reads worse than no affordance at all.
   ========================================================================== */
.site-header {
  position: sticky;
  top: 0;
  z-index: 100;
  background: rgba(247, 241, 228, 0.92);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--color-line);
}

.site-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  padding-block: 1.1rem;
}

.logo a {
  font-family: var(--font-display);
  font-size: 1.8rem;
  color: var(--jovi-maroon);
}

.primary-nav {
  display: flex;
  align-items: center;
  gap: clamp(1.25rem, 2.5vw, 2.5rem);
}

.nav-link {
  font-size: 0.92rem;
  font-weight: 600;
  position: relative;
  padding-block: 0.25rem;
}

.nav-link::after {
  content: '';
  position: absolute;
  left: 0;
  right: 100%;
  bottom: 0;
  height: 2px;
  background: var(--jovi-maroon);
  transition: right 0.25s var(--ease);
}

.nav-link:hover::after {
  right: 0;
}

.header-actions {
  display: flex;
  align-items: center;
  gap: 1rem;
}

.icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.4rem;
  height: 2.4rem;
}

.menu-toggle {
  display: none;
}

.menu-toggle__box {
  display: flex;
  flex-direction: column;
  gap: 5px;
  width: 22px;
}

.menu-toggle__box span {
  display: block;
  height: 2px;
  background: var(--jovi-espresso);
  transition: transform 0.25s var(--ease), opacity 0.25s var(--ease);
}

.menu-toggle[aria-expanded="true"] .menu-toggle__box span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.menu-toggle[aria-expanded="true"] .menu-toggle__box span:nth-child(2) { opacity: 0; }
.menu-toggle[aria-expanded="true"] .menu-toggle__box span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

/* 10. Mobile menu
   ========================================================================== */
.mobile-menu {
  position: fixed;
  inset: 0;
  z-index: 150;
  background: var(--jovi-paper);
  transform: translateX(100%);
  transition: transform 0.35s var(--ease);
  display: flex;
  flex-direction: column;
  padding: 1.25rem;
  overflow-y: auto;
}

.mobile-menu.is-open {
  transform: translateX(0);
}

.mobile-menu__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 2.5rem;
}

.mobile-menu__links {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}

.mobile-menu__links a {
  font-family: var(--font-display);
  font-size: 2.25rem;
  padding-block: 0.35rem;
}

.mobile-menu__meta {
  margin-top: auto;
  padding-top: 2rem;
  font-size: 0.85rem;
  color: var(--color-ink-soft);
}

/* 11. Opening
   An editorial spread, not a storefront banner: one headline, one line,
   one CTA, one large photograph. No gradient, no grain overlay, no
   floating meta card, no second competing CTA.
   ========================================================================== */
.opening {
  padding-block: 0;
  min-height: 92vh;
  display: flex;
  align-items: center;
  position: relative;
  overflow: hidden;
}

.opening__inner {
  margin-inline: 0;
  max-width: 34rem;
  padding-block: clamp(3rem, 8vw, 5rem);
  position: relative;
  z-index: 1;
}

.opening__eyebrow,
.opening .eyebrow {
  margin-bottom: 1.5rem;
}

.opening h1 {
  max-width: 13ch;
  margin-bottom: 1.75rem;
}

.opening__sub {
  max-width: 34ch;
  font-size: clamp(1.05rem, 0.6vw + 0.9rem, 1.2rem);
  color: var(--color-ink-soft);
  margin-bottom: 2.25rem;
}

.opening__figure {
  position: absolute;
  inset: 0;
  left: 44%;
  z-index: 0;
}

.opening__figure::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(to right, var(--jovi-paper) 0%, rgba(247, 241, 228, 0) 16%);
  pointer-events: none;
}

.opening__figure img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.opening__scroll-cue {
  position: absolute;
  bottom: 2rem;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.72rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--color-ink-soft);
}

.opening__scroll-cue .line {
  width: 1px;
  height: 34px;
  background: linear-gradient(var(--color-ink-soft), transparent);
}

/* 12. Section heading pattern
   ========================================================================== */
.eyebrow {
  text-transform: uppercase;
  letter-spacing: 0.14em;
  font-size: 0.78rem;
  font-weight: 700;
  color: var(--jovi-maroon);
  margin-bottom: 0.75rem;
}

.eyebrow--light {
  color: var(--color-on-dark-tertiary);
}

.section-head {
  max-width: 46rem;
  margin-bottom: clamp(2.5rem, 5vw, 4rem);
}

.section-head__sub {
  margin-top: 0.85rem;
  color: var(--color-ink-soft);
  font-size: 1.05rem;
}

.section-head__sub--light {
  color: var(--color-on-dark-soft);
}

/* 13. Origin
   A reading moment, a documentary photograph bled to the edge beside it —
   the workbench grounds the pull-quote in a real, small studio.
   ========================================================================== */
.origin {
  overflow: hidden;
}

.origin__layout {
  display: flex;
  align-items: stretch;
  gap: clamp(2rem, 5vw, 4rem);
}

.origin__inner {
  flex: 1 1 45%;
  max-width: 46rem;
  padding-inline-start: clamp(1.25rem, 4vw, 3rem);
  display: flex;
  flex-direction: column;
  justify-content: center;
}

.origin__quote {
  font-style: italic;
  max-width: 15ch;
  margin-bottom: clamp(2rem, 4vw, 3rem);
}

.origin__body p {
  font-size: 1.1rem;
  color: var(--color-ink-soft);
  max-width: 56ch;
  margin-bottom: 1.5rem;
}

.origin__signoff {
  margin-top: 1.5rem;
  font-size: 0.85rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--jovi-maroon);
}

.origin__figure {
  flex: 1 1 55%;
  min-height: clamp(22rem, 34vw, 32rem);
  overflow: hidden;
}

.origin__figure img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 65% 55%;
  display: block;
}

/* 14. The Material — signature moment
   The photograph does the work. Text is minimal and sits below it.
   ========================================================================== */
.material {
  padding-block: 0;
  background: var(--jovi-espresso);
}

.material__figure {
  position: relative;
  width: 100%;
  height: 88vh;
  min-height: 480px;
  max-height: 920px;
  background-image: url("../images/materials/leather-grain.webp");
  background-size: cover;
  background-position: center;
  display: flex;
  align-items: flex-end;
}

.material__scrim {
  position: absolute;
  inset: 0;
  background: linear-gradient(to top, rgba(36, 23, 18, 0.85) 0%, rgba(36, 23, 18, 0.4) 32%, transparent 62%);
  pointer-events: none;
}

.material__caption {
  position: relative;
  z-index: 1;
  padding-block: clamp(2.5rem, 6vw, 4.5rem);
  color: var(--jovi-paper);
  max-width: 42rem;
}

.material__caption h2 {
  color: var(--jovi-paper);
  max-width: 16ch;
  margin-bottom: 1rem;
}

.material__caption p {
  color: var(--color-on-dark-soft);
  font-size: 1.05rem;
  max-width: 46ch;
}

.material__caption .eyebrow { color: var(--color-on-dark-tertiary); }

/* 15. The Objects
   Curated edits + an editorial object list — alternating, photography-led,
   no dense card grid, no stock/scarcity chrome. Each edit group leads with
   a square lifestyle photo (see images/lifestyle/README.txt); until a
   real photo exists at a given path, its onerror swaps in the matching
   art-directed SVG illustration so the layout never shows a broken image.
   ========================================================================== */
.edits {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(2rem, 4vw, 4rem);
  margin-bottom: clamp(3rem, 6vw, 5rem);
  padding-bottom: clamp(2.5rem, 5vw, 4rem);
  border-bottom: 1px solid var(--color-line);
}

.edits__figure {
  aspect-ratio: 1 / 1;
  overflow: hidden;
  border-radius: 2px;
  margin-bottom: 1.25rem;
}

.edits__figure img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.edits__label {
  font-size: 0.78rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--color-ink-soft);
  margin-bottom: 1rem;
}

.edits__list {
  display: flex;
  flex-direction: column;
}

.edits__list li {
  display: flex;
  justify-content: space-between;
  padding-block: 0.65rem;
  border-top: 1px solid var(--color-line);
  font-family: var(--font-display);
  font-size: 1.15rem;
}

.edits__list li:last-child {
  border-bottom: 1px solid var(--color-line);
}

.objects__list {
  display: flex;
  flex-direction: column;
  gap: clamp(4rem, 8vw, 7rem);
}

.product-card {
  display: flex;
  align-items: center;
  gap: clamp(2rem, 5vw, 4.5rem);
}

.product-card--reverse {
  flex-direction: row-reverse;
}

.product-card--hero .product-card__frame {
  flex: 0 0 60%;
}

.product-card--hero .product-card__name {
  font-size: clamp(2rem, 2vw + 1.2rem, 2.9rem);
}

/* Paired accessories — two small objects grouped tightly to break the
   repeating hero rhythm. */
.product-pair {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(1.75rem, 4vw, 3rem);
}

.product-card--compact {
  flex-direction: column;
  align-items: stretch;
  gap: 1rem;
}

.product-card--compact .product-card__frame {
  flex: none;
  aspect-ratio: 1 / 1;
}

.product-card--compact .product-card__name {
  font-size: clamp(1.25rem, 1vw + 1rem, 1.6rem);
  margin-bottom: 0.5rem;
}

.product-card--compact .product-card__meta {
  font-size: 0.92rem;
  margin-bottom: 1rem;
}

.product-card--solo {
  max-width: 22rem;
  margin-inline: auto;
  text-align: center;
}

.product-card--solo .product-card__frame {
  aspect-ratio: 4 / 5;
}

.product-card--solo .product-card__row {
  justify-content: center;
}

/* A dramatic full-width moment for the gift set — the photograph runs
   the width of the section with the copy anchored beneath it. */
.product-card--feature {
  display: block;
}

.product-card--feature .product-card__frame {
  width: 100%;
  aspect-ratio: 21 / 10;
  margin-bottom: clamp(1.5rem, 3vw, 2.25rem);
}

.product-card--feature .product-card__body {
  max-width: 34rem;
  margin-inline: auto;
  text-align: center;
}

.product-card--feature .product-card__row {
  justify-content: center;
}

/* .product-card__meta and .product-card__color-label are shared across
   every card variant; only the centered ones (--solo, --feature) need
   their own box centered to match the text-align:center already set on
   their ancestor — left-aligned variants must stay untouched. */
.product-card--solo .product-card__meta,
.product-card--solo .product-card__color-label,
.product-card--feature .product-card__meta,
.product-card--feature .product-card__color-label {
  margin-inline: auto;
}

.product-card__frame {
  flex: 0 0 55%;
  aspect-ratio: 4 / 5;
  border-radius: var(--radius-img);
  overflow: hidden;
}

.product-card__frame img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.6s var(--ease);
}

.product-card:hover .product-card__frame img {
  transform: scale(1.03);
}

.product-card__body {
  flex: 1;
}

.product-card__name {
  font-family: var(--font-display);
  font-size: clamp(1.75rem, 1.6vw + 1.1rem, 2.5rem);
  margin-bottom: 0.75rem;
}

.product-card__meta {
  font-size: 1.02rem;
  color: var(--color-ink-soft);
  max-width: 40ch;
  margin-bottom: 1.5rem;
}

.product-card__row {
  display: flex;
  align-items: center;
  gap: 1.5rem;
  margin-bottom: 0.5rem;
}

.product-card__price {
  font-family: var(--font-display);
  font-size: 1.3rem;
}

.swatches {
  display: inline-flex;
  gap: 0.5rem;
}

.swatch {
  width: 1rem;
  height: 1rem;
  border-radius: 50%;
  background: var(--sw);
  border: 1px solid rgba(36, 23, 18, 0.15);
  padding: 0;
  transition: transform 0.2s var(--ease);
}

.swatch:hover {
  transform: scale(1.15);
}

.swatch.is-active {
  box-shadow: 0 0 0 2px var(--color-bg), 0 0 0 3px var(--jovi-espresso);
}

.product-card__color-label {
  font-size: 0.85rem;
  color: var(--color-ink-soft);
}

.objects__prompt {
  margin-top: clamp(3rem, 6vw, 5rem);
  padding-top: clamp(2.5rem, 5vw, 4rem);
  border-top: 1px solid var(--color-line);
  font-size: 1.1rem;
  color: var(--color-ink-soft);
  text-align: center;
  margin-inline: auto;
}

/* 16. Personalisation — signature moment
   The one deliberate polarity-flip on the page: dark canvas, generous
   space, minimal controls. A subtle shadow is allowed here — it's one of
   the two places on the site a major photograph earns it.
   ========================================================================== */
.personalise {
  background: var(--jovi-espresso);
  color: var(--jovi-paper);
}

.personalise__inner {
  display: grid;
  grid-template-columns: 0.9fr 1.25fr;
  gap: clamp(2.5rem, 5vw, 5rem);
  align-items: center;
}

.personalise h2 { color: var(--jovi-paper); }

.personalise__body {
  font-size: 1.1rem;
  color: var(--color-on-dark-soft);
  margin-block: 1.25rem;
  max-width: 40ch;
}

.personalise__controls {
  display: flex;
  flex-direction: column;
  gap: 1.75rem;
  margin-top: 1.5rem;
}

.personalise__input {
  padding: 1rem 1.25rem;
  border-radius: var(--radius-sm);
  border: 1.5px solid var(--color-line-on-dark);
  background: rgba(247, 241, 228, 0.06);
  color: var(--jovi-paper);
  font-family: var(--font-display);
  font-style: italic;
  font-size: 1.5rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  max-width: 20rem;
}

.personalise__input::placeholder {
  color: var(--color-on-dark-soft);
}

.personalise__targets {
  display: flex;
  flex-wrap: wrap;
  gap: 0.65rem;
}

.pz-target {
  padding: 0.6rem 1.15rem;
  border-radius: var(--radius-pill);
  border: 1.5px solid var(--color-line-on-dark);
  color: var(--color-on-dark-soft);
  font-weight: 600;
  font-size: 0.88rem;
  transition: background-color 0.2s var(--ease), color 0.2s var(--ease), border-color 0.2s var(--ease);
}

.pz-target.is-active {
  background: var(--jovi-maroon);
  border-color: var(--jovi-maroon);
  color: var(--jovi-paper);
}

.personalise__preview {
  text-align: center;
}

.pz-stage {
  position: relative;
  max-width: 480px;
  margin-inline: auto;
}

.pz-image {
  border-radius: var(--radius-img);
  overflow: hidden;
  box-shadow: 0 30px 60px -25px rgba(0, 0, 0, 0.55);
}

.pz-image img {
  width: 100%;
  display: block;
}

.pz-engrave {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  font-family: var(--font-display);
  font-style: italic;
  font-size: clamp(1.4rem, 4vw, 2.6rem);
  letter-spacing: 0.08em;
  color: var(--jovi-espresso);
  text-shadow: 1px 1px 0 rgba(255, 255, 255, 0.5), -1px -1px 0 rgba(0, 0, 0, 0.15);
  min-height: 1em;
}

.pz-engrave--fob {
  top: 64%;
  font-size: clamp(1.1rem, 3vw, 1.5rem);
}

.pz-caption {
  margin-top: 1rem;
  font-size: 0.78rem;
  color: var(--color-on-dark-soft);
  margin-inline: auto;
}

.pz-buy {
  margin-top: 1.75rem;
}

.pz-buy__name {
  font-family: var(--font-display);
  font-size: 1.25rem;
  margin-inline: auto;
}

.pz-buy__price {
  font-size: 0.9rem;
  color: var(--color-on-dark-soft);
  margin-top: 0.25rem;
  margin-inline: auto;
}

/* 17. Gift It
   Three consolidated moments — a small quiz entry, the bag annotation,
   and the packaging ritual — inside one narrative beat.
   ========================================================================== */
.gift-finder {
  max-width: 40rem;
  margin: 0 auto clamp(4rem, 8vw, 6rem);
}

.gift-finder__heading {
  text-align: center;
  margin-bottom: 2rem;
}

.gift-finder__panel {
  border: 1px solid var(--color-line);
  border-radius: var(--radius-img);
  padding: clamp(1.75rem, 4vw, 2.5rem);
}

.gift-finder__progress {
  display: flex;
  gap: clamp(0.75rem, 2vw, 2rem);
  margin-bottom: 2rem;
  flex-wrap: wrap;
}

.gift-finder__progress li {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--color-ink-soft);
}

.gift-finder__progress span {
  width: 1.6rem;
  height: 1.6rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  border: 1.5px solid var(--color-line);
  font-size: 0.78rem;
}

.gift-finder__progress li.is-active {
  color: var(--jovi-maroon);
}

.gift-finder__progress li.is-active span,
.gift-finder__progress li.is-done span {
  background: var(--jovi-maroon);
  border-color: var(--jovi-maroon);
  color: var(--jovi-paper);
}

.gift-finder__step {
  display: none;
}

.gift-finder__step.is-active {
  display: block;
  animation: gf-fade 0.35s var(--ease);
}

@keyframes gf-fade {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: translateY(0); }
}

.gift-finder__step h4 {
  margin-bottom: 1.25rem;
}

.gift-finder__options {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
}

.gf-option {
  padding: 0.8rem 1.35rem;
  border-radius: var(--radius-pill);
  border: 1.5px solid var(--color-line);
  font-weight: 600;
  font-size: 0.92rem;
  transition: border-color 0.2s var(--ease), color 0.2s var(--ease);
}

.gf-option:hover {
  border-color: var(--jovi-maroon);
  color: var(--jovi-maroon);
}

.gf-back {
  margin-top: 1.25rem;
  font-weight: 600;
  font-size: 0.9rem;
  color: var(--color-ink-soft);
}

.gf-back:hover {
  color: var(--jovi-maroon);
}

.gift-finder__results {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 1.5rem;
  margin-bottom: 1.5rem;
}

.gf-result-card {
  border-top: 1px solid var(--color-line);
  padding-top: 1rem;
}

.gf-result-card__image {
  aspect-ratio: 4 / 5;
  border-radius: var(--radius-img);
  overflow: hidden;
  margin-bottom: 1rem;
}

.gf-result-card__image img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.gf-result-card__chip {
  display: inline-block;
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--jovi-maroon);
  margin-bottom: 0.5rem;
}

.gf-result-card h4 {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 1.4rem;
  margin-bottom: 0.3rem;
}

.gf-result-card__price {
  font-size: 0.95rem;
  font-weight: 700;
  margin-bottom: 0.6rem;
}

.gf-result-card p {
  font-size: 0.92rem;
  color: var(--color-ink-soft);
  margin-bottom: 0.75rem;
}

.gf-restart {
  font-weight: 700;
  font-size: 0.9rem;
  color: var(--jovi-maroon);
  border-bottom: 1.5px solid currentColor;
}

.bag-annotate {
  margin-bottom: clamp(4rem, 8vw, 6rem);
}

.bag-annotate__layout {
  display: grid;
  grid-template-columns: 1.15fr 1fr;
  gap: clamp(2.5rem, 6vw, 5rem);
  align-items: center;
}

.bag-annotate__frame {
  position: relative;
  aspect-ratio: 4 / 5;
  border-radius: var(--radius-img);
  overflow: hidden;
}

.bag-annotate__frame img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.bag-annotate__markers {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.bag-annotate__marker {
  position: absolute;
  top: var(--y);
  right: 0;
  display: flex;
  align-items: center;
  transform: translate(50%, -50%);
}

.bag-annotate__marker-dot {
  flex: none;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--jovi-paper-alt);
  border: 1.5px solid var(--jovi-espresso);
  transition: background-color 0.25s var(--ease), border-color 0.25s var(--ease), transform 0.25s var(--ease);
}

.bag-annotate__marker-line {
  width: 28px;
  height: 1px;
  background: var(--color-line);
  transition: background-color 0.25s var(--ease);
}

.bag-annotate__list {
  list-style: none;
}

.bag-annotate__list li:not(:last-child) {
  border-bottom: 1px solid var(--color-line);
}

.bag-annotate__row {
  display: flex;
  align-items: flex-start;
  gap: 1.1rem;
  width: 100%;
  padding: 1.15rem 0;
  background: none;
  border: none;
  text-align: left;
  font: inherit;
  color: inherit;
  cursor: pointer;
  transition: transform 0.25s var(--ease);
}

.bag-annotate__row:hover,
.bag-annotate__row:focus-visible {
  transform: translateX(4px);
}

.bag-annotate__index {
  flex: none;
  width: 2ch;
  font-family: var(--font-display);
  font-size: 1.5rem;
  line-height: 1.1;
  color: var(--color-ink-soft);
  transition: color 0.25s var(--ease);
}

.bag-annotate__row:hover .bag-annotate__index,
.bag-annotate__row:focus-visible .bag-annotate__index {
  color: var(--jovi-maroon);
}

.bag-annotate__name {
  display: block;
  font-weight: 700;
  font-size: 1.05rem;
}

.bag-annotate__desc {
  display: block;
  margin-top: 0.3rem;
  font-size: 0.88rem;
  color: var(--color-ink-soft);
}

.bag-annotate__layout:has(.bag-annotate__row[data-annotate-target="1"]:is(:hover, :focus-visible)) [data-annotate-marker="1"] .bag-annotate__marker-dot,
.bag-annotate__layout:has(.bag-annotate__row[data-annotate-target="2"]:is(:hover, :focus-visible)) [data-annotate-marker="2"] .bag-annotate__marker-dot,
.bag-annotate__layout:has(.bag-annotate__row[data-annotate-target="3"]:is(:hover, :focus-visible)) [data-annotate-marker="3"] .bag-annotate__marker-dot,
.bag-annotate__layout:has(.bag-annotate__row[data-annotate-target="4"]:is(:hover, :focus-visible)) [data-annotate-marker="4"] .bag-annotate__marker-dot {
  background: var(--jovi-maroon);
  border-color: var(--jovi-maroon);
  transform: scale(1.4);
}

.bag-annotate__layout:has(.bag-annotate__row[data-annotate-target="1"]:is(:hover, :focus-visible)) [data-annotate-marker="1"] .bag-annotate__marker-line,
.bag-annotate__layout:has(.bag-annotate__row[data-annotate-target="2"]:is(:hover, :focus-visible)) [data-annotate-marker="2"] .bag-annotate__marker-line,
.bag-annotate__layout:has(.bag-annotate__row[data-annotate-target="3"]:is(:hover, :focus-visible)) [data-annotate-marker="3"] .bag-annotate__marker-line,
.bag-annotate__layout:has(.bag-annotate__row[data-annotate-target="4"]:is(:hover, :focus-visible)) [data-annotate-marker="4"] .bag-annotate__marker-line {
  background: var(--jovi-maroon);
}

.packaging__steps {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 2rem;
}

.packaging__steps svg {
  width: 40px;
  height: 40px;
  margin-bottom: 1.25rem;
  color: var(--jovi-maroon);
}

.packaging__steps h4 {
  margin-bottom: 0.5rem;
}

.packaging__steps p {
  font-size: 0.92rem;
  color: var(--color-ink-soft);
}

/* The ritual, photographed — a 3-panel triptych (prepare / wrap / give)
   shown at its natural aspect ratio so all three stages stay intact at
   any width, rather than cropped into a fixed frame. */
.packaging__figure {
  margin: 0;
  margin-top: clamp(2.5rem, 5vw, 4rem);
  border-radius: var(--radius-img);
  overflow: hidden;
}

.packaging__figure img {
  display: block;
  width: 100%;
  height: auto;
}

/* 18. JOVI Wall — an editorial contact sheet, not a pinboard.
   No rotation, no emoji, no rainbow of pastel tiles.
   ========================================================================== */
.wall {
  background: var(--jovi-espresso);
  color: var(--jovi-paper);
}

.wall h2, .wall .eyebrow--light { color: inherit; }

.wall__board {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-auto-rows: 160px;
  gap: 1px;
  background: var(--color-line-on-dark);
}

.wall__tile {
  background: var(--jovi-espresso);
  padding: 1.5rem;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  font-size: 0.9rem;
}

.wall__tile--quote,
.wall__tile--image {
  grid-column: span 2;
  grid-row: span 2;
}

.wall__tile--quote blockquote {
  font-family: var(--font-display);
  font-style: italic;
  font-size: 1.35rem;
  margin-bottom: 0.5rem;
}

.wall__tile--quote figcaption {
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--color-on-dark-tertiary);
}

.wall__tile--image {
  position: relative;
  padding: 0;
  justify-content: flex-end;
}

.wall__tile--image img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* A second, smaller photo moment — same image treatment as .wall__tile--image,
   but a single column wide so it reads as a quieter aside next to the Gift
   Handover tile rather than a matching pair. */
.wall__tile--compact {
  grid-column: span 1;
}

.wall__tile--image figcaption {
  position: relative;
  z-index: 1;
  padding: 1.25rem;
  background: linear-gradient(to top, rgba(36, 23, 18, 0.75), transparent);
  color: var(--jovi-paper);
  font-size: 0.82rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  width: 100%;
}

.wall__tile--stat {
  align-items: center;
  text-align: center;
  justify-content: center;
}

.wall__tile--stat strong {
  font-family: var(--font-display);
  font-size: 2.25rem;
  color: var(--jovi-maroon);
  display: block;
}

.wall__tile--stat span {
  font-size: 0.85rem;
  color: var(--color-on-dark-tertiary);
}

.wall__tile--caption {
  justify-content: center;
  text-align: center;
  font-size: 0.82rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--color-on-dark-tertiary);
}

.wall__tile--tag {
  justify-content: center;
  align-items: center;
  text-align: center;
  font-family: var(--font-display);
  font-style: italic;
  font-size: 1.15rem;
  color: var(--jovi-maroon);
}

/* At the 4-column desktop grid, the 7 tiles' spans leave the trust stat and
   tag as lone 1x1 cells — the auto-placement algorithm (still sparse, DOM
   order preserved throughout: no grid-auto-flow:dense, no explicit
   grid-row/column-start) then strands Personal Leather Moment, the final
   tile, alone in a fresh row, leaving a large empty trailing block. Widening
   the stat into a banner, letting the tag grow to match Candid Unboxing's
   height, and reshaping Personal into a low closing band lets the same 7
   tiles tile the grid with zero gaps — while keeping Personal visually the
   quietest of the three photos (a short band vs. Candid's tall portrait vs.
   Gift Handover's full hero block) and leaving Gift Handover, Candid
   Unboxing, and both quotes completely untouched.
   ========================================================================== */
@media (min-width: 961px) {
  .wall__tile--stat {
    grid-column: span 2;
  }

  .wall__tile--tag {
    grid-row: span 2;
  }

  .wall__tile--compact:last-of-type {
    grid-column: span 2;
    grid-row: span 1;
  }

  /* Personal Leather Moment's source photo is square; reshaped into a wide
     band, the default center crop pushes the hand and initials out of
     frame, so re-center lower to keep both in view. */
  .wall__tile--compact:last-of-type img {
    object-position: center 68%;
  }
}

/* 19. Visit & Close
   ========================================================================== */
.visit {
  background: var(--jovi-espresso);
  color: var(--jovi-paper);
}

/* Wall and Visit share the same dark background with no visual seam between
   them, so stacking a full section padding on both sides reads as one
   oversized empty block. Halve it on the Visit side, desktop only — mobile
   keeps its existing (correct) rhythm. */
@media (min-width: 961px) {
  .wall + .visit {
    padding-top: calc(var(--space-section) / 2);
  }
}

.visit__inner {
  max-width: 42rem;
  margin-inline: auto;
  text-align: center;
}

.visit h2 { color: var(--jovi-paper); }

.visit__intro p {
  margin-top: 1.25rem;
  color: var(--color-on-dark-soft);
  font-size: 1.05rem;
}

.visit__details {
  display: flex;
  justify-content: center;
  gap: clamp(2rem, 6vw, 4rem);
  margin-top: clamp(2.5rem, 5vw, 3.5rem);
  padding-top: clamp(2.5rem, 5vw, 3.5rem);
  border-top: 1px solid var(--color-line-on-dark);
}

.visit__details dt {
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--jovi-maroon);
  margin-bottom: 0.35rem;
}

.visit__details dd {
  margin: 0;
  font-weight: 600;
}

.visit__close {
  margin-top: clamp(3rem, 6vw, 4.5rem);
  padding-top: clamp(2.5rem, 5vw, 3.5rem);
  border-top: 1px solid var(--color-line-on-dark);
}

.visit__close h3 {
  color: var(--jovi-paper);
  margin-bottom: 1.5rem;
}

/* 20. Footer
   ========================================================================== */
.site-footer {
  background: var(--jovi-espresso);
  color: var(--color-on-dark-soft);
  padding-block: 3rem;
}

.site-footer__inner {
  display: grid;
  grid-template-columns: 1fr 2fr 1fr;
  gap: 2rem;
}

.site-footer__brand .logo a {
  color: var(--jovi-paper);
  font-size: 1.4rem;
}

.site-footer__brand p {
  margin-top: 0.5rem;
  font-size: 0.85rem;
}

.site-footer__links {
  display: flex;
  flex-wrap: wrap;
  gap: 0.85rem 1.35rem;
  font-size: 0.9rem;
}

.site-footer__links a:hover {
  color: var(--jovi-paper);
}

.site-footer__meta {
  font-size: 0.78rem;
  text-align: right;
}

.site-footer__meta a {
  text-decoration: underline;
  text-underline-offset: 2px;
}

/* 21. Reveal animation
   ========================================================================== */
.reveal {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity 0.6s var(--ease), transform 0.6s var(--ease);
}

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

@media (prefers-reduced-motion: reduce) {
  .reveal {
    opacity: 1;
    transform: none;
    transition: none;
  }

  .bag-annotate__row,
  .bag-annotate__marker-dot,
  .bag-annotate__marker-line {
    transition: none;
  }
}

/* 22. Responsive tweaks
   ========================================================================== */
@media (max-width: 1240px) and (min-width: 961px) {
  .opening__figure { left: 50%; }
  .opening__inner { max-width: 26rem; }
}

@media (max-width: 960px) {
  .primary-nav { display: none; }
  .menu-toggle { display: inline-flex; }

  .origin__layout {
    flex-direction: column;
    gap: clamp(1.5rem, 6vw, 2.5rem);
  }
  .origin__inner {
    max-width: none;
    padding-inline: clamp(1.25rem, 4vw, 3rem);
  }
  .origin__figure {
    order: -1;
    min-height: 0;
    aspect-ratio: 4 / 5;
  }
  .origin__figure img {
    object-position: 62% 42%;
  }

  .opening {
    min-height: auto;
    flex-direction: column;
    align-items: stretch;
  }
  .opening__inner {
    max-width: none;
    padding-block: clamp(2rem, 6vw, 3rem);
  }
  .opening__figure {
    position: static;
    aspect-ratio: 4 / 5;
    width: 100%;
  }
  .opening__figure::after {
    display: none;
  }

  .personalise__inner {
    grid-template-columns: 1fr;
  }
  .personalise__preview {
    margin-bottom: 1rem;
  }

  .edits {
    grid-template-columns: 1fr;
    gap: 2rem;
  }

  .product-card {
    flex-direction: column;
    align-items: stretch;
  }

  .product-card__frame {
    flex: none;
  }

  .product-card--hero .product-card__frame {
    flex: none;
  }

  .product-pair {
    grid-template-columns: 1fr;
    gap: 2.5rem;
  }

  .product-card--feature .product-card__frame {
    aspect-ratio: 4 / 5;
  }

  .bag-annotate__layout {
    grid-template-columns: 1fr;
  }
  .bag-annotate__markers { display: none; }

  .packaging__steps { grid-template-columns: repeat(2, 1fr); }

  .wall__board { grid-template-columns: repeat(2, 1fr); }
  .wall__tile--quote,
  .wall__tile--image { grid-column: span 2; }

  .visit__details { flex-direction: column; gap: 1.5rem; }

  .site-footer__inner { grid-template-columns: 1fr; text-align: left; }
  .site-footer__meta { text-align: left; }
}

/* Safety net: the mobile nav dialog is mobile-only. If a viewport resize
   crosses back to desktop while it's open (JS listens for this too, but a
   resize/matchMedia change isn't always observable — e.g. some automated
   viewport changes), this guarantees it can never sit stuck over the
   desktop layout. */
@media (min-width: 961px) {
  .mobile-menu.is-open {
    transform: translateX(100%);
    visibility: hidden;
  }
}

@media (max-width: 640px) {
  .banner-text-full { display: none; }
  .banner-text-short { display: inline; }

  .opening__figure { aspect-ratio: 4 / 5; }

  .material__figure {
    height: 62vh;
    min-height: 380px;
    /* Narrow crop needs its own framing: centered default pulls the stitching
       diagonal through the caption text. Shifting right keeps grain filling
       the dark negative space behind the text and the stitching as a clear
       accent above it, clear of the copy. */
    background-position: 60% center;
  }

  .packaging__steps { grid-template-columns: 1fr; }

  /* On a single column, the bag-contents list (What's in the Bag) and the
     ritual steps list sit back-to-back with near-identical numbered-list
     styling — extra room here reads them as separate chapters instead of
     one repeated pattern. */
  .packaging { margin-top: 1.5rem; }

  .wall__board { grid-template-columns: 1fr; grid-auto-rows: 220px; }
  .wall__tile--quote,
  .wall__tile--image { grid-column: span 1; }

  .gift-finder__progress { gap: 0.75rem; }
}

@media (min-width: 1600px) {
  .container { max-width: 1440px; }
}
