/* ==========================================================================
   Layout — shell, bands, drifting backdrop, section dots, header, menu, footer
   ========================================================================== */

/* ---------- Containers ---------- */
.wrap {
  width: 100%;
  max-width: var(--wrap);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.wrap--wide { max-width: var(--wrap-wide); }
.wrap--read { max-width: var(--wrap-read); }

/* Keep clear of the section dots once they appear */
@media (min-width: 1240px) {
  .wrap { padding-right: calc(var(--gutter) + 2.75rem); }
}

.section { padding-block: var(--section-y); position: relative; }
.section--tight { padding-block: calc(var(--section-y) * 0.66); }

/* Two OPEN sections in a row share one gap rather than stacking two, so the
   second drops its top padding.

   Both sides have to be open for that to be right. A toned section needs its
   own top padding or its background sits clamped against its first line, and
   the section after a toned one needs its own too: the tone's bottom padding
   is inside the tone, above its border, so past that border there is nothing
   left. An earlier version only excluded the second side, which measured as
   0px between a visible band edge and the next section's first content. */
.section:not(.section--band):not(.section--feature)
  + .section:not(.section--band):not(.section--feature) { padding-top: 0; }

.section--ruled { border-top: 1px solid var(--line); padding-top: var(--section-y); }

/* Three grounds, used by composition rather than by alternation:
   open (nothing, the backdrop shows), band (a raised surface for dense
   content), feature (a deeper tone, once per page, for the emotional beat). */
.section--band {
  background: var(--band);
  border-block: 1px solid var(--line);
}

.section--feature {
  background: var(--feature);
  border-block: 1px solid var(--line);
}

/* A section holding only a call to action does not need a full stop of space
   under it; the footer supplies the close. */
.section--cta { padding-block: calc(var(--section-y) * 0.75); }

/* ---------- Drifting backdrop ----------
   Three very soft blooms on slow paths. Sits behind everything, shows only
   where a section is translucent, and is drawn at half resolution because
   nothing in it has an edge. */
.drift {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  opacity: var(--drift-opacity);
  transition: opacity 600ms var(--ease-out);
}

.drift canvas { width: 100%; height: 100%; }

.shell { position: relative; z-index: 1; }

/* ---------- Section dots (right margin) ----------
   One dot per section, marking where you are in the page. Quiet by default,
   the current one fills brass and names itself. */
.measure {
  position: fixed;
  top: 50%;
  right: clamp(0.85rem, 1.5vw, 1.6rem);
  transform: translateY(-50%);
  z-index: var(--z-rule);
  display: none;
}

@media (min-width: 1240px) {
  .measure { display: block; }
}

.measure__ticks {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 0.15rem;
}

.measure__tick {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 0.7rem;
  padding: 0.42rem 0;
  color: var(--ink-3);
  text-decoration: none;
  cursor: pointer;
}

.measure__tick::after {
  content: "";
  width: 8px;
  height: 8px;
  flex: 0 0 auto;
  border-radius: 50%;
  border: 1px solid var(--line-2);
  background: transparent;
  transition: background-color var(--d-hover) var(--ease-out),
              border-color var(--d-hover) var(--ease-out),
              transform var(--d-hover) var(--ease-out);
}

/* Sections already behind you read as quietly filled */
.measure__tick[data-passed="true"]::after {
  background: var(--line-2);
  border-color: transparent;
}

.measure__tick[aria-current="true"]::after {
  background: var(--brass);
  border-color: var(--brass);
  transform: scale(1.34);
}

.measure__tick span {
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  white-space: nowrap;
  opacity: 0;
  transform: translateX(6px);
  transition: opacity var(--d-hover) var(--ease-out), transform var(--d-hover) var(--ease-out);
}

.measure__tick[aria-current="true"] { color: var(--brass); }
.measure__tick[aria-current="true"] span { opacity: 1; transform: translateX(0); }

@media (hover: hover) and (pointer: fine) {
  .measure__tick:hover { color: var(--brass); }
  .measure__tick:hover::after { border-color: var(--brass); transform: scale(1.34); }
  .measure__tick:hover span { opacity: 1; transform: translateX(0); }
}

.measure__tick:focus-visible { outline-offset: 4px; }

/* Narrow screens get a hairline progress bar instead */
.progress-bar {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: 2px;
  z-index: var(--z-rule);
  pointer-events: none;
}

.progress-bar i {
  display: block;
  height: 100%;
  background: var(--brass);
  transform-origin: left center;
  transform: scaleX(0);
  transition: transform 120ms linear;
}

@media (min-width: 1240px) { .progress-bar { display: none; } }

/* ---------- Header ---------- */
.header {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: var(--z-header);
  padding: var(--s-4) var(--gutter) 0;
  /* No transition here on purpose. This used to animate padding-top, which is
     a layout property, on a fixed element carrying a backdrop-filter: every
     frame forced a re-layout and a full re-resolve of the blurred backdrop,
     which is what produced the rectangular flash over changing content. The
     same movement is done with a transform on the bar below, which the
     compositor handles without touching layout. */
}

.header__bar {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--s-3);
  max-width: var(--wrap-wide);
  margin-inline: auto;
  padding: 0.6rem 0.6rem 0.6rem 1.15rem;
  border-radius: var(--r-pill);
  background: var(--glass-bg);
  -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(1.9);
  backdrop-filter: blur(var(--glass-blur)) saturate(1.9);
  box-shadow: var(--shadow-1);
  transform: translate3d(0, 0, 0);
  transition: transform var(--d-panel) var(--ease-out),
              background-color var(--d-panel) var(--ease-out),
              box-shadow var(--d-panel) var(--ease-out);
}

/* Hairline via a masked gradient ring, never a flat 1px border */
.header__bar::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  padding: 1px;
  background: linear-gradient(160deg, var(--glass-edge-1), transparent 42%, var(--glass-edge-2));
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
  pointer-events: none;
}

@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .header__bar { background: var(--glass-bg-2); }
}

.header[data-scrolled="true"] .header__bar {
  transform: translate3d(0, -8px, 0);
  background: var(--glass-bg-2);
  box-shadow: var(--shadow-2);
}

/* The masked gradient ring repaints with the bar. Isolating the bar keeps that
   repaint inside its own layer instead of inviting the browser to re-composite
   the region behind it. */
.header__bar { isolation: isolate; }

/* Wordmark */
.wordmark {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  min-height: 2.75rem;
  text-decoration: none;
  flex: 0 1 auto;
  min-width: 0;
}

.wordmark__mark {
  width: 2rem;
  height: 2rem;
  flex: 0 0 auto;
  transition: transform 420ms var(--ease-out);
}

.wordmark__text {
  display: flex;
  flex-direction: column;
  line-height: 1;
}

.wordmark__name {
  font-family: var(--font-display);
  font-size: 1.0625rem;
  letter-spacing: -0.012em;
  white-space: nowrap;
}

.wordmark__role {
  font-size: 0.5625rem;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  /* ink-3 cannot reach 4.5:1 over the hero photograph at any glass opacity
     worth having. ink-2 clears it at 4.84 light and 7.61 dark. */
  color: var(--ink-2);
  margin-top: 0.22rem;
  white-space: nowrap;
}

/* The tracked-out role line is wider than the name, so on small phones the
   header keeps the name and drops the role. It still reads in the footer. */
@media (max-width: 519px) {
  .header .wordmark__role { display: none; }
  .header .wordmark__name { font-size: 1rem; }
}

@media (min-width: 900px) {
  .header__bar { gap: var(--s-5); }
}

@media (hover: hover) and (pointer: fine) {
  .wordmark:hover .wordmark__mark { transform: rotate(-8deg) scale(1.04); }
}

/* Desktop nav */
.nav {
  display: none;
  align-items: center;
  gap: 0.15rem;
  margin-left: auto;
}

@media (min-width: 900px) { .nav { display: flex; } }

.nav__link {
  position: relative;
  padding: 0.5rem 0.9rem;
  border-radius: var(--r-pill);
  font-size: var(--t--1);
  font-weight: 500;
  color: var(--ink-2);
  text-decoration: none;
  transition: color var(--d-hover) var(--ease-out), background-color var(--d-hover) var(--ease-out);
}

.nav__link::after {
  content: "";
  position: absolute;
  left: 0.9rem;
  right: 0.9rem;
  bottom: 0.34rem;
  height: 1px;
  background: var(--brass);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 260ms var(--ease-out);
}

@media (hover: hover) and (pointer: fine) {
  .nav__link:hover { color: var(--ink); }
  .nav__link:hover::after { transform: scaleX(1); }
}

.nav__link[aria-current="page"] { color: var(--ink); }
.nav__link[aria-current="page"]::after { transform: scaleX(1); background: var(--brass); }

.header__actions {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  margin-left: auto;
}

@media (min-width: 900px) { .header__actions { margin-left: var(--s-4); } }

/* Scoped to .header__bar on purpose: components.css loads after this file and
   its bare .btn rule would otherwise win the cascade and force the CTA back on
   at phone widths, where it collides with the wordmark. */
.header__bar .header__cta { display: none; }

@media (min-width: 1040px) {
  .header__bar .header__cta { display: inline-flex; }
}

/* ---------- Theme toggle ---------- */
.theme-toggle {
  position: relative;
  width: 2.5rem;
  height: 2.5rem;
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  border-radius: var(--r-pill);
  color: var(--ink-2);
  cursor: pointer;
  transition: color var(--d-hover) var(--ease-out),
              background-color var(--d-hover) var(--ease-out),
              transform var(--d-press) var(--ease-out);
}

.theme-toggle:active { transform: scale(0.94); }

@media (hover: hover) and (pointer: fine) {
  .theme-toggle:hover { color: var(--ink); background: var(--brass-wash); }
}

.theme-toggle svg { width: 1.125rem; height: 1.125rem; }

.theme-toggle__sun, .theme-toggle__moon {
  grid-area: 1 / 1;
  transition: opacity 300ms var(--ease-out), transform 420ms var(--ease-out);
}

.theme-toggle__moon { opacity: 0; transform: rotate(-70deg) scale(0.6); }
:root[data-theme="dark"] .theme-toggle__sun { opacity: 0; transform: rotate(70deg) scale(0.6); }
:root[data-theme="dark"] .theme-toggle__moon { opacity: 1; transform: rotate(0) scale(1); }

/* ---------- Hamburger ---------- */
.burger {
  position: relative;
  width: 2.5rem;
  height: 2.5rem;
  display: grid;
  place-items: center;
  border-radius: var(--r-pill);
  color: var(--ink);
  cursor: pointer;
  transition: background-color var(--d-hover) var(--ease-out), transform var(--d-press) var(--ease-out);
}

.burger:active { transform: scale(0.94); }
@media (min-width: 900px) { .burger { display: none; } }

.burger i {
  position: absolute;
  left: 0.7rem;
  width: 1.1rem;
  height: 1.5px;
  border-radius: 2px;
  background: currentColor;
  transition: transform 380ms var(--ease-drawer), opacity 180ms var(--ease-out);
}

.burger i:nth-child(1) { transform: translateY(-4px); }
.burger i:nth-child(2) { transform: translateY(4px); }

.burger[aria-expanded="true"] i:nth-child(1) { transform: translateY(0) rotate(45deg); }
.burger[aria-expanded="true"] i:nth-child(2) { transform: translateY(0) rotate(-45deg); }

/* ---------- Mobile menu overlay ---------- */
.menu {
  position: fixed;
  inset: 0;
  z-index: var(--z-overlay);
  display: grid;
  grid-template-rows: auto 1fr auto;
  padding: calc(var(--s-4) + 3.9rem) var(--gutter) var(--s-8);
  background: var(--glass-bg-2);
  -webkit-backdrop-filter: blur(28px) saturate(1.4);
  backdrop-filter: blur(28px) saturate(1.4);
  opacity: 0;
  visibility: hidden;
  transition: opacity var(--d-panel) var(--ease-out), visibility 0s linear var(--d-panel);
}

.menu[data-open="true"] {
  opacity: 1;
  visibility: visible;
  transition: opacity var(--d-panel) var(--ease-out), visibility 0s;
}

.menu__nav {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: var(--s-1);
}

.menu__link {
  display: flex;
  align-items: baseline;
  gap: var(--s-4);
  padding: var(--s-3) 0;
  font-family: var(--font-display);
  font-size: var(--t-4);
  line-height: 1.05;
  letter-spacing: -0.025em;
  text-decoration: none;
  border-bottom: 1px solid var(--line);
  opacity: 0;
  transform: translateY(1.5rem);
  transition: opacity 460ms var(--ease-out), transform 560ms var(--ease-out), color var(--d-hover) var(--ease-out);
}

.menu[data-open="true"] .menu__link { opacity: 1; transform: translateY(0); }
.menu[data-open="true"] .menu__link:nth-child(1) { transition-delay: 60ms; }
.menu[data-open="true"] .menu__link:nth-child(2) { transition-delay: 110ms; }
.menu[data-open="true"] .menu__link:nth-child(3) { transition-delay: 160ms; }
.menu[data-open="true"] .menu__link:nth-child(4) { transition-delay: 210ms; }

.menu__link i {
  font-family: var(--font-ui);
  font-style: normal;
  font-size: 0.625rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  color: var(--brass);
}

.menu__link[aria-current="page"] { color: var(--brass); }

.menu__foot {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-3) var(--s-5);
  align-items: center;
  opacity: 0;
  transform: translateY(1rem);
  transition: opacity 460ms var(--ease-out) 260ms, transform 560ms var(--ease-out) 260ms;
}

.menu[data-open="true"] .menu__foot { opacity: 1; transform: translateY(0); }

body[data-menu-open="true"] { overflow: hidden; }

/* ---------- Footer ---------- */
.footer {
  position: relative;
  padding-block: var(--s-7) var(--s-4);
  border-top: 1px solid var(--line);
  background: var(--paper-2);
}

.footer__top {
  display: grid;
  gap: var(--s-6);
  grid-template-columns: 1fr;
}

@media (min-width: 760px) {
  .footer__top { grid-template-columns: 1.6fr 1fr 1fr; gap: var(--s-6); }
}

.footer__head {
  font-family: var(--font-ui);
  font-size: 0.625rem;
  font-weight: 700;
  line-height: 1.4;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-bottom: var(--s-2);
}

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

/* Padded to a comfortable touch height rather than spaced with a gap, so the
   whole row is tappable instead of just the glyphs. */
.footer__links a {
  width: fit-content;
  padding-block: 0.45rem;
  font-size: var(--t--1);
  color: var(--ink-2);
  text-decoration: none;
  transition: color var(--d-hover) var(--ease-out);
}

@media (hover: hover) and (pointer: fine) {
  .footer__links a:hover { color: var(--brass); }
}

.footer__blurb {
  max-width: 34ch;
  margin-top: var(--s-3);
  font-size: var(--t--1);
  color: var(--ink-2);
}

.footer__bottom {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2) var(--s-5);
  align-items: baseline;
  justify-content: space-between;
  margin-top: var(--s-4);
  padding-top: var(--s-4);
  border-top: 1px solid var(--line);
  font-size: var(--t--2);
  color: var(--ink-3);
}

/* Notices are required but they are not reading material. They stay on the
   page and one tap away rather than taking a third of the footer. */
.footer__legal {
  margin-top: var(--s-5);
  padding-top: var(--s-4);
  border-top: 1px solid var(--line);
  font-size: var(--t--2);
  color: var(--ink-3);
}

.footer__legal summary {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  width: fit-content;
  min-height: 2rem;
  cursor: pointer;
  list-style: none;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  font-size: 0.5625rem;
  transition: color var(--d-hover) var(--ease-out);
}

.footer__legal summary::-webkit-details-marker { display: none; }

.footer__legal summary svg {
  width: 0.65rem;
  height: 0.65rem;
  transition: transform var(--d-panel) var(--ease-out);
}

.footer__legal[open] summary svg { transform: rotate(45deg); }

@media (hover: hover) and (pointer: fine) {
  .footer__legal summary:hover { color: var(--brass); }
}

.footer__legal p {
  max-width: 88ch;
  margin-top: var(--s-3);
  line-height: 1.65;
}

/* Locked build credit. Present on every page of every vendor site. */
.footer__watermark {
  font-size: var(--t--2);
  letter-spacing: 0.03em;
  color: var(--ink-3);
}

.footer__watermark a {
  color: var(--ink-2);
  text-decoration: none;
  border-bottom: 1px solid var(--line-brass);
  padding-bottom: 1px;
  transition: color var(--d-hover) var(--ease-out), border-color var(--d-hover) var(--ease-out);
}

@media (hover: hover) and (pointer: fine) {
  .footer__watermark a:hover { color: var(--brass); border-color: var(--brass); }
}

.footer__legal {
  max-width: 62ch;
  margin-top: var(--s-4);
  font-size: var(--t--2);
  line-height: 1.7;
  color: var(--ink-3);
}

.footer__legal p + p { margin-top: var(--s-2); }

/* ---------- Reveal on enter ---------- */
[data-reveal] {
  opacity: 0;
  transform: translateY(1.75rem);
  filter: blur(6px);
  transition: opacity var(--d-reveal) var(--ease-out),
              transform var(--d-reveal) var(--ease-out),
              filter var(--d-reveal) var(--ease-out);
  transition-delay: var(--reveal-delay, 0ms);
}

[data-reveal="in"] { opacity: 1; transform: none; filter: none; }

/* No-JS safety: never leave content invisible */
.no-js [data-reveal] { opacity: 1; transform: none; filter: none; }


/* ---------- Cursor ----------
   Only hides the native cursor once cursor.js has actually started, so a
   browser where it does not run is never left with no pointer at all. */
:root[data-cursor="on"],
:root[data-cursor="on"] a,
:root[data-cursor="on"] button,
:root[data-cursor="on"] summary,
:root[data-cursor="on"] .chip,
:root[data-cursor="on"] input,
:root[data-cursor="on"] textarea,
:root[data-cursor="on"] select { cursor: none; }

/* The map is a real interactive surface with its own cursors, so it keeps them */
:root[data-cursor="on"] .leaflet-container,
:root[data-cursor="on"] .leaflet-container * { cursor: auto; }

.cursor,
.cursor__glow {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 200;
  pointer-events: none;
  opacity: 0;
  transition: opacity 260ms var(--ease-out);
  will-change: transform;
}

.cursor[data-visible="true"],
.cursor__glow[data-visible="true"] { opacity: 1; }

.cursor {
  width: 30px;
  height: 30px;
  border-radius: 50%;
  border: 1.5px solid var(--cursor-ink, var(--ink));
  transition: opacity 260ms var(--ease-out),
              width 260ms var(--ease-out),
              height 260ms var(--ease-out),
              border-color 200ms var(--ease-out),
              background-color 200ms var(--ease-out);
}

/* Ground-aware ink. Sampled from whatever sits under the pointer, so the ring
   reads on a chalk panel and on a black photograph without inverting the
   brand colours the way a difference blend would. */
.cursor[data-tone="light"] { --cursor-ink: rgba(22, 19, 14, 0.62); }
.cursor[data-tone="dark"]  { --cursor-ink: rgba(244, 239, 229, 0.72); }

/* Over imagery the luminance is unknown, so it takes a ring that survives
   either: a light stroke with a dark halo behind it. */
.cursor[data-tone="media"] {
  --cursor-ink: rgba(255, 255, 255, 0.9);
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.35), inset 0 0 0 1px rgba(0, 0, 0, 0.2);
}

/* Over something clickable it opens up and picks up the brand colour */
.cursor[data-active="true"] {
  width: 52px;
  height: 52px;
  border-color: var(--brass);
  background: var(--brass-wash);
}

.cursor[data-press="true"] { width: 22px; height: 22px; }

.cursor__glow {
  width: 260px;
  height: 260px;
  border-radius: 50%;
  background: radial-gradient(circle, var(--brass-wash) 0%, transparent 62%);
  filter: blur(6px);
}

:root[data-theme="dark"] .cursor__glow {
  background: radial-gradient(circle, rgba(220, 172, 99, 0.16) 0%, transparent 62%);
}

@media (prefers-reduced-motion: reduce) {
  .cursor, .cursor__glow { display: none; }
}

@media (hover: none), (pointer: coarse) {
  .cursor, .cursor__glow { display: none; }
}
