/* ===========================================================
   MANIMA — shared styles
   Fonts (all locally hosted from /media/):
     - Cormorant (italic + regular, variable weight 300–700) — headlines
       (italic used throughout; regular added for the cookie banner button)
     - Brother 1816 Book (+ Italic) — body copy, menu, UI sans
     - Garamond Premier Pro (kept available as fallback)
   =========================================================== */

@font-face {
  font-family: "Cormorant";
  font-style: italic;
  font-weight: 300 700;
  font-display: swap;
  src: url("media/Cormorant-Italic.ttf") format("truetype-variations"),
       url("media/Cormorant-Italic.ttf") format("truetype");
}
@font-face {
  font-family: "Cormorant";
  font-style: normal;
  font-weight: 300 700;
  font-display: swap;
  src: url("media/Cormorant-VariableFont_wght.ttf") format("truetype-variations"),
       url("media/Cormorant-VariableFont_wght.ttf") format("truetype");
}
@font-face {
  font-family: "Brother 1816";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("media/Brother1816-Book.ttf") format("truetype");
}
@font-face {
  font-family: "Brother 1816";
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url("media/Brother1816-BookItalic.ttf") format("truetype");
}
@font-face {
  font-family: "Garamond Premier Pro";
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url("media/GaramondPremierPro-Italic.otf") format("opentype");
}
@font-face {
  font-family: "Garamond Premier Pro";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("media/GaramondPremierPro-Regular.otf") format("opentype");
}

:root {
  --ink:        #111111;
  --ink-soft:   #2a2a2a;
  --paper:      #ffffff;
  --rule:       #e7e3dc;
  --muted:      #7a7367;
  /* Used to make body-copy text links stand out for visitors, instead of
     blending in at --muted grey. Started as the logo mark's red
     (rgb(238,51,67)), swapped to this gold per feedback — sampled from a
     reference swatch. Deliberately NOT applied to .world-subchip's
     white/light-grey links (see further down) — those already read
     clearly against their own colored card backgrounds. */
  --link:       #a98a2e;
  --link-hover: #8a7025;

  --nav-track:   0.32em;
  --logo-track:  0.55em;

  --serif: "Cormorant", "Garamond Premier Pro", "Garamond", "Times New Roman", serif;
  --sans:  "Brother 1816", -apple-system, BlinkMacSystemFont, "Helvetica Neue", Arial, sans-serif;

  --max-w: 1500px;
  --pad-x: 6vw;
}

* { box-sizing: border-box; }

/* One continuous scrolling page now — nav links jump to in-page anchors. */
html { scroll-behavior: smooth; }

/* Land just below the sticky header instead of tucking the section's top
   behind it. --header-h is kept in sync with the header's real height by
   the JS in index.html. */
#world,
#vision-film-intro,
#atelier-film-intro,
#trousseau,
#b2b,
#concierge,
#press {
  scroll-margin-top: var(--header-h, 156px);
}

html, body {
  margin: 0;
  padding: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  scroll-behavior: smooth;
}

img, video { display: block; max-width: 100%; height: auto; }

/* ---------- HEADER ---------- */
.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background: var(--paper);
  padding: 56px 0 18px;
}

/* ---------- BURGER (mobile only) ---------- */
.nav-toggle {
  display: none;
  position: absolute;
  top: 22px;
  right: 20px;
  width: 46px;
  height: 46px;
  background: none;
  border: 0;
  padding: 8px;
  cursor: pointer;
  z-index: 200;
}
.nav-toggle span {
  display: block;
  width: 30px;
  height: 2px;
  background: var(--ink);
  margin: 5px auto;
  transition: transform .3s ease, opacity .25s ease;
}
.nav-toggle[aria-expanded="true"] span:nth-child(1) {
  transform: translateY(7px) rotate(45deg);
}
.nav-toggle[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.nav-toggle[aria-expanded="true"] span:nth-child(3) {
  transform: translateY(-7px) rotate(-45deg);
}

.logo-wrap {
  display: flex;
  align-items: center;
  justify-content: center;
  user-select: none;
  text-decoration: none;
  color: var(--ink);
}

.logo-wrap img,
.logo-wrap svg {
  height: 60px;
  width: auto;
  display: block;
}

@media (max-width: 860px) {
  /* 30% smaller again (64/17vw/88 * 0.7). The header has no fixed height —
     just padding around the logo (see .site-header) — and --header-h is
     re-measured from the actual rendered height via JS (see
     "Keep the sticky header offset in sync" in index.html), so shrinking
     the logo alone is enough to pull the header shorter and everything
     below it (nav, hero, headline) up to match — nothing else needs a
     manual nudge to close the gap this leaves. */
  .logo-wrap img,
  .logo-wrap svg { height: clamp(45px, 11.9vw, 62px); }
}

.main-nav {
  margin-top: 38px;
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  align-items: center;
  justify-items: center;
  max-width: var(--max-w);
  padding: 0 var(--pad-x);
  margin-left: auto;
  margin-right: auto;
}

.main-nav a {
  font-family: var(--sans);
  /* Fixed 13px read fine at full desktop widths (~1440px+, where the row
     has plenty of room) but felt cramped into one dense run of text
     around iPad-Pro-width (~1024px) — same nav, same 7 items, but roughly
     30% less horizontal room for it (container width tracks viewport
     minus --pad-x's 6vw each side). Scaling the size down as the row
     narrows gives the words visible gaps again instead of shrinking that
     gap to fit; the letter-spacing below is in em so it scales down in
     step automatically, no separate adjustment needed there. Caps out at
     13px from ~1440px up (unchanged from before) and bottoms out at
     10.5px at the 860px mobile breakpoint (where this row disappears
     entirely in favour of the burger menu anyway). */
  font-size: clamp(10.5px, 6.8px + 0.43vw, 13px);
  font-weight: 400;
  letter-spacing: var(--nav-track);
  text-transform: uppercase;
  color: var(--ink);
  text-decoration: none;
  padding: 6px 4px;
  transition: opacity .2s ease;
  /* Without this, "PRESS ROOM" (the only two-word label) is the first to
     run out of room as the 7-column grid narrows — e.g. at iPad-Pro-width
     (~1024px, still above the 860px mobile breakpoint so the inline nav is
     still in play) it wraps onto two lines while every other one-word
     label stays on one, since a plain space is a valid line-break point
     and nothing else here was. Forcing every label to stay on one line
     keeps the row visually even; verified this doesn't overflow its
     column at that width since "PARTNERSHIPS" (longer, unbreakable
     already) already fits fine there. */
  white-space: nowrap;
}

.main-nav a:hover,
.main-nav a[aria-current="page"] { opacity: 0.5; }

/* ---------- LAYOUT ---------- */
.container {
  max-width: var(--max-w);
  margin: 0 auto;
  padding: 0 var(--pad-x);
}

section { padding: 80px 0; }

/* ---------- HERO ---------- */
.hero { padding-top: 30px; padding-bottom: 0; }

/* Stack the three home videos flush against each other —
   no vertical breathing room between hero + the two splits
   that carry video 2 and video 3. */
section.flush { padding-top: 0; padding-bottom: 0; }
section.flush-bottom { padding-bottom: 0; }

/* The three home video blocks share the same 900px grid as the
   portraits below. Hero video is centered; the two split sections
   are also centered, which makes their video (left column) line up
   with Carolina's photo on the left. */
.hero-media,
section.flush .split {
  max-width: 900px;
  margin-left: auto;
  margin-right: auto;
}

.hero-media {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  background: #ddd1bd;
}

.hero-media img,
.hero-media video {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.hero-headline {
  position: absolute;
  top: 8%;
  left: 0;
  right: 0;
  text-align: center;
  font-family: var(--serif);
  font-style: italic;
  font-weight: 400;
  /* Sized to keep "The Greatest Traditions Never Stand Still"
     on one line inside the 900px hero. */
  font-size: clamp(13px, 3.3vw, 38px);
  color: var(--ink);
  letter-spacing: 0.01em;
  padding: 0 4%;
  margin: 0;
  white-space: nowrap;
}

/* Light variant: white headline + subtle drop shadow for legibility
   when the hero video is darker / has motion behind the text. */
.hero-media--light .hero-headline {
  color: #ffffff;
  text-shadow: 0 1px 2px rgba(0,0,0,0.25), 0 0 16px rgba(0,0,0,0.18);
}

/* Trousseau rebuilt to reuse the exact same .world-film-section /
   .world-film-wrap / .world-film markup as the World/Vision/Mission
   videos (see index.html) instead of the old bespoke .hero-media +
   .hero-headline setup — that older pattern (fixed 900px cap fighting a
   %-based text column, several rounds of margin hacks for the scroll-
   anchor/sticky-header interaction) kept causing exactly the drift and
   bugs reported here. Reusing the proven shared component means no
   Trousseau-specific CSS is needed at all anymore: same 34px heading gap,
   same 5/7-aligned video (.world-film-section--aligned), same plain
   .text-block .prose below it. */

/* Concierge / Press headlines matched to the same size + top spacing as
   the other section headlines, instead of the much larger generic
   .page-intro h1 treatment. */
#b2b,
#concierge,
#press {
  padding-top: 8px;
}
#b2b h1,
#concierge h1,
#press h1 {
  font-size: clamp(24px, 4vw, 38px);
  line-height: 1.18;
  letter-spacing: 0.01em;
  white-space: normal;
  margin-top: -10px;
}

/* Two-line hero headline (Trousseau): explicit <br>, both lines
   stay non-wrapping; sits a touch lower so the second line breathes. */
.hero-headline--multi {
  white-space: nowrap;
  line-height: 1.18;
  top: 8%;
}

/* ---------- SPLIT SECTIONS ---------- */
.split {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.2fr);
  gap: clamp(40px, 6vw, 90px);
  align-items: center;
}

.split .media {
  aspect-ratio: 4 / 5;
  width: 100%;
  overflow: hidden;
  background: #e7e1d3;
}

.split .media img,
.split .media video {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.split.media-wide .media { aspect-ratio: 4 / 3; }

.split .copy h2 {
  font-family: var(--serif);
  font-style: italic;
  font-weight: 400;
  /* Split copy column is ~440px wide inside the 900px grid; cap the
     font size so "What We Inherit, We Transform" stays on one line. */
  font-size: clamp(15px, 2.1vw, 28px);
  margin: 0 0 22px;
  line-height: 1.15;
  white-space: nowrap;
}

.split .copy p {
  font-family: var(--sans);
  font-style: normal;
  font-weight: 400;
  font-size: clamp(14px, 1.05vw, 17px);
  line-height: 1.6;
  letter-spacing: 0.005em;
  color: var(--ink-soft);
  margin: 0 0 16px;
  max-width: 46ch;

  /* Blocksatz — wie bei der Creators-Prosa */
  text-align: justify;
  -webkit-text-align: justify;
  text-align-last: left;
  text-justify: inter-word;
  hyphens: auto;
  -webkit-hyphens: auto;
  -ms-hyphens: auto;
}

/* ---------- PORTRAITS ---------- */
.portraits-section { padding-top: 40px; padding-bottom: 24px; }

.portraits-title {
  text-align: center;
  font-family: var(--serif);
  font-style: italic;
  font-weight: 400;
  /* Same scale as the split headlines (What We Inherit / Ancient Patterns) */
  font-size: clamp(15px, 2.1vw, 28px);
  margin: 0 0 22px;
  white-space: nowrap;
}

.portraits {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0;
  max-width: 900px;
  margin: 0 auto;
}

.portraits .portrait {
  aspect-ratio: 5 / 6;
  overflow: hidden;
  background: #efe6d4;
  margin: 0;
}

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

/* Composition of the source photos: Carolina sits on the left of
   her frame (facing right), Piero sits on the right of his frame
   (facing left). Anchor the crops accordingly so the faces are
   preserved and the two figures appear to face each other. */
.portraits .portrait:first-child img { object-position: 35% center; }
.portraits .portrait:last-child  img { object-position: 65% center; }

/* ---------- TEXT BLOCK ---------- */
.text-block { padding: 24px 0 120px; text-align: center; }

/* When a text-block directly follows the prose text-block,
   pull it up so the headline sits close to the paragraph above —
   and tighten the gap below it as well. */
.text-block.flush-top { padding-top: 0; padding-bottom: 0; margin-top: -80px; }
.text-block.flush-top h2 { margin-bottom: 12px; }

.text-block h2 {
  font-family: var(--serif);
  font-style: italic;
  font-weight: 400;
  /* Same scale as split + portraits titles */
  font-size: clamp(15px, 2.1vw, 28px);
  margin: 0 0 22px;
  white-space: nowrap;
}

/* Matched to the same 75% width already used for the World/Vision/Atelier
   videos and the founders grid, instead of a fixed 720px cap — one
   consistent content column width across the whole desktop layout. */
.text-block .prose {
  max-width: 75%;
  margin: 0 auto;
  padding: 0 24px;            /* visible side inset on narrow screens */
  text-align: justify;        /* on parent for older browsers */
}

.text-block .prose p {
  font-family: var(--sans);
  font-style: normal;
  font-weight: 400;
  font-size: clamp(14px, 1.05vw, 17px);
  line-height: 1.7;
  letter-spacing: 0.005em;
  color: var(--ink-soft);
  margin: 0 0 18px;

  /* Blocksatz — beide Kanten bündig */
  text-align: justify;
  -webkit-text-align: justify;
  text-align-last: left;
  text-justify: inter-word;

  hyphens: auto;
  -webkit-hyphens: auto;
  -ms-hyphens: auto;
}

/* ---------- PAGE INTRO (subpages) ---------- */
.page-intro {
  text-align: center;
  padding: 80px 0 40px;
}
.page-intro h1 {
  font-family: var(--serif);
  font-style: italic;
  font-weight: 400;
  font-size: clamp(28px, 4.5vw, 64px);
  margin: 0 0 18px;
  white-space: nowrap;
}

/* For pages whose H1 carries an explicit two-line composition
   (e.g. Trousseau: "The MANIMA Trousseau." / "Crafted for…").
   Desktop max matches the home hero (38px); mobile minimum
   is bumped up so the title remains a true page headline. */
.page-intro h1.multi-line {
  white-space: nowrap;        /* line break comes from <br>, not wrapping */
  line-height: 1.18;
  font-size: clamp(24px, 4vw, 38px);
  letter-spacing: 0.01em;
}
.page-intro p {
  font-family: var(--sans);
  font-style: normal;
  font-weight: 400;
  font-size: clamp(14px, 1.1vw, 18px);
  letter-spacing: 0.005em;
  color: var(--ink-soft);
  max-width: 600px;
  margin: 0 auto;
  line-height: 1.65;
}

/* ---------- COLLECTION CAROUSEL ---------- */
.collection {
  padding: 0 0 60px;
  margin-top: -8px;
}

.collection-title {
  font-family: var(--sans);
  font-weight: 400;
  font-style: normal;
  font-size: clamp(11px, 0.95vw, 13px);
  letter-spacing: 0.42em;
  text-transform: uppercase;
  color: var(--ink);
  text-align: center;
  margin: 0 0 22px;
}

.carousel {
  position: relative;
  width: 100%;
  max-width: 720px !important;   /* match the prose column width */
  margin-left: auto !important;
  margin-right: auto !important;
  overflow: hidden;
  background: #f3eee5;
}

.carousel-track {
  display: flex;
  transition: transform .55s cubic-bezier(.22,.7,.25,1);
  will-change: transform;
}

.carousel-slide {
  flex: 0 0 100%;
  margin: 0;
  aspect-ratio: 16 / 9;
  background: #f3eee5;
  overflow: hidden;
}

.carousel-slide img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  user-select: none;
  -webkit-user-drag: none;
}

/* Click zones — left half = prev, right half = next */
.carousel-zone {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 50%;
  background: transparent;
  border: 0;
  cursor: pointer;
  padding: 0;
  z-index: 2;
}
.carousel-zone--prev { left: 0; cursor: w-resize; }
.carousel-zone--next { right: 0; cursor: e-resize; }
.carousel-zone:disabled { cursor: default; opacity: 0; pointer-events: none; }

/* Arrow indicators on hover (desktop) */
.carousel-arrow {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 44px;
  height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
  opacity: 0;
  transition: opacity .25s ease;
  color: #fff;
  text-shadow: 0 1px 4px rgba(0,0,0,0.5);
  font-family: var(--serif);
  font-style: italic;
  font-size: 36px;
  line-height: 1;
  z-index: 3;
}
.carousel-arrow--prev { left: 18px; }
.carousel-arrow--next { right: 18px; }
.carousel:hover .carousel-arrow { opacity: 0.92; }
.carousel-zone--prev:disabled ~ .carousel-arrow--prev,
.carousel-zone--next:disabled ~ .carousel-arrow--next { opacity: 0 !important; }

/* Dots indicator */
.carousel-dots {
  display: flex;
  justify-content: center;
  gap: 10px;
  margin-top: 18px;
}
.carousel-dots button {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  border: 0;
  padding: 0;
  background: #cdc4b3;
  cursor: pointer;
  transition: background .25s ease, transform .25s ease;
}
.carousel-dots button.is-active {
  background: var(--ink);
  transform: scale(1.15);
}

/* On mobile, no hover; arrows hidden, click zones still work; swipe primary */
@media (max-width: 860px) {
  .carousel-arrow { display: none; }
  .carousel-zone { cursor: default; }
  .collection { padding: 0 0 50px; margin-top: 0; }
  .collection-title { font-size: 11px; letter-spacing: 0.35em; margin-bottom: 16px; }
}

/* ---------- FOOTER ---------- */
/* Five legal/contact columns (entity+address, directors, registration,
   copyright, contact) — same quiet uppercase-label + regular-case-content
   pairing used for micro-copy elsewhere on the page (e.g. the chip
   headlines), just laid out as a row of columns instead of a single
   centred line. */
.site-footer {
  border-top: 1px solid var(--rule);
  padding: 60px 0 0;
  font-family: var(--sans);
  color: var(--ink);
}

/* Bottom rule mirrors the border-top above: same 1px/var(--rule) line,
   same full-bleed width (a plain div, not wrapped in .container, so it
   spans edge-to-edge exactly like the border-top does), same 60px gap
   down to .footer-columns as the top rule has up to it. Lives after
   .footer-columns in normal document flow (not fixed/absolute) so it —
   and the credit block below it — naturally moves down whenever a
   footer column's accordion opens and grows the row's height. */
.footer-bottom-rule {
  height: 1px;
  background: var(--rule);
  margin-top: 60px;
}

.footer-credit {
  text-align: center;
  padding: 24px 0 40px;
}
.footer-credit-label {
  font-family: var(--sans);
  font-size: 11px;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--muted);
  line-height: 1.6;
  margin: 0 0 6px;
}
/* Single line on desktop (all three parts, bullet-separated); two lines on
   mobile, breaking before "Content Production" — same swap-by-breakpoint
   approach as elsewhere on the site, rather than relying on the text to
   wrap naturally (at 11px/0.15em letter-spacing the three-part line would
   wrap at an arbitrary word, not the intended point). */
.footer-credit-label-mobile { display: none; }
@media (max-width: 860px) {
  .footer-credit-label-desktop { display: none; }
  .footer-credit-label-mobile { display: inline; }
}
/* Logo kept deliberately small/quiet (14px tall — well under the 24.8px
   leaf marks used in the section dividers) and slightly translucent, so
   it reads as a discreet credit rather than a second brand mark
   competing with MANIMA's own logo in the header. */
.footer-credit-logo-link {
  display: inline-block;
  line-height: 0;
}
.footer-credit-logo {
  height: 8.624px;
  width: auto;
  opacity: 0.5;
  transition: opacity 0.2s ease;
}
.footer-credit-logo-link:hover .footer-credit-logo { opacity: 0.85; }

.footer-columns {
  display: grid;
  grid-template-columns: repeat(8, 1fr);
  gap: clamp(16px, 2vw, 32px);
  text-align: left;
}

/* Column title is a <button> acting as an accordion toggle — reset to
   look like the plain text label it replaced (no border, no background,
   no underline), just with a pointer cursor and an open/closed state. */
.footer-col-title {
  display: block;
  width: 100%;
  text-align: inherit;
  font: inherit;
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  font-family: var(--sans);
  font-size: 11px;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--muted);
  text-decoration: none;
  margin-bottom: 0;
  transition: color 0.2s ease;
}
.footer-col-title:hover,
.footer-col.is-open .footer-col-title { color: var(--ink); }

/* Collapsed by default; expands downward on click via the 0fr->1fr
   grid-template-rows trick (animates to content's natural height without
   needing JS to measure it), then collapses back the same way. */
.footer-col-content {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 0.3s ease;
}
.footer-col-content-inner { overflow: hidden; }
.footer-col.is-open .footer-col-content {
  grid-template-rows: 1fr;
  margin-top: 12px;
}

.footer-col p {
  margin: 0;
  font-size: 13px;
  line-height: 1.7;
  color: var(--ink);
}
.footer-col p + p { margin-top: 10px; }

.footer-col a {
  color: inherit;
  text-decoration: none;
  border-bottom: 1px solid var(--rule);
  transition: border-color 0.2s ease;
}
.footer-col a:hover { border-color: var(--ink); }

@media (max-width: 860px) {
  .footer-columns {
    grid-template-columns: 1fr;
    gap: 32px;
    text-align: center;
  }

  /* Privacy/Cookie/Accessibility bodies are proper multi-sentence prose
     (unlike the short address/name lines in the other columns), so on
     mobile they get the exact same treatment as the rest of the site's
     flowing text (see .text-block .prose / .text-block .prose p): not
     just the Blocksatz justification, but also that block's own extra
     24px side inset on top of the .container gutter — without it, these
     three columns sit visibly closer to the screen edges than every
     other mobile text block on the page. The inset goes on the content
     wrapper only (not the title button), matching how .text-block
     .prose's padding never touches the heading sitting outside it. */
  .footer-col--policy p {
    text-align: justify;
    -webkit-text-align: justify;
    text-align-last: left;
    text-justify: inter-word;
    hyphens: auto;
    -webkit-hyphens: auto;
    -ms-hyphens: auto;
  }
  .footer-col--policy .footer-col-content-inner {
    padding: 0 24px;
  }
}

/* ---------- COOKIE BANNER ---------- */
/* Fixed to the bottom of the viewport, hidden (translated off-screen) until
   JS adds .is-visible once it has checked localStorage — see the script
   block near the end of index.html. z-index 500 is deliberately above
   everything else on the page (the burger button, the highest other
   value in this file, sits at 200) since this can appear over any other
   section, including the sticky header, on first visit. */
.cookie-banner {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 500;
  background: #F4F1EC;
  border-top: 1px solid var(--rule);
  transform: translateY(100%);
  transition: transform 0.4s ease;
}
.cookie-banner.is-visible {
  transform: translateY(0);
}
.cookie-banner-inner {
  max-width: var(--max-w);
  margin: 0 auto;
  padding: 18px var(--pad-x);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 32px;
}
.cookie-banner-text {
  margin: 0;
  font-family: var(--sans);
  font-size: clamp(13px, 0.95vw, 15px);
  line-height: 1.6;
  color: var(--ink-soft);
}
/* Reuses the site's standard muted/no-underline text-link treatment —
   .world-inline-link only carries color/underline styling when explicitly
   opted in per container (see the allowlist further down this file), so
   .cookie-banner is added there rather than left to fall back to the
   browser default blue/underlined link. */
.cookie-banner-ok {
  flex: 0 0 auto;
  background: var(--ink);
  color: #fff;
  border: none;
  cursor: pointer;
  font-family: var(--serif);
  font-style: normal;
  font-weight: 500;
  font-size: 16px;
  letter-spacing: 0.04em;
  padding: 11px 34px;
  transition: opacity 0.2s ease;
}
.cookie-banner-ok:hover { opacity: 0.85; }

@media (max-width: 860px) {
  .cookie-banner-inner {
    flex-direction: column;
    align-items: stretch;
    gap: 16px;
    padding: 18px 24px;
  }
  .cookie-banner-ok {
    width: 100%;
    padding: 12px 0;
  }
}

/* ---------- WORLD EXPLORER (drill-down: Worlds → Objects → Detail) ---------- */
.world-explorer { padding-top: 8px; padding-bottom: 40px; }

/* The Cormorant italic headline's own line-height adds a chunk of invisible
   whitespace above its cap-height, which made the menu→headline gap look
   much bigger than the headline→slideshow gap even though the box-model
   margins matched. Nudge just the heading up (not the whole section — that
   overlapped the sticky header and clipped the text) to eat into that
   whitespace without touching the actual menu/header gap. */
#world .world-mid-heading { margin-top: -10px; }

/* Same nudge for the Our Vision / Our Atelier intro headlines — same font,
   same optical whitespace issue, same fix. Kept small and heading-only,
   same reasoning as #world .world-mid-heading above: these sections'
   scroll-margin-top anchors position the SECTION at header-height from
   the viewport top, so anything past about -8px here (padding-top's own
   value) pushes the heading up behind the sticky header on an anchor
   jump — confirmed the hard way. The bigger "too much gap above" fix
   lives on the *preceding* section's padding instead (see .world-film-section
   :has(+ #vision-film-intro) etc. below), which doesn't touch this
   section's own box or its scroll anchor at all. */
#vision-film-intro .world-intro-heading,
#atelier-film-intro .world-intro-heading,
#trousseau .world-intro-heading,
#b2b .world-intro-heading,
#concierge .world-intro-heading,
#press .world-intro-heading { margin-top: -10px; }

/* Closing the lopsided gap-above-heading (see screenshots) from the other
   side: reduce bottom padding on just the specific preceding section
   instance before each of these three headings, via :has() so the shared
   .world-film-section / .founders-section classes elsewhere on the page
   (e.g. before the Visionaries heading, which wasn't flagged) keep their
   normal 100px. This is safe for scroll-anchoring — it only shortens the
   page above the target section, it doesn't touch the target section's
   own box or its heading's position within it.
   Updated to reach through the .section-divider ornament now sitting
   between these sections (:has() supports a full relative selector, not
   just an immediate "+"), otherwise it stopped matching the moment the
   divider markup was inserted and silently fell back to the default
   100px — which is exactly the "too much headroom" regression reported.
   Also extended to the transitions that never had this fix at all
   (Trousseau video → Concierge, Concierge photo → Press) so every
   main-nav boundary now uses the exact same, already-proven 30px gap. */
.world-film-section:has(+ .section-divider + #vision-film-intro),
.world-film-section:has(+ .section-divider + #atelier-film-intro),
.world-film-section:has(+ .section-divider + #trousseau),
.world-film-section:has(+ .section-divider + #b2b),
.world-film-section:has(+ .section-divider + #concierge) {
  padding-bottom: 30px;
}

/* Concierge's silent looping video (no heading, no transcript) sitting
   right before Press Room — split out from the shared 30px group above,
   same reasoning as the World/Mission/Vision transcript fix further down:
   the gap from the video's own bottom edge to the divider's top line
   should equal the 53.8px the divider's own two lines sit apart by, not
   the smaller 30px used for the heading-optical-whitespace transitions.
   Measured live rather than eyeballed (see .world-film-section:has(.film-
   transcript) below for the same approach). */
.world-film-section:has(+ .section-divider + #press) {
  padding-bottom: 53.8px;
}

/* Trousseau's layout is now headline -> video -> flowing text -> slideshow.
   The video's own tight join above (to the headline) comes for free from
   .world-film-section's base padding-top: 0.
   Its bottom padding is set here so the *visible* gap from the video down
   to the first line of text matches the *visible* gap from the last line
   of text down to the slideshow. That second gap is NOT just "copy's 8px
   bottom padding" (measured on the live page: it's 66px), because the
   collapsed .enquiry-accordion trigger sits inside #trousseau-copy, after
   the last paragraph, adding its own height/margin before the section's
   own padding-bottom even starts — a plain padding-number comparison
   between the two sides misses that. 58px + #trousseau-copy's own
   default 8px top padding (.world-explorer) = the same 66px on this
   side too. Verified with a headless-browser measurement, not just the
   CSS box-model on paper. */
#trousseau-video {
  padding-bottom: 58px;
}

/* Slideshow now sits last, directly before the B2B divider — same 30px
   pre-divider amount used sitewide for this exact transition (see the
   .world-film-section:has(+ .section-divider + #b2b) rule above), just
   set directly since this is a single unique instance, not a shared
   class. Top join to the flowing text above stays 0 (unchanged). */
.trousseau-slideshow {
  padding-top: 0;
  padding-bottom: 30px;
}

/* Slideshow width locked to the exact same grid as the video window below
   it (.world-film-section--aligned .world-film-wrap: 5/7 of the container
   on desktop, full-width on mobile) instead of the .carousel component's
   own default 720px prose-width cap — so the two "windows" line up
   edge-to-edge on both breakpoints. */
.trousseau-slideshow .carousel {
  width: calc(100% / 7 * 5);
  max-width: none !important;
}
@media (max-width: 860px) {
  .trousseau-slideshow .carousel {
    width: 100%;
  }
}

/* Main headline sitting above the whole section — same Cormorant italic
   treatment/size as the other page headlines (.page-intro h1.multi-line),
   since the phrase is too long to force onto one line like the shorter
   page titles (Concierge, Press Room, …). */
.world-intro-heading {
  text-align: center;
  font-family: var(--serif);
  font-style: italic;
  font-weight: 400;
  font-size: clamp(24px, 4vw, 38px);
  line-height: 1.18;
  letter-spacing: 0.01em;
  margin: 0 0 18px;
}

/* "The MANIMA World" now sits centred between the intro text and the
   slideshow/drill-down split (not left-aligned inside the drill-down
   column anymore). */
.world-mid-heading { margin-bottom: 26px; }

/* Intro copy block (headline + prose) — reused wherever a page needs the
   same tight-spaced intro treatment as "Our World" (not just #world).
   Reuses the .text-block prose typography, but with its own (much
   tighter) spacing so it doesn't add the generic .text-block's 120px
   bottom padding. */
.world-intro { padding: 0 0 20px; text-align: center; }

/* On pages where a film sits directly under this intro text with nothing
   in between (Atelier, Vision, …), pull both paddings in so the two
   sections read as one continuous block instead of two separately-spaced
   ones. */
#atelier-film-intro,
#vision-film-intro,
#trousseau,
#trousseau-copy,
#b2b,
#concierge,
#press { padding-bottom: 8px; }
#atelier-film-intro .world-intro,
#vision-film-intro .world-intro,
#trousseau .world-intro,
#trousseau-copy .world-intro,
#b2b .world-intro,
#concierge .world-intro,
#press .world-intro { padding-bottom: 0; }

.world-split {
  align-items: flex-start;
  /* Equal columns + no gutter: the seam sits exactly at the horizontal
     centre of the .container, which — since the header logo is centred
     on the full page — is also the logo's centre line. */
  grid-template-columns: 1fr 1fr;
  gap: 0;
}

.world-media {
  grid-column: 1;
  grid-row: 1;
  position: sticky;
  /* Set from JS to the header's true measured height, so it can never be
     out of sync with reality (a guessed pixel value kept being wrong). */
  top: var(--header-h, 156px);
  aspect-ratio: 4 / 5;
  min-height: 480px;
  z-index: 1;
}

/* -------- QUICK HARD TEST: wide slideshow + swipeable chip overlay --------
   Rough, direct prototype (not the final rebuild) to see the horizontal-
   scroll concept live before redesigning everything properly. Spans both
   grid columns; the drill-down copy/background box are hidden underneath
   it for the duration of this test. */
.world-media--wide-test {
  grid-column: 1 / -1;
  height: auto;
  min-height: 0;
}
/* #world scoping beats .split .media's aspect-ratio:4/5 (2 classes) —
   without it, that rule silently won and kept the box portrait-shaped,
   which is why the mosaic cells looked stretched instead of square.
   Locked to exactly 7:3 so the 7x3 grid always tiles into perfect
   squares edge-to-edge, at any viewport width. */
#world .world-media--wide-test { aspect-ratio: 7 / 3; }

/* 7x3 mosaic — replaces the single-image crossfade slideshow. Each cell
   independently crossfades between images/colours from a shared pool, on
   its own randomised timer, so changes ripple across the grid instead of
   happening all at once. */
.world-mosaic {
  position: absolute;
  inset: 0;
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  grid-template-rows: repeat(3, 1fr);
}
.mosaic-cell {
  position: relative;
  overflow: hidden;
}
.mosaic-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  /* Supersoft crossfade, never a hard cut. Duration is deliberately shorter
     than the JS scheduling delay (see index.html) so a fade always finishes
     before the next one starts on that cell — otherwise the interrupted
     transition would look like a jump/snap. */
  transition: opacity 1.4s ease-in-out;
}
.mosaic-img.is-active { opacity: 1; }
.world-split--wide-test .world-copy-bg,
.world-split--wide-test .world-copy {
  display: none;
}

.world-chip-row-test {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: flex-start;
  /* Widened from 63px so the Living sub-chip's 130% "pop" scale (see
     .world-chip-visual .world-subchip below) has clear room either side
     without brushing its neighbours. */
  gap: 74px;
  /* Now that there are several chips, real horizontal swipe/scroll — snaps
     one chip at a time, scrollbar hidden so it reads as a swipe gesture
     rather than a normal scrollbar. */
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  padding: clamp(60px, 8vw, 100px);
}
.world-chip-row-test::-webkit-scrollbar { display: none; }
.world-chip-row-test.is-hidden { display: none; }

/* ---- Fabric swatch tag chip (concept 2) ----
   An opaque little card instead of a translucent overlay fighting the
   moving mosaic behind it — reads like a woven clothing label / fabric
   sample: dashed "stitched" border around the swatch, tracked-out caps
   name below, a torn/deckle edge along the bottom of the whole card. */
.world-chip-test {
  position: relative;
  flex: 0 0 auto;
  /* Another 5% larger (265px/63.9vw → 278px/67.1vw). Gap between chips
     (.world-chip-row-test gap, now 74px) is a separate, untouched property —
     widening the chips doesn't shrink it. */
  width: min(278px, 67.1vw);
  display: flex;
  flex-direction: column;
  /* No card-wide background — the swatch's own tint needs the mosaic
     behind it to actually read as transparent, not just blend into an
     opaque paper card. */
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  font: inherit;
  scroll-snap-align: center;
}

.world-chip-swatch {
  position: relative;
  margin: 14px 14px 0;
  aspect-ratio: 4 / 3;
  border: 2px dashed rgba(17, 17, 17, 0.32);
  overflow: hidden;
  background: rgba(239, 232, 213, 0.72);
  display: flex;
  align-items: center;
  justify-content: center;
}
/* Test-only comparison variant: just the raw PNG, no background, no
   border, no frame of any kind — nothing behind it at all. The PNG
   itself now carries an opaque white headline strip across its own top
   (see chip-test-04.png), on a square 1:1 canvas sized so the longest
   category name fits it on one line — so no inset margin/padding here,
   the artwork is meant to bleed to the card's edges. */
.world-chip-swatch--solid {
  margin: 0;
  aspect-ratio: 1 / 1;
  background: none;
  border: none;
  /* Subtle lift off the mosaic behind it — soft, no hard edge. Nudged a
     touch stronger than the first pass. */
  box-shadow: 0 12px 28px rgba(17, 17, 17, 0.16);
}
/* The <picture> wrapper (used for the mobile thin-line chip artwork swap)
   shouldn't introduce its own box — treat it as if the img were a direct
   child, exactly as before. */
.world-chip-swatch picture {
  display: contents;
}
.world-chip-swatch img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  padding: 14%;
}
.world-chip-swatch--solid img {
  padding: 0;
}

/* Headline sits inside the PNG's own opaque white strip — measured at
   the top 22.3% of the square canvas (0 to 932px of 4176px tall). */
.world-chip-headline-test {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 22.3%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--sans);
  /* Nudged a touch smaller than .world-chip-label so the longest name
     (Hand Embroidered Venturing) stops crowding the swatch edges.
     Minimal bump again — the larger chip already gives enough extra room
     that letter-spacing didn't need to move this time. */
  font-size: 11.5px;
  letter-spacing: 0.12em;
  white-space: nowrap;
  overflow: hidden;
  text-transform: uppercase;
  color: var(--ink);
  text-align: center;
  padding: 0 4%;
  /* Optical nudge — flex-centering the line-box left it sitting a
     couple of px too high inside the white strip. */
  transform: translateY(3px);
}
/* Venturing has no real photography yet — a placeholder question mark
   stands in rather than forcing a photo that doesn't exist. */
.world-chip-swatch--placeholder {
  font-family: var(--serif);
  font-style: italic;
  font-size: clamp(34px, 5vw, 52px);
  color: rgba(17, 17, 17, 0.32);
}

/* Sub-chip test (Living only): clicking the main chip swaps its face for
   this card in the exact same slot in the row, rather than navigating to
   the drill-down screen. .world-chip-visual is an in-flow wrapper that
   holds the aspect-ratio (so the button's own height doesn't jump), and
   the swatch/subchip are both absolutely stacked inside it so they can
   crossfade with a gentle scale-up instead of an instant display swap —
   .is-subchip-active (toggled in JS) drives which one is visible. */
.world-chip-visual {
  position: relative;
  width: 100%;
  aspect-ratio: 1 / 1;
}
.world-chip-visual .world-chip-swatch,
.world-chip-visual .world-subchip {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  transform-origin: center center;
  /* Opacity and transform now run on separate timings: opacity settles
     relatively quickly (.5s) so the card doesn't look hazy for long, while
     the scale keeps gently drifting into place for .85s after — that
     "solid, then settles" split reads as much smoother than animating
     both in lockstep, especially over this much scale distance. */
  transition: opacity .5s cubic-bezier(.22, 1, .36, 1), transform .85s cubic-bezier(.22, 1, .36, 1);
  will-change: opacity, transform;
}
.world-chip-visual .world-chip-swatch {
  opacity: 1;
  transform: scale(1);
  z-index: 1;
}
.world-chip-test.is-subchip-active .world-chip-visual .world-chip-swatch {
  opacity: 0;
  transform: scale(0.92);
  pointer-events: none;
}
.world-chip-visual .world-subchip {
  opacity: 0;
  transform: scale(0.86);
  pointer-events: none;
  z-index: 1;
  /* Redesigned art (v2) is a plain square, same canvas as the main chips —
     solid box throughout, with only a small decorative icon cut-out near
     the top (roughly 8%–26% of the height, centered). */
  box-shadow: 0 12px 28px rgba(17, 17, 17, 0.16);
}
.world-chip-test.is-subchip-active .world-chip-visual .world-subchip {
  opacity: 1;
  /* Noticeably larger than 100% on reveal — a clear "pop" that makes the
     swap unmistakable rather than just a plain crossfade. */
  transform: scale(1.4);
  pointer-events: auto;
  z-index: 2;
}
.world-subchip-art {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  pointer-events: none;
  transition: opacity .3s ease;
}
/* While a form overlay is open on top of this card (JS adds
   .has-overlay-open, see index.html), the card's own art/text fade out
   underneath so only the translucent form shows — not both stacked. */
.world-subchip.has-overlay-open .world-subchip-art,
.world-subchip.has-overlay-open .world-subchip-text {
  opacity: 0;
}
.world-subchip-text {
  position: absolute;
  left: 0;
  right: 0;
  /* Icon cut-out ends by ~26% of the height. Since the Cormorant headline
     was dropped, the two copy paragraphs no longer need to start flush
     against the cut-out — there's spare room below, so a bit more air
     between "window" and text reads better than a cramped top edge. */
  top: 36%;
  bottom: 0;
  transition: opacity .3s ease;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  justify-content: flex-start;
  gap: 8px;
  padding: 0 11% 4%;
  overflow: hidden;
}
.world-subchip-copy {
  font-family: var(--sans);
  font-size: 10px;
  line-height: 1.35;
  letter-spacing: 0.005em;
  color: var(--ink-soft);
  text-align: justify;
}
.world-subchip .world-inline-link,
.world-subchip .world-inline-link:visited {
  color: #fff;
  text-decoration: none;
  cursor: pointer;
}
.world-subchip .world-inline-link:hover {
  color: rgba(255, 255, 255, 0.7);
}

/* Dining's subchip body copy in white (rest keep the default var(--ink-soft)),
   and its inline links in light grey instead of the default white — this
   card's own artwork reads better with that combination. */
.world-chip-test[data-goto="dining"] .world-subchip-copy {
  color: #fff;
}
.world-chip-test[data-goto="dining"] .world-subchip .world-inline-link,
.world-chip-test[data-goto="dining"] .world-subchip .world-inline-link:visited {
  color: #ccc;
}
.world-chip-test[data-goto="dining"] .world-subchip .world-inline-link:hover {
  color: #fff;
}

/* Bathing keeps the default (dark) body-copy colour, so its links need a
   darker grey than Dining's #ccc to still read against this card's
   artwork — but still clearly lighter than the near-black body copy
   (var(--ink-soft) #2a2a2a) so the link remains visibly distinct from the
   surrounding text. */
.world-chip-test[data-goto="bathing"] .world-subchip .world-inline-link,
.world-chip-test[data-goto="bathing"] .world-subchip .world-inline-link:visited {
  color: #888;
}
.world-chip-test[data-goto="bathing"] .world-subchip .world-inline-link:hover {
  color: #555;
}
@media (max-width: 860px) {
  /* Mobile box is min(360px,82vw) — noticeably wider/taller than the
     fixed 278px desktop box, so more headroom is available. But the
     narrowest phones (e.g. 375px wide → 82vw ≈ 307px box) are tighter
     than that, so these scale with vw rather than jumping straight to
     the sizes the widest phones could support. */
  .world-subchip-copy { font-size: clamp(7.7px, 2vw, 9.1px); }
  .world-subchip-text { top: 35%; gap: 6px; }
  /* Back down to 120% on mobile — 140% (desktop) got tight against the
     vertical carousel's neighbouring chips at narrower phone widths. */
  .world-chip-test.is-subchip-active .world-chip-visual .world-subchip {
    transform: scale(1.2);
  }
}

.world-chip-label {
  display: block;
  font-family: var(--sans);
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  text-align: center;
  color: var(--ink);
  padding: 14px 10px 24px;
  /* The swatch above is a genuine window onto the mosaic now, so the
     label needs its own solid backing to stay legible. */
  background: var(--paper);
  box-shadow: 0 10px 26px rgba(0, 0, 0, 0.18);
  position: relative;
  z-index: 1;
}

/* Torn/deckle fabric-sample edge along the bottom of the card. */
.world-chip-test::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -9px;
  height: 18px;
  background:
    linear-gradient(135deg, var(--paper) 50%, transparent 50%),
    linear-gradient(225deg, var(--paper) 50%, transparent 50%);
  background-size: 18px 18px;
  background-position: bottom left;
  background-repeat: repeat-x;
}
/* This test chip uses the new white-strip-headline template, not the
   fabric-swatch-tag look — no torn/deckle edge under it. */
.world-chip-test--plain::after {
  content: none;
}

/* Plain child of .world-media, same technique as .world-slide (position:
   absolute; inset:0) so it always covers the slideshow's box exactly,
   without needing to duplicate its sticky/aspect-ratio sizing separately. */
.world-media-overlay {
  position: absolute;
  inset: 0;
  z-index: 3;
  display: none;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  gap: clamp(16px, 2vw, 24px);
  background: rgba(17, 17, 17, 0.55);
  text-align: center;
  padding: 24px;
  overflow-y: auto;
}
.world-media-overlay.is-active { display: flex; }

.world-media-overlay-inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  /* Icon removed — the headline is the lead element now, so a slightly
     bigger gap reads as deliberately centered rather than cramped. */
  gap: clamp(12px, 1.4vw, 18px);
  max-width: 100%;
}
.world-media-overlay-inner p {
  font-family: var(--sans);
  font-size: clamp(14px, 1.05vw, 16px);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: #fff;
  line-height: 1.6;
  margin: 0;
}

.world-download-form {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 10px;
  width: min(240px, 80vw);
  margin-top: 6px;
}
.world-download-form input,
.world-download-form textarea {
  font-family: var(--sans);
  font-size: 13px;
  padding: 10px 12px;
  border: 1px solid rgba(255,255,255,0.4);
  background: rgba(255,255,255,0.08);
  color: #fff;
  border-radius: 2px;
  resize: none;
}
.world-download-form input::placeholder,
.world-download-form textarea::placeholder { color: rgba(255,255,255,0.65); }
.world-download-form input:focus,
.world-download-form textarea:focus {
  outline: none;
  border-color: #fff;
}
.world-download-form button[type="submit"] {
  font-family: var(--sans);
  font-size: 12px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  padding: 11px 12px;
  border: 1px solid #fff;
  background: none;
  color: #fff;
  cursor: pointer;
  transition: background .2s ease, color .2s ease;
}
.world-download-form button[type="submit"]:hover { background: #fff; color: #111; }

.world-download-sent {
  display: none;
  font-family: var(--sans);
  font-size: 12px;
  letter-spacing: 0.08em;
  color: #fff;
  text-align: center;
  margin: 0;
}
.world-download-form.is-sent input,
.world-download-form.is-sent button[type="submit"] { display: none; }

/* Once a submission is confirmed, the overlay's own "Download The X"
   headline is redundant (and reads as if the download is still pending)
   — hide it so only the confirmation message remains. */
.world-media-overlay-inner.is-sent .world-overlay-title { display: none; }
.world-download-form.is-sent .world-download-sent { display: block; }

/* Real download progress (see the fetch-based download in the world media
   overlay script) — shown in place of the inputs/submit button while a
   PDF is actually being fetched, so "your download has started" is never
   shown before it's true. Large files (the Commission Guide is ~95MB)
   otherwise leave the visitor with zero feedback for several seconds. */
.world-download-progress { display: none; width: 100%; }
.world-download-form.is-downloading input,
.world-download-form.is-downloading button[type="submit"] { display: none; }
.world-download-form.is-downloading .world-download-progress { display: block; }
.world-download-progress-track {
  width: 100%;
  height: 3px;
  border-radius: 2px;
  background: rgba(255, 255, 255, 0.25);
  overflow: hidden;
}
.world-download-progress-bar {
  height: 100%;
  width: 0%;
  background: #fff;
  transition: width .15s ease;
}
.world-download-progress-label {
  font-family: var(--sans);
  font-size: 11px;
  letter-spacing: 0.06em;
  color: rgba(255, 255, 255, 0.85);
  text-align: center;
  margin: 8px 0 0;
}
.world-media-overlay-close {
  position: absolute;
  top: clamp(12px, 1.6vw, 20px);
  right: clamp(12px, 1.6vw, 20px);
  width: 32px;
  height: 32px;
  border: 0;
  background: none;
  color: #fff;
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
  opacity: 0.8;
}
.world-media-overlay-close:hover { opacity: 1; }

/* Mobile-only ~30% reduction for the standard (non-subchip) contact-form
   overlay — Concierge's "Make an appointment", B2B's clone of it, and
   Press's "Tell us how we can help" all use this base variant directly
   (same one the signature/legacy/price overlays use when opened from an
   object's detail panel rather than a .world-subchip). Desktop untouched. */
@media (max-width: 860px) {
  .world-media-overlay:not(.is-subchip-overlay) .world-media-overlay-inner p {
    font-size: clamp(9.8px, 0.7vw, 11px);
  }
  .world-media-overlay:not(.is-subchip-overlay) .world-download-form {
    gap: 7px;
    width: min(168px, 56vw);
    margin-top: 4px;
  }
  .world-media-overlay:not(.is-subchip-overlay) .world-download-form input,
  .world-media-overlay:not(.is-subchip-overlay) .world-download-form textarea {
    font-size: 9px;
    padding: 7px 8px;
  }
  .world-media-overlay:not(.is-subchip-overlay) .world-download-form button[type="submit"] {
    font-size: 8px;
    padding: 8px 8px;
  }
  .world-media-overlay:not(.is-subchip-overlay) .world-download-sent {
    font-size: 8px;
  }
  .world-media-overlay:not(.is-subchip-overlay) .world-download-progress-label {
    font-size: 8px;
  }
  .world-media-overlay:not(.is-subchip-overlay) .world-media-overlay-close {
    width: 22px;
    height: 22px;
    font-size: 15px;
    top: clamp(8px, 1.1vw, 14px);
    right: clamp(8px, 1.1vw, 14px);
  }
}

/* Compact variant: applied (via JS reparenting, see index.html) when an
   overlay is opened from inside a .world-subchip rather than the full
   .world-media panel — the card is only ~278px (desktop) / up to ~360px
   (mobile) square, so the same padding/type scale used for the big media
   panel would overflow it. overflow-y:auto on .world-media-overlay
   (unchanged) is the safety net if content still runs long. */
.world-media-overlay.is-subchip-overlay {
  padding: 16px 14px;
  gap: 8px;
}
.world-media-overlay.is-subchip-overlay .world-media-overlay-inner {
  gap: 8px;
}
.world-media-overlay.is-subchip-overlay .world-media-overlay-inner p {
  font-size: 9px;
  letter-spacing: 0.07em;
  line-height: 1.35;
}
.world-media-overlay.is-subchip-overlay .world-download-form {
  width: 100%;
  gap: 6px;
  margin-top: 2px;
}
.world-media-overlay.is-subchip-overlay .world-download-form input,
.world-media-overlay.is-subchip-overlay .world-download-form textarea {
  font-size: 10px;
  padding: 6px 8px;
}
.world-media-overlay.is-subchip-overlay .world-download-form button[type="submit"] {
  font-size: 9px;
  padding: 7px 8px;
}
.world-media-overlay.is-subchip-overlay .world-download-sent {
  font-size: 9.5px;
}
.world-media-overlay.is-subchip-overlay .world-download-progress-label {
  font-size: 9.5px;
}
.world-media-overlay.is-subchip-overlay .world-media-overlay-close {
  width: 22px;
  height: 22px;
  font-size: 15px;
  top: 6px;
  right: 6px;
}
@media (max-width: 860px) {
  /* The mobile sub-chip card is min(360px,82vw) — noticeably roomier than
     the fixed 278px desktop card — so the compact sizes above (tuned for
     desktop) read as cramped here. Scale back up closer to the original
     full-size form's proportions (13px type, ~11px input padding). */
  .world-media-overlay.is-subchip-overlay {
    padding: 15px 13px;
    gap: 8px;
  }
  .world-media-overlay.is-subchip-overlay .world-media-overlay-inner p {
    font-size: 9px;
    letter-spacing: 0.1em;
    line-height: 1.5;
  }
  .world-media-overlay.is-subchip-overlay .world-download-form {
    gap: 7px;
    margin-top: 3px;
  }
  .world-media-overlay.is-subchip-overlay .world-download-form input,
  .world-media-overlay.is-subchip-overlay .world-download-form textarea {
    font-size: 10px;
    padding: 8px 9px;
  }
  .world-media-overlay.is-subchip-overlay .world-download-form button[type="submit"] {
    font-size: 8px;
    padding: 8px 8px;
  }
  .world-media-overlay.is-subchip-overlay .world-download-sent {
    font-size: 8px;
  }
  .world-media-overlay.is-subchip-overlay .world-download-progress-label {
    font-size: 8px;
  }
  .world-media-overlay.is-subchip-overlay .world-media-overlay-close {
    width: 21px;
    height: 21px;
    font-size: 14px;
    top: 7px;
    right: 7px;
  }
}

/* Sits in the same grid cell as .world-copy (column 2, row 1) and stretches
   to the full row height — since .world-media is sticky, it visually stays
   in view for as long as the whole menu column scrolls past, so the
   backdrop needs to cover that entire column, not just its own short box. */
.world-copy-bg {
  grid-column: 2;
  grid-row: 1;
  align-self: stretch;
  background: #fbf0e6;
  z-index: 0;
  pointer-events: none;
}
/* Each world can have its own backdrop colour — set via the JS-driven
   [data-active-screen] attribute on #world (see the drill-down nav script). */
#world[data-active-screen="dining"] .world-copy-bg { background: #fcf0ef; }
#world[data-active-screen="living"] .world-copy-bg { background: #efe8d5; }

.world-slide {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transform: scale(1);
  transform-origin: center center;
  /* Transitioning transform too (not just opacity) means that when
     .is-active is removed mid-zoom, the scale eases back down smoothly
     instead of snapping instantly to 1 — it settles at exactly the same
     pace as the fade, so the two finish together. */
  transition: opacity 2.5s ease-in-out, transform 2.5s ease-in-out;
}
.world-slide.is-active {
  opacity: 1;
  /* Slow, soft Ken Burns push-in while each frame holds — timed to finish
     exactly as the crossfade to the next slide completes (see JS interval
     + this transition's duration), so the zoom never feels cut short. */
  animation: worldSlideZoom 8s ease-in-out forwards;
}
@keyframes worldSlideZoom {
  from { transform: scale(1); }
  to   { transform: scale(1.08); }
}

.world-copy {
  grid-column: 2;
  grid-row: 1;
  position: relative;
  /* The real bug behind the "changing gap" while scrolling: .world-media
     is sticky, but a sticky element can only stay stuck for as long as its
     grid row is TALLER than its own box — the row's height is set by
     whichever column has more content. Short screens (e.g. the 5-item
     worlds list, or a 2-paragraph object detail) are shorter than the
     slideshow's own ~4:5 box, so there is little/no room for it to
     actually stick — it just scrolls normally the whole time, and the
     gap to the header keeps changing continuously. Forcing every screen
     to be at least one viewport tall guarantees real scroll room, so the
     slideshow can hold a constant gap for the whole scroll, regardless of
     which screen/level is currently showing. */
  min-height: calc(100vh - var(--header-h, 156px));
  z-index: 2;
}

.world-screen {
  display: none;
  opacity: 0;
  transform: translateY(22px);
}
.world-screen.is-active {
  display: block;
  animation: worldScreenIn .6s cubic-bezier(.22,.7,.25,1) forwards;
}
@keyframes worldScreenIn {
  from { opacity: 0; transform: translateY(22px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* "The MANIMA World" is the one exception that centres on the same axis
   as the icons (the seam / logo centre-line) rather than left-aligning.
   Since .world-copy is exactly half of .world-split (equal columns, no
   gap), a 200%-wide box pulled left by its own width spans the full
   split — centring text inside it centres it on the seam, not the column. */
.world-heading {
  text-align: left;
  margin-left: clamp(67px, 8.4vw, 103px);
  font-family: var(--serif);
  font-style: italic;
  font-weight: 400;
  font-size: clamp(21px, 2.9vw, 37px);
  margin-top: clamp(16px, 3vw, 40px);
  margin-bottom: 34px;
  line-height: 1.15;
}

/* Everything else stays left-aligned on one consistent guide — the same
   offset the object rows use — so title, tagline, back-link and every
   label share a single vertical line down the column. */
.world-title,
.world-tagline,
.world-back {
  margin-left: clamp(67px, 8.4vw, 103px);
}

/* #world scoping (ID specificity) guarantees these beat the generic
   .split .copy h2 / .split .copy p rules used on other pages — those
   were silently resetting margin-left, font and alignment here. */
#world h2.world-title {
  font-family: var(--serif);
  font-style: italic;
  font-weight: 400;
  /* Same size as the other main headlines (.world-heading / "The MANIMA
     World"), for visual consistency across the drill-down levels. */
  font-size: clamp(21px, 2.9vw, 37px);
  margin-top: 0;
  margin-bottom: 14px;
  margin-left: clamp(67px, 8.4vw, 103px);
  line-height: 1.15;
  white-space: normal;
  max-width: none;
}

#world p.world-tagline {
  font-family: var(--serif);
  font-style: italic;
  font-size: clamp(16px, 1.4vw, 20px);
  color: var(--ink);
  max-width: 40ch;
  margin-top: 0;
  margin-bottom: 34px;
  margin-left: clamp(67px, 8.4vw, 103px);
  text-align: left;
}

.world-back,
.world-unfocus {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  color: var(--muted);
  transition: opacity .2s ease;
}
.world-back { margin-top: clamp(16px, 3vw, 40px); margin-bottom: 22px; }

.world-back-arrow {
  display: block;
  width: 28px;
  height: auto;
}

.world-back-label {
  font-family: var(--sans);
  font-size: 12px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
}
.world-unfocus { margin-top: 18px; }
.world-back:hover,
.world-unfocus:hover { opacity: 0.6; }

/* Clean, even spacing above the first icon, below the last one, and
   between each row — independent of any heading (there's no heading
   inside this list anymore, "The MANIMA World" now sits above the whole
   split). */
.world-list { padding: clamp(32px, 5vw, 56px) 0 32px; }

.world-row {
  /* Same principle as the object rows now: icon on top, label below,
     left-aligned — no longer icon-beside-label. */
  position: relative;
  display: block;
  width: 100%;
  background: none;
  border: 0;
  padding: 0 0 32px;
  cursor: pointer;
  text-align: left;
}
.world-row:last-child { padding-bottom: 0; }
.world-object-row {
  position: relative;
  display: block;
  width: 100%;
  background: none;
  border: 0;
  padding: 0 0 16px;
  cursor: pointer;
  text-align: left;
}

/* Every icon shares one fixed, uniform "slot" size (object-fit: contain
   centres each piece of artwork inside it, whatever its native aspect
   ratio) and is centred exactly on the seam between the slideshow and the
   text column, so it always sits half over the embroidery and half over
   the white panel. Because the slot width is fixed, the label below can
   start at one constant offset — no more per-icon guessing, no overlap. */
.world-row-media {
  position: absolute;
  left: 0;
  top: 0;
  /* Flush against the slideshow's right edge (the seam) — no longer
     centred/straddling. All five main-menu icons share an identical 2:1
     aspect ratio, so width/height stay proportional at every size.
     25% smaller than before, so the label can sit below the icon instead
     of beside it, same as the object rows. */
  width: clamp(150px, 16.5vw, 240px);
  height: clamp(75px, 8.25vw, 120px);
  z-index: 2;
  pointer-events: none;
}
.world-object-row .world-row-media {
  /* Same size as the main-menu icons now — same slot, same treatment. */
  top: 0;
  bottom: auto;
  width: clamp(150px, 16.5vw, 240px);
  height: clamp(75px, 8.25vw, 120px);
}

.world-row-media img,
.world-row-media svg {
  width: 100%;
  height: 100%;
  object-fit: contain;
  object-position: center bottom;
  display: block;
  transition: transform .5s cubic-bezier(.22,.7,.25,1);
}
.world-object-row .world-row-media img,
.world-object-row .world-row-media svg {
  filter: drop-shadow(0 10px 18px rgba(17,17,17,0.24));
}
.world-row-media svg {
  stroke: var(--ink);
  stroke-width: 1.1;
  fill: none;
}
.world-row:hover .world-row-media img,
.world-row:hover .world-row-media svg,
.world-object-row:hover .world-row-media img,
.world-object-row:hover .world-row-media svg {
  transform: translateY(-3px);
}

.world-row-label {
  font-family: var(--sans);
  font-size: clamp(13px, 1vw, 15px);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink);
  /* Below the icon now, not beside it — left-aligned with the rest of
     the copy (same offset as .world-title / .world-detail p). */
  display: block;
  padding-left: 0;
  padding-bottom: 0;
  margin-left: clamp(67px, 8.4vw, 103px);
  margin-top: calc(clamp(75px, 8.25vw, 120px) + 14px);
  transition: opacity .3s ease;
}
.world-object-row .world-row-label {
  letter-spacing: 0.08em;
}
.world-row:hover .world-row-label { opacity: 0.55; }

.world-object {
  max-height: 640px;
  opacity: 1;
  transition: max-height .5s ease, opacity .4s ease, margin .4s ease;
}
.world-object.is-away {
  max-height: 0;
  opacity: 0;
  /* Clipping only applies while a sibling pushes this one away — in the
     normal/focused state overflow stays visible so the icon can bleed
     over the seam onto the slideshow instead of being cut off. */
  overflow: hidden;
}

.world-detail {
  max-height: 0;
  opacity: 0;
  overflow: hidden;
  padding-left: clamp(67px, 8.4vw, 103px);
  transition: max-height .6s ease, opacity .5s ease .05s;
}
.world-object.is-focused .world-detail {
  max-height: 640px;
  opacity: 1;
  padding-bottom: 28px;
}

#world .world-detail p {
  font-family: var(--sans);
  font-style: normal;
  font-size: clamp(14px, 1.05vw, 16px);
  line-height: 1.65;
  color: var(--ink-soft);
  max-width: 52ch;
  margin: 0 0 14px;
  text-align: left;
}

#world .world-detail .world-inline-link,
#world .world-detail .world-inline-link:visited {
  color: var(--link);
  text-decoration: none;
}
#world .world-detail .world-inline-link:hover { color: var(--link-hover); }

/* Same treatment for the "Make an appointment." link in the Concierge
   prose — .world-inline-link only has color/no-underline styling when
   scoped under .world-subchip or #world .world-detail, so outside those
   two it was falling back to the browser's default underlined link.
   .press-section sits as its own sibling section outside the #press id
   (see index.html), so it needs the same explicit opt-in — otherwise its
   "Read the feature" links silently fall back to default blue/underline
   too, breaking the site-wide rule that text links are always grey, never
   underlined. */
#b2b .world-inline-link,
#b2b .world-inline-link:visited,
#concierge .world-inline-link,
#concierge .world-inline-link:visited,
#press .world-inline-link,
#press .world-inline-link:visited,
.press-section .world-inline-link,
.press-section .world-inline-link:visited,
#trousseau-copy .world-inline-link,
#trousseau-copy .world-inline-link:visited,
.cookie-banner .world-inline-link,
.cookie-banner .world-inline-link:visited {
  color: var(--link);
  text-decoration: none;
}
#b2b .world-inline-link:hover,
#concierge .world-inline-link:hover,
#press .world-inline-link:hover,
.press-section .world-inline-link:hover,
#trousseau-copy .world-inline-link:hover,
.cookie-banner .world-inline-link:hover { color: var(--link-hover); }

#world .world-detail p.world-price {
  font-style: italic;
  color: var(--muted);
}

@media (max-width: 860px) {
  .world-explorer { padding-top: 20px; }
  /* A bit more breathing room between "We give your rituals a signature."
     and the slideshow/mosaic right under it (was the same 26px as
     desktop, which read as too tight once the mosaic sits full-width and
     stacked on mobile). */
  #world .world-mid-heading { margin-bottom: 40px; }
  .world-split { grid-template-columns: 1fr; gap: 28px; }
  .world-media {
    grid-column: 1;
    grid-row: auto;
    position: relative;
    top: auto;
    aspect-ratio: 4 / 3;
    min-height: 0;
  }
  /* Below the breakpoint the wide mosaic banner turns portrait (3 cols x
     10 rows instead of 7x3) — a landscape 7:3 strip is too shallow to hold
     a swipeable row of square chips on a phone. Extended again from 3x10
     (30 cells) to 3x13 (39 cells) to give the now-through-Bathing chip run
     enough vertical room in the slideshow — reuses the same 30-image
     mosaic pool (25 embroidery + 5 colour), so some images repeat
     across the extra 9 cells; that's expected (pickImage() falls back to a
     repeat once the unused pool for a cell's rules is exhausted). Mosaic
     cells stay square either way since rows/cols and the aspect-ratio flip
     together — must match the JS's GRID_COLS/GRID_ROWS exactly. */
  /* min-height is a belt-and-braces floor alongside aspect-ratio, not a
     replacement for it — chips have kept clipping at the bottom despite
     the ratio math checking out on paper, so this guarantees real height
     through a second, independent mechanism (vw units, not dependent on
     aspect-ratio resolving correctly at all) rather than trying to reason
     out why aspect-ratio alone wasn't enough. ~88vw container width * 13/3
     ≈ 381vw; 377vw kept just under that so it only ever acts as a floor,
     never fighting the ratio if that IS in fact computing correctly. */
  #world .world-media--wide-test {
    aspect-ratio: 3 / 13;
    min-height: 377vw;
  }
  .world-mosaic {
    grid-template-columns: repeat(3, 1fr);
    grid-template-rows: repeat(13, 1fr);
  }
  /* Mobile-only: the chip carousel turns vertical (swipe up/down, one chip
     at a time) instead of the desktop horizontal swipe — matches the now-
     portrait mosaic strip. Chips are sized well beyond the mosaic's own
     grid (large, dominant squares) rather than shrinking to fit a column.
     Stays an absolutely-positioned overlay ON TOP of the mosaic — that's
     the whole point of the transparent chip artwork (a window onto the
     moving photos behind it), so this must not become normal page flow.

     Native overflow-y:auto + scroll-snap (three attempts: overscroll-
     behavior, padding→margin, taller box) never reliably stayed contained
     — the swipe kept handing off to the page scroll partway through the 5
     chips. Replaced with a JS-driven carousel (see index.html) that moves
     this row via transform and owns the touch gesture directly instead of
     relying on the browser's nested-scroll behaviour at all.
     Top padding increased (32px min → 60px min) so chip 0's resting
     position has real breathing room above it instead of sitting flush
     against the mosaic's top edge — a plain CSS gap, nothing repositioned
     or resized. */
  .world-chip-row-test {
    flex-direction: column;
    justify-content: flex-start;
    overflow: hidden;
    touch-action: none;
    /* All three now come from ONE JS-computed value (see the "even
       spacing" script in index.html) instead of two independent
       hardcoded numbers — the old fixed 64px gap and the old
       clamp(60px,14vw,100px) edge padding never actually matched each
       other (nor scaled the same way), so the space above chip 0 and the
       space between/after the chips never read as truly even. --chip-gap-m
       is (slideshow height − 5×chip height) ÷ 6, giving identical gaps
       top, between every chip, and at the bottom, at any viewport width.
       The px fallbacks only apply for the instant before that script
       first runs. */
    gap: var(--chip-gap-m, 64px);
    padding-top: var(--chip-gap-m, 60px);
    padding-bottom: var(--chip-gap-m, 60px);
    will-change: transform;
  }
  /* Reduced ~30% from the previous min(360px,82vw) — chips were too tall
     relative to the mosaic/slideshow's real height on mobile, cutting off
     the bottom chip regardless of positioning. */
  .world-chip-test {
    width: min(252px, 57vw);
  }
  .world-chip-headline-test {
    font-size: 10px;
  }
  /* Single column below the breakpoint — media and copy stack normally,
     so the overlapping backdrop from the desktop layout is no longer needed. */
  .world-copy-bg { display: none; }
  .world-copy { grid-column: 1; grid-row: auto; }
  /* Below the breakpoint there is no seam to straddle — icon sits above
     its label like a normal stacked list item. */
  .world-row,
  .world-object-row {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    min-height: 0;
    padding: 24px 0 16px;
    gap: 14px;
  }
  .world-row-media,
  .world-object-row .world-row-media {
    position: static;
    top: auto;
    bottom: auto;
    transform: none;
    width: 77px;
    height: 58px;
  }
  .world-object-row .world-row-media { width: 62px; height: 48px; }
  .world-row-media img,
  .world-row-media svg {
    object-position: center;
  }
  .world-object-row .world-row-media img,
  .world-object-row .world-row-media svg {
    filter: drop-shadow(0 4px 8px rgba(17,17,17,0.15));
  }
  .world-row-label,
  .world-object-row .world-row-label {
    padding-left: 0;
    padding-bottom: 0;
    margin-left: 0;
    margin-top: 0;
  }
  .world-heading {
    width: auto;
    margin-left: 0;
    margin-top: 0;
    text-shadow: none;
  }
  .world-tagline,
  .world-title,
  .world-back {
    margin-left: 0;
  }
  /* Re-override the #world-scoped (ID-specificity) desktop rules, which
     a plain class selector can't beat regardless of media query order. */
  #world h2.world-title,
  #world p.world-tagline {
    margin-left: 0;
  }
  .world-detail { padding-left: 0; }
}

/* ---------- OUR WORLD FILM (below the whole configuration section) ---------- */
.world-film-section { padding-top: 0; padding-bottom: 100px; }

.world-film-heading {
  text-align: center;
  font-family: var(--serif);
  font-style: italic;
  font-weight: 400;
  font-size: clamp(21px, 2.9vw, 37px);
  line-height: 1.15;
  margin: 0 0 34px;
  color: var(--ink);
}


.world-film-wrap {
  position: relative;
  aspect-ratio: 16 / 9;
  width: 75%;
  margin: 0 auto;
  overflow: hidden;
}

/* ---------- SECTION DIVIDER (between main-nav sections only) ---------- */
/* Small ornament marking the boundary between the six main-nav sections
   (World/Vision/Atelier/Trousseau/Concierge/Press) now that they're one
   continuous scroll. Deliberately a plain, unpositioned sibling sitting
   *before* the next section in the DOM — never inside it, never pulled up
   via negative margin — so on an anchor-jump (nav-link click) the target
   section's own scroll-margin-top still puts its heading right at the
   header, and this ends up scrolled out of view above it, exactly as
   required. Kept small/quiet (low opacity) on purpose.
   Now also a real link back to #top (see id="top" on .site-header) — the
   page's native scroll-behavior:smooth handles the animated scroll, no
   extra JS needed. */
/* Two thin rules, one above and one below the icon — no background
   change, page stays plain white here exactly as before. Line width
   matches the shared video-width grid (.world-film-wrap's own 75% /
   5-of-7 formula, reused everywhere else on the site) instead of a short
   ornamental dash. IMPORTANT: only this element's own look changes — its
   outer margin (0 0 12px) is untouched, and nothing here touches
   scroll-margin-top on the section ids or the .world-film-section:has(+
   .section-divider + #id) padding-bottom rules further up this file, so
   the anchor-jump / "glued heading" behaviour on a nav-link click is
   pixel-identical to before. */
.section-divider {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 14px;
  /* Same box model as .container (max-width/margin/padding) — .section-
     divider sits directly under <main>, not nested in a .container, so
     without this its own width (and therefore the lines' percentages
     below) would be measured against the raw viewport instead of the
     same padded content box .world-film-wrap measures its 75% / 5-of-7
     against. This is what makes the lines actually come out video-width,
     not just numerically 75%-of-something-else. */
  max-width: var(--max-w);
  /* Bottom margin bumped 12px -> 32px for more headroom above every
     headline that follows one of these dividers. Safe to change here
     specifically (and only here) because of how anchor-jump scrolling
     works: a nav-link click positions the *target section's own* top
     edge at scroll-margin-top from the header — the divider sits
     *before* that section (see the comment above this whole block) and
     ends up scrolled out of view above it either way, so its own margin
     never factors into where the heading lands after a nav click. It
     only adds visible space when scrolling through the page naturally.
     The heading's own margin-top (scoped per id, e.g. #b2b .world-intro-
     heading) and scroll-margin-top itself are both untouched. */
  margin: 0 auto 32px;
  padding: 0 var(--pad-x);
  text-decoration: none;
}
.section-divider-line {
  width: 75%;
  height: 1px;
  background: var(--rule);
}
@media (min-width: 861px) {
  .section-divider-line { width: calc(100% / 7 * 5); }
}
.section-divider img { transition: opacity .2s ease; }
.section-divider:hover img { opacity: 0.6; }
.section-divider img {
  /* Same size as the three leaf marks in the header logo render (logo is
     60px tall overall, leaves occupy ~44% of that ≈ 27px, bumped 10%
     larger per feedback → 31px), now reduced a further 20% (31 * 0.8 =
     24.8px) per later feedback. */
  height: 24.8px;
  width: auto;
  opacity: 0.35;
}

@media (max-width: 860px) {
  /* Same leaf-to-logo ratio as before (31/60 ≈ 0.517), re-applied to the
     mobile logo's own shrunk height (.logo-wrap img/svg, clamp(45px,
     11.9vw, 62px)) and then reduced the same further 20% as the desktop
     value above. */
  .section-divider img {
    height: clamp(18.4px, 4.92vw, 24.8px);
  }
  .section-divider { gap: 12px; }
}

/* Resize (not crop) the video so its left/right edges land exactly where
   the master 7x3 mosaic's edge-column cells would end — same 1/7 math the
   mosaic itself uses (see .world-mosaic / aspect-ratio:7/3 below), so the
   video occupies the middle 5/7 of the container. Applied to all three
   film sections (World/Vision/Mission), desktop only. */
.world-film-section--aligned .world-film-wrap {
  width: calc(100% / 7 * 5);
}

.world-film {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* The browser's native fullscreen mode only forces size/position — it does
   NOT reset object-fit, so without this the video would keep "cover"ing
   the full device screen and get cropped to match its aspect ratio.
   Switch to "contain" (classic letterboxed fullscreen, no cropping) only
   while the video is the fullscreen element. */
.world-film:fullscreen,
.world-film:-webkit-full-screen {
  object-fit: contain;
  background: #000;
}

/* Primary fullscreen path: the whole wrap (video + our own buttons) goes
   fullscreen together, so the mute button and the close "X" stay visible
   and usable — see the JS comment for why fullscreening the bare <video>
   alone doesn't work for this. Object-fit still needs the same cover→contain
   swap here, scoped via the ancestor instead of the video's own :fullscreen.

   The object-fit swap alone wasn't the whole fix, though: .world-film-wrap
   itself carries a fixed aspect-ratio:16/9 plus width:75% (or 5/7 via
   .world-film-section--aligned) for its normal in-page layout, and NEITHER
   of those was ever reset for the fullscreen state. So on any screen that
   isn't itself 16:9, the wrap kept forcing its box into a 16:9 shape sized
   off a fraction of the screen — on an ultrawide monitor that left the
   video floating in a 16:9 island with no real letterbox at all; on a
   taller/narrower screen the box's own height could exceed the viewport
   and get clipped by the wrap's overflow:hidden. object-fit:contain can
   only letterbox correctly *within* a box that itself already fills the
   real screen — this makes the wrap that box: full viewport, no imposed
   ratio, so whatever black margin is left (the actual dynamic letterbox)
   forms naturally around the contained video regardless of the screen's
   own aspect ratio. */
.world-film-wrap:fullscreen,
.world-film-wrap:-webkit-full-screen,
.world-film-wrap.is-fs {
  background: #000 !important;
  aspect-ratio: auto !important;
  width: 100vw !important;
  height: 100vh !important;
  margin: 0 !important;
}
.world-film-wrap:fullscreen .world-film,
.world-film-wrap:-webkit-full-screen .world-film,
.world-film-wrap.is-fs .world-film {
  object-fit: contain;
}
/* The "enter fullscreen" icon is redundant once already fullscreen — the
   close "X" takes over as the single, unambiguous way out.
   .is-fs is a JS-driven mirror of :fullscreen (see the fullscreenchange
   listener in the script) — kept alongside the pseudo-class rules as a
   belt-and-suspenders fallback since the pseudo-class alone proved
   unreliable for the sizing above. */
.world-film-wrap:fullscreen .world-fullscreen-toggle,
.world-film-wrap:-webkit-full-screen .world-fullscreen-toggle,
.world-film-wrap.is-fs .world-fullscreen-toggle {
  display: none;
}
.world-film-close {
  display: none;
  position: absolute;
  top: clamp(14px, 1.6vw, 22px);
  right: clamp(14px, 1.6vw, 22px);
  z-index: 4;
  width: 42px;
  height: 42px;
  border-radius: 50%;
  border: none;
  background: rgba(17, 17, 17, 0.55);
  backdrop-filter: blur(2px);
  color: #fff;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: background .2s ease;
}
.world-film-close:hover { background: rgba(17, 17, 17, 0.75); }
.world-film-close svg {
  width: 18px;
  height: 18px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
}
.world-film-wrap:fullscreen .world-film-close,
.world-film-wrap:-webkit-full-screen .world-film-close,
.world-film-wrap.is-fs .world-film-close {
  display: flex;
}

/* If the file is ever missing, hide the section instead of showing a broken player. */
.world-film-section.film-unavailable { display: none; }

.world-sound-toggle {
  position: absolute;
  right: clamp(14px, 1.6vw, 22px);
  bottom: clamp(14px, 1.6vw, 22px);
  z-index: 3;
  width: 42px;
  height: 42px;
  border-radius: 50%;
  border: none;
  background: rgba(17, 17, 17, 0.55);
  backdrop-filter: blur(2px);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: background .2s ease;
}
.world-sound-toggle:hover { background: rgba(17, 17, 17, 0.75); }
.world-sound-toggle svg {
  width: 20px;
  height: 20px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.world-sound-toggle .icon-unmuted { display: none; }
.world-sound-toggle.is-unmuted .icon-muted { display: none; }
.world-sound-toggle.is-unmuted .icon-unmuted { display: block; }

/* Fullscreen button — mirrors the mute button, opposite corner. */
.world-fullscreen-toggle {
  position: absolute;
  left: clamp(14px, 1.6vw, 22px);
  bottom: clamp(14px, 1.6vw, 22px);
  z-index: 3;
  width: 42px;
  height: 42px;
  border-radius: 50%;
  border: none;
  background: rgba(17, 17, 17, 0.55);
  backdrop-filter: blur(2px);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: background .2s ease;
}
.world-fullscreen-toggle:hover { background: rgba(17, 17, 17, 0.75); }
.world-fullscreen-toggle svg {
  width: 20px;
  height: 20px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* Full player controls (play/pause + seek bar + volume, alongside the
   existing mute button) — scoped to .world-film-wrap--player, which World,
   Mission, Vision and Trousseau all carry; Concierge/Press stay plain
   ambient loops with no controls at all (no --player class, no mute
   button). Grouped into one bottom row; fullscreen stays put bottom-left. */
.world-film-wrap--player .world-sound-toggle {
  position: static;
}
.world-film-controls {
  position: absolute;
  /* left inset clears the fullscreen button (42px, same bottom row, see
     .world-fullscreen-toggle) so the seek bar below doesn't run under it */
  left: calc(clamp(14px, 1.6vw, 22px) + 42px + 10px);
  right: clamp(14px, 1.6vw, 22px);
  bottom: clamp(14px, 1.6vw, 22px);
  z-index: 3;
  display: flex;
  align-items: center;
  gap: 8px;
}
.world-play-toggle {
  flex: 0 0 auto;
  width: 42px;
  height: 42px;
  border-radius: 50%;
  border: none;
  background: rgba(17, 17, 17, 0.55);
  backdrop-filter: blur(2px);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: background .2s ease;
}
.world-play-toggle:hover { background: rgba(17, 17, 17, 0.75); }
.world-play-toggle svg {
  width: 16px;
  height: 16px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.world-play-toggle .icon-play {
  fill: currentColor;
  stroke: none;
  display: none;
}
.world-play-toggle.is-paused .icon-pause { display: none; }
.world-play-toggle.is-paused .icon-play { display: block; }

.world-volume-slider {
  flex: 0 0 auto;
  -webkit-appearance: none;
  appearance: none;
  /* Without this, Chrome/Edge tint the native fill with the OS accent
     colour (usually blue) even though appearance is otherwise fully
     custom — flattens it back to plain white/grey like the rest of the UI. */
  accent-color: rgba(255, 255, 255, 0.9);
  width: 72px;
  height: 3px;
  border-radius: 2px;
  background: rgba(255, 255, 255, 0.35);
  outline: none;
  cursor: pointer;
  margin: 0 4px;
}
.world-volume-slider::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: #fff;
  cursor: pointer;
}
.world-volume-slider::-moz-range-thumb {
  width: 12px;
  height: 12px;
  border-radius: 50%;
  border: none;
  background: #fff;
  cursor: pointer;
}
.world-volume-slider::-moz-range-track {
  height: 3px;
  border-radius: 2px;
  background: rgba(255, 255, 255, 0.35);
}
/* Firefox draws the "played" portion as a separate ::-moz-range-progress
   layer on top of the track in its own accent colour (blue by default) —
   match it to the track so there's no colour break, same flat look as
   every other slider on the site. */
.world-volume-slider::-moz-range-progress {
  height: 3px;
  border-radius: 2px;
  background: rgba(255, 255, 255, 0.35);
}

/* Seek/scrub bar — full draggable timeline (click-or-drag-to-seek) between
   the play button and the volume/mute cluster. Same flat-track visual
   language as .world-volume-slider, just growing to fill the row so it
   spans the width of the control bar. */
.world-seek-slider {
  flex: 1 1 auto;
  min-width: 0;
  -webkit-appearance: none;
  appearance: none;
  accent-color: rgba(255, 255, 255, 0.9);
  height: 3px;
  border-radius: 2px;
  background: rgba(255, 255, 255, 0.35);
  outline: none;
  cursor: pointer;
  margin: 0 4px;
}
.world-seek-slider::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: #fff;
  cursor: pointer;
}
.world-seek-slider::-moz-range-thumb {
  width: 12px;
  height: 12px;
  border-radius: 50%;
  border: none;
  background: #fff;
  cursor: pointer;
}
.world-seek-slider::-moz-range-track {
  height: 3px;
  border-radius: 2px;
  background: rgba(255, 255, 255, 0.35);
}
.world-seek-slider::-moz-range-progress {
  height: 3px;
  border-radius: 2px;
  background: rgba(255, 255, 255, 0.35);
}

/* Player controls (fullscreen button + the play/seek/volume/mute cluster)
   start hidden and are revealed purely by :hover/:focus-within — visible
   only while the cursor is actually over the video, gone the instant it
   isn't, no lingering timer. This is what fixes the "covers the captions"
   complaint: during normal ambient viewing nothing sits over the
   burned-in captions at all. The one exception is .controls-visible,
   toggled by JS (see the film players script) purely to keep the bar up
   while the video is paused, so a visitor who paused isn't left reaching
   for controls that just faded out from under their cursor. */
.world-film-wrap--player .world-fullscreen-toggle,
.world-film-wrap--player .world-film-controls {
  opacity: 0;
  pointer-events: none;
  transition: opacity .25s ease;
}
.world-film-wrap--player:focus-within .world-fullscreen-toggle,
.world-film-wrap--player:focus-within .world-film-controls,
.world-film-wrap--player.controls-visible .world-fullscreen-toggle,
.world-film-wrap--player.controls-visible .world-film-controls {
  opacity: 1;
  pointer-events: auto;
}
/* :hover reveal scoped to devices with an actual mouse/trackpad (hover:
   hover AND pointer: fine) rather than just "not explicitly touch-only" —
   iPadOS Safari is known to report hover:hover even with no mouse
   connected (since one COULD be connected via Bluetooth/trackpad), and
   separately simulates a :hover state on the first tap of any touch (a
   long-standing WebKit quirk that also affects iPhone). Without this
   scoping, a tap on the video on iPad could trigger this rule directly via
   CSS and get stuck showing the controls independently of the JS-driven
   .controls-visible + auto-hide-after-3s logic below — real desktop hover
   behaviour was never actually reachable on touch, it only looked similar
   by accident. */
@media (hover: hover) and (pointer: fine) {
  .world-film-wrap--player:hover .world-fullscreen-toggle,
  .world-film-wrap--player:hover .world-film-controls {
    opacity: 1;
    pointer-events: auto;
  }
}

/* ---------- FILM TRANSCRIPTS (World / Mission / Vision / Trousseau —
   Press is a silent ambient loop with no dialogue to transcribe, see its
   schema.org VideoObject "description" instead) ---------- */
/* Same collapsed-by-default accordion mechanic as .footer-col-content
   (0fr -> 1fr grid-template-rows trick). The text itself is NOT a bespoke
   width/typography scheme — it reuses .text-block .prose's exact rules
   (75% width desktop / 720px mobile, Blocksatz, same sans + clamp size),
   just re-declared under .film-transcript-content-inner .prose instead of
   .text-block .prose, since wrapping in the real .text-block class would
   also pull in its 120px section-spacing padding, which doesn't belong
   inside an accordion. Same content column as every other flowing text
   block on the site — see chat: this was a one-off special case before
   and got corrected to match. */
.film-transcript {
  margin: 14.4px auto 0;
  text-align: center;
}

/* World/Mission/Vision are the only three .world-film-section instances
   that contain a transcript (see .film-transcript above) — this overrides
   just those three, on top of the shared :has(+ .section-divider + #id)
   30px rule further up the file. Needs !important: that shared rule's
   :has() argument includes an id (e.g. #atelier-film-intro), which counts
   towards its specificity same as :not()/:has() always do, so it outranks
   a plain two-class selector like this one regardless of source order —
   confirmed by measuring the live page, this rule was silently losing the
   cascade without !important. Result: the video->TRANSCRIPT->divider span
   works out to exactly the same 53.8px gap the divider's own two lines
   sit apart by, with "Transcript" sitting exactly centered between video
   and the divider's top line. Measured/solved with a headless-browser
   check, not eyeballed: .film-transcript's margin-top (14.4px) and this
   padding-bottom (17.4px) are the two independent levers, the other
   ~9.5px on each side comes from the toggle button's own line-height/
   height that isn't worth hand-tuning further. B2B/Concierge/Press (no
   transcript) keep their normal 30px from the shared rule, untouched. */
.world-film-section:has(.film-transcript) {
  padding-bottom: 17.4px !important;
}
.film-transcript-toggle {
  display: inline-block;
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  font-family: var(--sans);
  font-size: 11px;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--muted);
  transition: color 0.2s ease;
}
.film-transcript-toggle:hover,
.film-transcript.is-open .film-transcript-toggle { color: var(--ink); }

.film-transcript-content {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 0.3s ease;
}
.film-transcript-content-inner { overflow: hidden; }
.film-transcript.is-open .film-transcript-content {
  grid-template-rows: 1fr;
  margin-top: 14px;
}

.film-transcript-content-inner .prose {
  max-width: 75%;
  margin: 0 auto;
  padding: 0 24px;
  text-align: justify;
}
.film-transcript-content-inner .prose p {
  font-family: var(--sans);
  font-style: normal;
  font-weight: 400;
  font-size: clamp(14px, 1.05vw, 17px);
  line-height: 1.7;
  letter-spacing: 0.005em;
  color: var(--ink-soft);
  margin: 0 0 18px;

  /* Blocksatz — beide Kanten bündig, same as .text-block .prose p */
  text-align: justify;
  -webkit-text-align: justify;
  text-align-last: left;
  text-justify: inter-word;
  hyphens: auto;
  -webkit-hyphens: auto;
  -ms-hyphens: auto;
}
.film-transcript-content-inner .prose p:last-child { margin-bottom: 0; }
.film-transcript-content-inner .prose p strong { color: var(--ink); font-weight: 600; }

@media (max-width: 860px) {
  /* Same desktop-only-75% exception as .text-block .prose above. */
  .film-transcript-content-inner .prose { max-width: 720px; }
}

@media (max-width: 860px) {
  /* Match the slideshow/mosaic's full container width on mobile instead of
     the desktop 75% — all three film wraps (World/Vision/Atelier) share
     the same .container box as the mosaic, so 100% lines them up exactly.
     Keep the same 16:9 ratio as desktop (inherited, no override here) —
     forcing 4:3 cropped the sides off the actual 16:9 footage. */
  .world-film-wrap { width: 100%; }
  /* The 5/7 test above is desktop-only — needs 2 classes to win outside
     any media query, so it would otherwise also beat this 1-class mobile
     rule. Force it back to the same 100% every other film wrap gets here. */
  .world-film-section--aligned .world-film-wrap { width: 100%; }
}

/* ---------- FOUNDERS (photo + name + bio, two-up) ---------- */
/* Founders/Visionaries now sits directly under the Vision intro text, with
   the video moved below it (swapped order — video is now last, right
   before the divider, matching every other section's video-last pattern).
   #vision-film-intro's own padding-bottom:8px (the "text directly followed
   by media, nothing in between" rule, shared with Atelier/Trousseau/
   Concierge/Press) already gives a tight gap above, so no negative
   margin-top is needed here any more (previously -60px, pulling up
   against the video's 100px padding when the video came first).
   padding-bottom:40px preserves the same net gap the founders/video pair
   had before (100px video padding - 60px margin = 40px), just now
   contributed from this side since the video's own top padding is 0. */
.founders-section { padding-top: 0; padding-bottom: 40px; }

.founders-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(40px, 6vw, 90px);
  max-width: var(--max-w);
  width: 75%;
  margin: 0 auto;
}
/* Same 5/7 alignment as the film sections/Trousseau above, desktop only —
   mobile keeps the existing 75% (already effectively full-width once the
   grid collapses to 1 column below). The founder photos are already
   native 1000x1000 squares, so this width change alone doesn't introduce
   any cropping — aspect-ratio:1/1 + object-fit:cover below was already
   crop-free before this and stays that way. */
@media (min-width: 861px) {
  .founders-grid {
    width: calc(100% / 7 * 5);
  }
}

.founder-photo {
  aspect-ratio: 1 / 1;
  overflow: hidden;
  background: #efe6d4;
  margin-bottom: 24px;
}
.founder-photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* Name + bio are both set in Brother 1816 (var(--sans)) — no serif here,
   unlike the italic headlines elsewhere on the site. */
.founder-name {
  font-family: var(--sans);
  font-style: normal;
  font-weight: 400;
  font-size: clamp(16px, 1.3vw, 19px);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink);
  margin: 0 0 14px;
}
.founder p {
  font-family: var(--sans);
  font-style: normal;
  font-weight: 400;
  font-size: clamp(14px, 1.05vw, 17px);
  line-height: 1.7;
  letter-spacing: 0.005em;
  color: var(--ink-soft);
  margin: 0 0 16px;
  text-align: justify;
  text-align-last: left;
  text-justify: inter-word;
  hyphens: auto;
  -webkit-hyphens: auto;
}
.founder p:last-child { margin-bottom: 0; }

@media (max-width: 860px) {
  .founders-grid { grid-template-columns: 1fr; gap: 48px; }
}

/* Shared enquiry accordion — Press's "Tell us how we can help.",
   Concierge's and B2B's "Make an appointment." all use this one ruleset
   (same 0fr->1fr grid-template-rows mechanic as .footer-col-content /
   .film-transcript-content, see comments there). All three used to be
   .world-media-overlay modals; each one's own intro section is only as
   tall as its heading + one short paragraph, nowhere near enough room for
   that overlay's full-size form — it either overlapped the text showing
   through the dark scrim, or (moved to the video instead) opened so far
   from its own trigger link that it looked like nothing had happened. An
   inline drop-down that pushes the rest of the page down while open, then
   lets it settle back on close, has neither problem — one ruleset, reused
   by id (#press-enquiry-panel / #concierge-enquiry-panel /
   #b2b-enquiry-panel) rather than three near-duplicates. Width matches
   the shared video-width grid (.world-film-wrap's own 75% / 5-of-7
   formula) used everywhere else on the site, not the full container
   width. */
.enquiry-accordion {
  width: 75%;
  margin: 20px auto 0;
}
@media (min-width: 861px) {
  .enquiry-accordion { width: calc(100% / 7 * 5); }
}
/* Extra breathing room before whatever follows (As Seen In / the photo
   section) — only while the accordion is actually open. Left off the
   base rule above on purpose: collapsed, .enquiry-accordion already
   renders at ~0 height, so a permanent margin here would just leave a
   dead gap sitting above the next section at all times. */
.enquiry-accordion.is-open {
  margin-bottom: 48px;
}
.enquiry-accordion-content {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 0.3s ease;
}
.enquiry-accordion-content-inner {
  position: relative;
  overflow: hidden;
  padding-top: 38px;
}
.enquiry-accordion.is-open .enquiry-accordion-content {
  grid-template-rows: 1fr;
  margin-top: 20px;
}
/* Explicit close control inside the open panel — clicking the trigger
   link again also closes it (same toggle mechanic as everywhere else),
   but that link is back up in the intro paragraph, easy to lose track of
   once the form has pushed the page down. A visible × right on the panel
   itself (same treatment as .world-media-overlay-close, just in ink
   instead of white for this light background) makes closing obvious.
   Hidden until the accordion is actually open — at grid-template-rows:0fr
   the button is already clipped by the overflow:hidden wrapper above, but
   opacity:0 + pointer-events:none here is an explicit belt-and-braces so
   it never flashes visible or intercepts a click while collapsed. */
.enquiry-accordion-close {
  position: absolute;
  top: 0;
  right: 0;
  width: 30px;
  height: 30px;
  border: 0;
  background: none;
  color: var(--muted);
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
  opacity: 0;
  pointer-events: none;
  transition: color 0.2s ease, opacity 0.2s ease;
}
.enquiry-accordion.is-open .enquiry-accordion-close {
  opacity: 1;
  pointer-events: auto;
}
.enquiry-accordion-close:hover { color: var(--ink); }

/* .world-download-form was built for the dark .world-media-overlay scrim
   (white text/borders on a translucent dark background) — reused here on
   the plain white page background, so the palette needs inverting to the
   same --ink/--paper/--muted/--rule variables used everywhere else on the
   site, not a bespoke new colour scheme. */
.enquiry-accordion-content-inner .world-download-form {
  width: min(320px, 80%);
  margin: 0 auto;
}
.enquiry-accordion-content-inner .world-download-form input,
.enquiry-accordion-content-inner .world-download-form textarea {
  color: var(--ink);
  background: var(--paper);
  border: 1px solid var(--rule);
}
.enquiry-accordion-content-inner .world-download-form input::placeholder,
.enquiry-accordion-content-inner .world-download-form textarea::placeholder {
  color: var(--muted);
}
.enquiry-accordion-content-inner .world-download-form input:focus,
.enquiry-accordion-content-inner .world-download-form textarea:focus {
  border-color: var(--ink);
}
.enquiry-accordion-content-inner .world-download-form button[type="submit"] {
  border: 1px solid var(--ink);
  color: var(--ink);
}
.enquiry-accordion-content-inner .world-download-form button[type="submit"]:hover {
  background: var(--ink);
  color: var(--paper);
}
.enquiry-accordion-content-inner .world-download-sent { color: var(--ink); }

/* Same inversion for the real-progress PDF download bar (see
   .world-download-progress in the dark-overlay rules above) — this is the
   first .enquiry-accordion instance to carry a download form (Trousseau's
   Heritage Map link) rather than a plain enquiry form, so the white-on-dark
   progress bar/track/label need the light-background treatment too. */
.enquiry-accordion-content-inner .world-download-progress-track {
  background: var(--rule);
}
.enquiry-accordion-content-inner .world-download-progress-bar {
  background: var(--ink);
}
.enquiry-accordion-content-inner .world-download-progress-label {
  color: var(--muted);
}

/* Lets a <button> stand in for the "Tell us how we can help." trigger
   (needed for aria-expanded/aria-controls — a real disclosure control,
   not a link to nowhere) while still reading as the exact same inline
   text link as every .world-inline-link elsewhere: strip the browser's
   own button chrome rather than adding new visual styling. */
button.world-inline-link {
  display: inline;
  background: none;
  border: 0;
  padding: 0;
  margin: 0;
  font: inherit;
  cursor: pointer;
  text-align: left;
}

/* ---------- PRESS ROOM: "As Seen In" selected-coverage grid ---------- */
/* Same slot in the flow as founders-section above (world-intro text-block
   -> this -> the following video's world-film-section, which always
   carries padding-top:0) — reuse the identical padding-top:0 /
   padding-bottom:40px pairing so the vertical rhythm matches exactly. */
.press-section { padding-top: 0; padding-bottom: 40px; }

/* Every .world-film-heading on the site (Watch the MANIMA World/Mission/
   Vision, The Visionaries of MANIMA, As Seen In) shares the same sans/
   uppercase treatment, matching the outlet-name size right below "As Seen
   In" (.press-outlet) so every sub-headline reads as one family. Scoped
   per section (rather than editing .world-film-heading itself) so the
   two-class specificity beats the mobile .world-film-heading font-size
   bump further down — this stays the same size at every viewport width. */
.world-film-section--aligned .world-film-heading,
.founders-section .world-film-heading,
.press-section .world-film-heading {
  font-family: var(--sans);
  font-style: normal;
  font-weight: 400;
  font-size: clamp(15px, 1.15vw, 18px);
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.press-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(32px, 4vw, 56px) clamp(24px, 3vw, 48px);
  max-width: var(--max-w);
  width: 75%;
  margin: 0 auto;
}
@media (min-width: 861px) {
  .press-grid { width: calc(100% / 7 * 5); }
}
@media (max-width: 1100px) and (min-width: 861px) {
  .press-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 860px) {
  /* Bug: below 861px the desktop width:75% rule above was still in
     effect (only grid-template-columns/gap were overridden here), while
     every flowing text block on the page (.text-block .prose) switches
     to max-width:720px + its own 24px side padding at this breakpoint —
     which, on an actual mobile viewport (always well under 720px),
     resolves to "100% of the container, inset 24px each side". 75% centred
     with no padding is a narrower, differently-positioned column, so the
     press cards visually stepped in from the same margin every other
     mobile text block (including the Press Room intro paragraph directly
     above this grid) lines up on. Matching that exact 100%/720px/24px
     recipe here removes the mismatch. */
  .press-grid {
    grid-template-columns: 1fr;
    gap: 40px;
    width: 100%;
    max-width: 720px;
    padding: 0 24px;
  }
}

/* "As Seen In" logo bar — a plain typographic row (no external logo
   image files: real trademarked mastheads vary wildly in style/colour/
   aspect ratio, which would fight the "all same size, all black" brief
   and pull in third-party brand assets we don't hold rights to). Reuses
   the exact .founder-name/.press-outlet treatment (uppercase, tracked,
   var(--ink)) so it reads as one more instance of the site's existing
   "name row" pattern rather than a new one-off style. One entry per
   real outlet — Vogue Italia + Vogue Ukraine collapse to a single
   "Vogue" mark, both Corriere della Sera pieces collapse to one. */
/* Single centered, wrapping line of outlet names separated by a "•"
   bullet (added via ::after so the separator never needs to live in the
   markup or trail the last item) — same grid width as the other text
   blocks on the site, wraps at that width exactly like running prose
   would, just without the justify/hyphenation mechanic since these are
   names, not sentences. */
.press-logos {
  text-align: center;
  max-width: var(--max-w);
  width: 75%;
  margin: 0 auto 56px;
}
@media (min-width: 861px) {
  .press-logos { width: calc(100% / 7 * 5); }
}
.press-logo {
  font-family: var(--sans);
  font-style: normal;
  font-weight: 400;
  font-size: clamp(13px, 1vw, 15px);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink);
  white-space: nowrap;
  line-height: 2.4;
}
.press-logo:not(:last-child)::after {
  content: "\00a0\2022\00a0";
  color: var(--muted);
  letter-spacing: 0;
}
@media (max-width: 860px) {
  /* Same fix as .press-grid above: match the .text-block .prose mobile
     recipe (100% / max-width:720px / 24px side padding) instead of a
     bare width:100% with no inset, which sat flush to the container edge
     while the prose text next to it (and everything else on mobile)
     carries a 24px margin — another instance of the grid stepping out of
     the shared column. */
  .press-logos {
    width: 100%;
    max-width: 720px;
    padding: 0 24px;
    margin-bottom: 40px;
  }
  .press-logo { line-height: 2.2; }
}

/* B2B partner logos — real image marks this time (unlike .press-logos
   above, which deliberately avoids third-party logo files). Pre-cropped
   to a matching height already in media/, so a plain
   height:Npx/width:auto per image is enough for even sizing without any
   individual tweaking. Kept deliberately small/quiet ("dezente Größe")
   rather than matching the press-logos row's already-modest scale —
   this sits right under a full paragraph of copy, not as its own
   section. Same width-matching-the-prose recipe as everything else. */
/* Grid, not flex: the 5 logos are different intrinsic widths (Rocco Forte
   is noticeably wider than Lanza Baucina, say), so a centered flex row
   puts the visual midpoint of the *group* in the middle, not the middle
   *logo* — the heavier side pulls the whole row off-centre. 5 equal-width
   columns with each logo centred in its own column keeps column 3
   (Orient Express) dead centre on the row regardless of how wide any
   logo actually renders. */
.partner-logos {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  align-items: center;
  justify-items: center;
  column-gap: clamp(24px, 4vw, 48px);
  max-width: 75%;
  margin: 32px auto 0;
}
.partner-logos a {
  position: relative;
  display: inline-flex;
  align-items: center;
  color: inherit;
  text-decoration: none;
  transition: opacity 0.2s ease;
}
.partner-logos a:hover { opacity: 0.65; }
.partner-logos img {
  height: 30px;
  width: auto;
  object-fit: contain;
}
/* Partner name — hidden until the logo is hovered/focused, same
   uppercase sans treatment as the press outlet names so it reads as
   a caption rather than a bespoke tooltip. */
.partner-logo-name {
  position: absolute;
  top: 100%;
  left: 50%;
  transform: translate(-50%, 6px);
  margin-top: 8px;
  font-family: var(--sans);
  font-style: normal;
  font-weight: 400;
  font-size: clamp(10px, 0.85vw, 12px);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink);
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.2s ease, transform 0.2s ease;
}
.partner-logos a:hover .partner-logo-name,
.partner-logos a:focus-visible .partner-logo-name {
  opacity: 1;
  transform: translate(-50%, 0);
}
@media (max-width: 860px) {
  .partner-logos {
    max-width: 720px;
    width: 100%;
    padding: 0 24px;
    column-gap: 12px;
    margin-top: 28px;
  }
  /* Top-align the row instead of centering it: names wrap to a
     different number of lines per partner (e.g. "La Dolce Vita Orient
     Express" vs. "Blue"), so centering the whole column would push the
     logos themselves off a shared line depending on caption length.
     Top-aligning keeps every logo on the same axis regardless. */
  .partner-logos { align-items: start; }
  /* No real :hover on touch, so a tap would otherwise jump straight to
     the partner's site without the name ever being shown — names stay
     permanently visible below each logo on mobile instead. The extra
     padding on the link also grows the tappable area well past the
     22px-tall logo alone (closer to a comfortable touch target). */
  .partner-logos a {
    flex-direction: column;
    padding: 10px 6px;
  }
  .partner-logos img { height: 22px; }
  .partner-logo-name {
    position: static;
    display: block;
    opacity: 1;
    pointer-events: auto;
    transform: none;
    margin: 8px auto 0;
    max-width: 84px;
    white-space: normal;
    text-align: center;
    line-height: 1.3;
    font-size: 9px;
  }
  .partner-logos a:hover .partner-logo-name,
  .partner-logos a:focus-visible .partner-logo-name {
    transform: none;
  }
}

/* Outlet name doubles as the item's heading — same uppercase sans
   treatment as .founder-name for visual consistency between the two
   "meet the people / meet the press" grids. */
.press-outlet {
  font-family: var(--sans);
  font-style: normal;
  font-weight: 400;
  font-size: clamp(15px, 1.15vw, 18px);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink);
  margin: 0 0 6px;
}
.press-outlet-sub {
  text-transform: none;
  letter-spacing: 0.01em;
  color: var(--ink-soft);
}
.press-meta {
  font-family: var(--sans);
  font-size: clamp(12px, 0.9vw, 13px);
  letter-spacing: 0.03em;
  color: var(--ink-soft);
  opacity: 0.7;
  margin: 0 0 12px;
}
.press-item p:not(.press-meta) {
  font-family: var(--sans);
  font-size: clamp(14px, 1.05vw, 16px);
  line-height: 1.65;
  color: var(--ink-soft);
  margin: 0 0 14px;
}
.press-item .world-inline-link { font-size: clamp(13px, 0.95vw, 15px); }

/* Instagram link, centered directly on top of the Press Room's ambient
   video — same circular-icon-button footprint as .world-fullscreen-toggle
   etc., but positioned dead-center via absolute + transform instead of
   their corner placement, and white/outline rather than the dark
   video-overlay treatment so it reads as a light badge against the
   footage. */
.social-link {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  z-index: 3;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 52px;
  height: 52px;
  border-radius: 50%;
  background: var(--paper);
  border: 1px solid var(--rule);
  color: var(--muted);
  transition: color 0.2s ease, border-color 0.2s ease;
}
.social-link:hover { color: var(--ink); border-color: var(--ink); }
.social-link svg {
  width: 22px;
  height: 22px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* ---------- MOBILE-ONLY LINE BREAKS ---------- */
.mobile-br { display: none; }
@media (max-width: 860px) {
  .mobile-br { display: inline; }
}

/* ---------- REVEAL ANIMATION ---------- */
.reveal { opacity: 0; transform: translateY(14px); transition: opacity .8s ease, transform .8s ease; }
.reveal.visible { opacity: 1; transform: none; }

/* ---------- MOBILE ---------- */
@media (max-width: 860px) {
  /* Burger button is the visible nav trigger on mobile */
  .nav-toggle { display: block; }

  /* Inline nav becomes a fullscreen drop-down overlay */
  .main-nav {
    position: fixed;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 32px;
    background: var(--paper);
    padding: 0 8vw;
    z-index: 150;

    /* Hidden by default — slides in from the top */
    transform: translateY(-100%);
    transition: transform .4s cubic-bezier(.2,.7,.2,1);
    visibility: hidden;
  }
  .main-nav.open {
    transform: translateY(0);
    visibility: visible;
  }

  .main-nav a {
    font-family: var(--sans);
    font-size: 18px;
    letter-spacing: 0.4em;
    padding: 8px 4px;
    text-align: center;
  }

  /* Prevent body scroll while menu is open */
  body.nav-open { overflow: hidden; }
  .split { grid-template-columns: 1fr; gap: 24px; }
  .split .media { aspect-ratio: 4 / 5; }

  /* On mobile, copy stacks ABOVE the video — headline +
     paragraph introduce the visual that follows. */
  .split .copy  { order: 1; }
  .split .media { order: 2; }
  .portraits { grid-template-columns: 1fr 1fr; }
  section { padding: 50px 0; }

  /* On mobile, let headlines wrap to multiple lines so they can
     stay at a readable size instead of shrinking to fit. */
  .hero-headline,
  .split .copy h2,
  .portraits-title,
  .text-block h2,
  .page-intro h1 {
    white-space: normal;
    line-height: 1.2;
  }

  .hero-headline {
    top: 8%;
    /* Hero stays the largest title on the page */
    font-size: clamp(22px, 6.5vw, 34px);
  }
  /* Mobile-only: bring every headline-styled text on the page to the same
     size as the six main section titles (e.g. "We give your rituals a
     signature.", clamp(24px,4vw,38px)) — previously these sub-headlines
     ("By Appointment", "Get in Touch", "Our Trousseau Collections", "Media
     Enquiries", and the "Watch the MANIMA …" video captions below) rendered
     visibly smaller, which read as inconsistent headline sizing. Desktop is
     untouched — this is scoped to the existing mobile breakpoint only. */
  .split .copy h2,
  .portraits-title,
  .text-block h2,
  .world-film-heading {
    font-size: clamp(24px, 4vw, 38px);
  }
  .page-intro h1 {
    font-size: clamp(30px, 8.5vw, 44px);
  }

  /* On mobile we stack each split as copy-above-video,
     so the previous video needs visible breathing room
     before the next headline begins. */
  section.flush { padding-top: 48px; padding-bottom: 0; }

  /* Section-headline rhythm on mobile — all section titles
     ("What We Inherit", "Ancient Patterns", "Carolina & Piero",
     "The Creators…") sit at the same distance below the previous
     block, while the inner spacing (title → photos / paragraphs)
     stays tight. */
  .portraits-section { padding-top: 48px; padding-bottom: 0; }
  .portraits-title   { margin-bottom: 32px; }
  .text-block        { padding-top: 48px; padding-bottom: 80px; }
  .text-block h2     { margin-bottom: 28px; }
  .text-block.flush-top { padding-top: 0; margin-top: -88px; }

  /* Bug: Vision/Atelier/Trousseau/Concierge/Press's intro wrapper carries
     BOTH .world-intro and .text-block (<div class="world-intro text-block">).
     .world-intro's own padding-top:0 (desktop, line ~682) and this mobile
     .text-block rule's padding-top:48px have equal specificity, and
     .text-block comes later in the source, so on mobile it silently won —
     pushing the prose 48px below the heading instead of sitting close to
     it. Only padding-bottom had an ID-scoped override (line ~693) strong
     enough to win; padding-top didn't. Restore the intended tight gap. */
  #vision-film-intro .world-intro,
  #atelier-film-intro .world-intro,
  #trousseau .world-intro,
  #trousseau-copy .world-intro,
  #b2b .world-intro,
  #concierge .world-intro,
  #press .world-intro {
    padding-top: 0;
  }

  /* Drastic, uniform tightening of the headline-to-prose gap on mobile —
     same treatment already applied on desktop. The heading's own
     margin-bottom (18px, see .world-intro-heading above) is cut roughly
     in half here on top of the padding-top:0 fix above, so the paragraph
     sits close under the headline instead of floating a full line-height
     or more below it. Applies to every section using this intro pattern:
     World, Vision, Atelier, Trousseau, Concierge, Press. */
  .world-intro-heading {
    margin-bottom: 8px;
  }

  /* Desktop-only change: the 75% max-width above (matching the video/
     founders-grid width) would needlessly narrow the already-tight mobile
     column. Restore the original unconstrained-in-practice cap here. */
  .text-block .prose { max-width: 720px; }
}

/* Honeypot: a real-looking field that no person can see or tab into, so
   anything arriving with it filled in came from a script. Hidden by
   moving it out of view rather than with display:none — some bots skip
   display:none fields specifically because they know the trick. */
.hp-field {
  position: absolute !important;
  left: -9999px !important;
  width: 1px !important;
  height: 1px !important;
  opacity: 0 !important;
  pointer-events: none !important;
}

/* Avviso mostrato nel form quando l'invio automatico non riesce. Sostituisce
   la vecchia apertura del client di posta: dice cosa e' successo e lascia un
   indirizzo su cui scrivere, invece di far sparire il messaggio del cliente. */
.world-send-error {
  margin: 0.75rem 0 0;
  font-size: 0.85rem;
  line-height: 1.45;
  color: #b23b3b;
}
.world-send-error a {
  color: inherit;
  text-decoration: underline;
}
