/* src/styles/blank-9ed0a606.css */
:root {
  --ink: #242222;
  --ink-soft: #35353a;
  --gray: #515153;
  --gray-mid: #696969;
  --gray-light: #939393;
  --blue: #0071e3;
  --surface: #f5f5f7;
  --surface-alt: #f6f5f7;
  /* SF Pro first so all Latin text renders in Apple's system face; PingFang TC
     picks up the Chinese glyphs it doesn't cover. No webfont, nothing to load. */
  --sans: -apple-system, BlinkMacSystemFont, "SF Pro Text", "SF Pro Display",
    "Helvetica Neue", "PingFang TC", "Noto Sans TC", sans-serif;
  --display: -apple-system, BlinkMacSystemFont, "SF Pro Display", "SF Pro Text",
    "Helvetica Neue", "PingFang TC", "Noto Sans TC", sans-serif;
  /* Apple's standard ease + duration */
  --ease: cubic-bezier(.28, .11, .32, 1);
  --dur: .5s;
}

* { box-sizing: border-box; }

html {
  scroll-behavior: smooth;
  /* anchors clear the sticky nav */
  scroll-padding-top: 70px;
}

/* Apple-style reveal: content eases up as it enters the viewport.
   ponytail: the hidden state is scoped to .js-reveal, which reveal.js sets on
   <html>. If the script never runs (CMS strips it, JS disabled), nothing hides. */
.js-reveal .reveal {
  opacity: 0;
  transform: translateY(24px);
  transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.js-reveal .reveal.in { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .js-reveal .reveal, .js-reveal .reveal.in { opacity: 1; transform: none; transition: none; }
  * { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

body {
  margin: 0;
  font-family: var(--sans);
  color: var(--ink);
  background: #fff;
  -webkit-font-smoothing: antialiased;
}

img { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }
ul { margin: 0; padding: 0; list-style: none; }

/* ponytail: one container width for every section, per the design's 1111px column */
.wrap {
  width: min(1111px, calc(100% - 80px));
  margin-inline: auto;
  position: relative;
}

/* ---------- language ---------- */
/* Instatic allows exactly one site-wide layout, so it carries BOTH navs and
   BOTH footers; the page's own <main class="lang-en"> decides which shows.
   Locally each page only has its own, and these rules simply match nothing. */
body:has(main.lang-en) [data-lang="zh"] { display: none !important; }
body:not(:has(main.lang-en)) [data-lang="en"] { display: none !important; }

.nav-end { display: flex; align-items: center; gap: 22px; }
.lang-switch {
  font-size: 14px;
  font-weight: 500;
  color: var(--gray);
  padding: 4px 2px;
  transition: color .3s var(--ease);
}@media (hover: hover) {
.lang-switch:hover { color: var(--ink); }
}

/* Apple-style crossfade between pages. Cross-document view transitions are
   opt-in per document; browsers without support just navigate normally. */
@view-transition { navigation: auto; }
::view-transition-old(root) { animation: page-out .22s var(--ease) both; }
::view-transition-new(root) { animation: page-in .34s var(--ease) both; }
@keyframes page-out { to { opacity: 0; transform: scale(.994); } }
@keyframes page-in { from { opacity: 0; transform: scale(1.006); } }
@media (prefers-reduced-motion: reduce) {
  ::view-transition-old(root), ::view-transition-new(root) { animation: none; }
}

/* Headlines break where the eye expects, not wherever the line runs out —
   the English copy is long enough that "Security built / in" happens without
   it. Unsupported browsers just wrap as before. */
h1, h2, .lead, .sub, .plan-title, .card-title,
/* short standfirst copy balances like a headline */
.hero-text > p, .page-head .lede, .plan-audience, .plan-price, .form-intro p, .form-done p {
  text-wrap: balance;
}

/* Body copy is too long to balance (browsers cap it at a handful of lines
   anyway) — pretty only fixes the last line, so no orphan word is left alone. */
.manifesto-copy p, .feature-copy p, .project p, .detail-section p,
.card-note, .hint, .plan-cards .card-note, .contact-hint {
  text-wrap: pretty;
}

/* ---------- nav ---------- */
.nav {
  position: sticky;
  top: 0;
  z-index: 10;
  height: 70px;
  background: #fff;
  display: flex;
  align-items: center;
}
.nav-inner {
  width: min(1000px, calc(100% - 80px));
  margin-inline: auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 30px;
}
/* ponytail: checkbox toggle, no JS. NOT <details> — a closed <details> hides its
   own content, so the desktop navlinks disappeared (Safari always, Chromium once
   display:contents was dropped). The checkbox stays focusable for keyboard users. */
.menu-toggle {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}
.menu-btn { display: none; }
.nav-links {
  display: flex;
  gap: 30px;
  font-size: 14px;
  font-weight: 500;
  color: var(--gray);
}
.nav-links a { min-width: 80px; text-align: center; }
.nav-links a, .nav-contact, .footer-links a, .project .more, .back { transition: color .3s var(--ease), opacity .3s var(--ease); }@media (hover: hover) {
.nav-links a:hover, .nav-contact:hover, .footer-links a:hover { color: var(--ink); }
}
.nav-contact {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 14px;
  font-weight: 500;
  color: var(--gray);
}
.nav-contact img { width: 20px; height: 20px; }

/* ---------- buttons ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 11px 21px;
  border-radius: 100px;
  font-size: 16px;
  line-height: 22px;
  font-weight: 600;
}
.btn-primary { background: var(--blue); color: #fff; }@media (hover: hover) {
.btn-primary:hover { background: #0062c4; }
}
.btn { transition: background-color var(--dur) var(--ease), transform .25s var(--ease); }
.btn:active { transform: scale(.97); }
.btn-ghost { color: var(--ink-soft); font-weight: 500; }@media (hover: hover) {
.btn-ghost:hover { background: rgba(0, 0, 0, .05); }
}
.btn-arrow { padding-left: 18px; }
.arrow { width: 22px; height: 22px; transform: rotate(90deg); }
/* ponytail: the exported arrow is a black glyph — invert it on the blue button
   instead of shipping a second asset. */
.btn-primary .arrow { filter: brightness(0) invert(1); }

.menu-cta { display: none; }

/* ---------- hero ---------- */
.hero {
  position: relative;
  background: var(--surface);
  padding: 80px 0 0;
  text-align: center;
  overflow: hidden;
}
.hero-bg {
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
}
.puzzle {
  position: absolute;
  bottom: -177px;
  width: 503px;
  height: 426px;
  opacity: .1;
  object-fit: cover;
}
.puzzle-left { left: 200px; transform: rotate(-114.55deg); }
.puzzle-right { right: 200px; width: 484px; height: 410px; transform: rotate(160.57deg); }
.hero-text {
  position: relative;
  width: min(561px, calc(100% - 40px));
  margin-inline: auto;
}
.hero-text h1 {
  margin: 0;
  font-family: var(--display);
  font-size: 50px;
  font-weight: 600;
  line-height: 1.2;
}
.hero-text > p {
  margin: 20px 0 0;
  font-size: 20px;
  line-height: 26px;
  font-weight: 500;
  color: var(--gray-light);
}
.ctas {
  margin-top: 30px;
  display: flex;
  gap: 4px;
  justify-content: center;
  align-items: center;
  /* on a narrow phone the second button drops to its own line — without
     flex: none they would instead shrink and break their own label */
  flex-wrap: wrap;
}
.ctas .btn { flex: none; white-space: nowrap; }
/* ponytail: the design crops a 3456x2176 render into a 761x654 window —
   keep the crop as authored rather than letterboxing the full image. */
.hero-img {
  position: relative;
  width: 761px;
  max-width: 100%;
  aspect-ratio: 761 / 654;
  margin: 41px auto 0;
  overflow: hidden;
}
.hero-img img {
  position: absolute;
  left: -35.84%;
  top: -26.6%;
  width: 172.77%;
  height: 126.61%;
  max-width: none;
}

/* ---------- manifesto ---------- */
.manifesto { background: var(--surface-alt); padding: 150px 0; }
.manifesto-inner {
  display: flex;
  align-items: flex-end;
  gap: 100px;
}
.manifesto-copy { flex: 1; }
.manifesto-copy h2 {
  margin: 0 0 26px;
  font-family: var(--display);
  font-size: 48px;
  font-weight: 600;
  line-height: 1.2;
}
.manifesto-copy p { margin: 0; font-size: 18px; line-height: 25px; }
.signature {
  width: 156px;
  height: auto;
  flex: none;
  transform: rotate(-19.19deg);
}

/* ---------- feature sections ---------- */
/* Per Figma: sections 2 and 4 are flat #f6f5f7; sections 1 and 3 carry a gradient. */
.feature {
  background: var(--surface-alt);
  padding: 166px 0;
}
.feature-grad-gray { background: linear-gradient(180deg, #ededed 0%, #f2f7f8 100%); }
.feature-grad-blue { background: linear-gradient(180deg, #d0ecf6 0%, #f2f7f8 100%); }
.eyebrow {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 30px;
  margin: 0 0 100px;
  font-size: 20px;
  font-weight: 500;
}
.eyebrow::before, .eyebrow::after {
  content: "";
  width: 1px;
  height: 29.5px;
  background: rgba(36, 34, 34, .35);
}
.feature-grid {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 60px;
}
.feature-copy { width: 392px; flex: none; }
.feature-copy h2 {
  margin: 0 0 26px;
  font-family: var(--display);
  font-weight: 600;
  line-height: 1.2;
}
.feature-copy h2 .lead { display: block; font-size: 68px; }
.feature-copy h2 .sub { display: block; font-size: 48px; }
.feature-copy p { margin: 0; font-size: 16px; line-height: 25px; }
.feature-list { width: 450px; flex: none; }
.list-title { margin: 0 0 20px; font-size: 16px; }
.feature-list ul { display: flex; flex-direction: column; gap: 10px; }
.feature-list li {
  min-height: 82px;
  padding: 22px 23px 22px 20px;
  border-radius: 10px;
  background: #fff;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 30px;
}
.card-title {
  font-family: var(--display);
  font-size: 20px;
  font-weight: 600;
}
.card-note { font-size: 16px; color: var(--gray-mid); }
/* fixed note column: every note starts at the same x and ends on the card's
   right padding, instead of drifting with the title's width */
.feature-list .card-note { width: 220px; flex: none; text-align: left; }
.puzzle-red {
  position: absolute;
  right: -67px;
  top: 76px;
  width: 134px;
  height: auto;
  transform: rotate(12deg);
  pointer-events: none;
}

/* ---------- plan sections ---------- */
.plan { padding: 166px 0; }
/* One black field for both tiers; the only thing dividing them is a hairline
   pinned to the same column the content sits in. */
.plan-pro, .plan-prox { background: #000; }
.plan-prox { position: relative; }
.plan-prox::before {
  content: '';
  position: absolute;
  inset-block-start: 0;
  inset-inline-start: 50%;
  transform: translateX(-50%);
  width: min(1111px, calc(100% - 80px));   /* matches .wrap exactly */
  height: 2px;
  background: rgba(255, 255, 255, .14);
}
.plan-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 60px;
}
.plan-title {
  flex: 1;
  margin: 0;
  font-family: var(--display);
  font-size: 48px;
  font-weight: 600;
  line-height: 1.2;
  /* Champagne silver. The metallic read comes from the mid stop's lightness
     (~93%), not its hue — drop it to ~81% and it reads as a coloured word
     instead of a reflection. Warm here, iridescent cool on ProX: on one black
     field the temperature is what tells the two tiers apart. */
  background-image: linear-gradient(90deg, #e8cbaa 14%, #f1e8de 31.25%, #fff 49%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.plan-prox .plan-title {
  background-image: linear-gradient(90deg, #fa8fb0 14.4%, #b8dbff 31.25%, #fff 49%);
}
.plan-title span { display: block; }
.plan-intro { width: 460px; flex: none; color: #fff; }
.plan-intro p { margin: 0; font-size: 16px; line-height: 25px; }
.plan-audience, .plan-price {
  margin-bottom: 26px !important;
  font-family: var(--display);
  font-size: 20px !important;
  font-weight: 600;
  line-height: 1.4 !important;
}
/* pill above a plan title — deliberately not blue, the CTA owns the blue */
.plan-badge {
  margin: 0 0 22px;
  padding: 7px 16px;
  border-radius: 100px;
  background: rgba(255, 255, 255, .12);
  display: inline-block;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: .04em;
  color: #fff;
}
.plan .btn-primary { margin-top: 25px; }
.plan-cards {
  margin-top: 100px;
  display: flex;
  gap: 20px;
}
.plan-cards li {
  flex: 1;
  min-height: 158px;
  padding: 22px 23px 22px 20px;
  border: 1px solid #4f4f4f;
  border-radius: 10px;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: 20px;
}
.plan-cards .card-title { color: #e0e0e0; }
.plan-cards .card-note { color: #c2c2c2; }
/* The industries a plan suits — reference material, not a second pitch.
   Deliberately a different object from the cards above: one filled panel
   instead of three outlined cards, rows instead of columns. Same type sizes
   would still read as equal weight, so the shape has to differ, not just the
   colour. */
/* No panel fill: at any alpha subtle enough to stay subordinate it measured
   1.06x against these backgrounds — invisible. The silhouette does the work
   instead: full-width open rows against three enclosed cards. */
.plan-fit { margin-top: 56px; }
.plan-fit-title {
  margin: 0 0 4px;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: .08em;
  color: #8b8b93;
}
.plan-fit dl { margin: 0; }
.plan-fit dl > div {
  display: grid;
  grid-template-columns: 200px 1fr;
  gap: 30px;
  padding: 22px 0;
  border-top: 1px solid rgba(255, 255, 255, .1);
}
.plan-fit dl > div:last-child { padding-bottom: 0; }
.plan-fit dt { font-family: var(--display); font-size: 15px; font-weight: 600; color: #fff; }
.plan-fit dd { margin: 0; font-size: 14px; line-height: 1.7; color: #9a9aa2; }
@media (max-width: 860px) {
  .plan-fit { padding: 24px 22px; }
  .plan-fit dl > div { grid-template-columns: 1fr; gap: 7px; }
}

/* ---------- sub pages: one flat --surface canvas, no extra layers ---------- */
.page-surface { background: var(--surface); }
/* nav keeps its #fff fill everywhere */
.page-surface .footer,
.page-surface .closing { background: transparent; }
.page-surface .closing h2 {
  background-image: none;
  color: var(--ink);
}
.page-head {
  padding: 120px 0 70px;
  text-align: center;
}
.page-head h1 {
  margin: 0;
  font-family: var(--display);
  font-size: 50px;
  font-weight: 600;
  line-height: 1.2;
}
.page-head .lede {
  margin: 20px auto 0;
  max-width: 561px;
  font-size: 20px;
  line-height: 26px;
  font-weight: 500;
  color: var(--gray-light);
}

/* ---------- project cards ---------- */
/* ponytail: no card layer at all — image and text sit straight on --surface,
   the way the 留白 section does. Nothing to style but spacing and type. */
.projects { padding: 100px 0 140px; }
.project-list {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 90px 50px;
}
.project-shot {
  aspect-ratio: 3 / 2;
  border-radius: 10px;
  overflow: hidden;
  margin-bottom: 26px;
}
.project-shot img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform .4s ease;
}
.project-shot img { transition: transform .7s var(--ease); }@media (hover: hover) {
.project:hover .project-shot img { transform: scale(1.03); }
}
.project h2 {
  margin: 0 0 14px;
  font-family: var(--display);
  font-size: 24px;
  font-weight: 600;
  line-height: 1.4;
}
.project .client { margin: 0 0 10px; font-size: 14px; color: var(--gray-light); }
.project-metrics {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 24px;
  margin: 0 0 14px;
}
.project-metrics li {
  font-family: var(--display);
  font-size: 16px;
  font-weight: 600;
}
.project p { margin: 0 0 22px; font-size: 16px; line-height: 25px; color: var(--gray-mid); }
.project .more {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 16px;
  color: var(--blue);
}
.project .more .arrow { width: 18px; height: 18px; filter: none; }@media (hover: hover) {
.project .more:hover { text-decoration: underline; }
}

/* ---------- project detail ---------- */
.detail-head { padding: 70px 0 36px; }
.back {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-bottom: 28px;
  font-size: 16px;
  color: var(--gray);
}@media (hover: hover) {
.back:hover { color: var(--ink); }
}
.back .arrow { width: 18px; height: 18px; transform: rotate(-90deg); }
.detail-head .client { margin: 0 0 14px; font-size: 16px; color: var(--gray-light); }
.detail-head h1 {
  margin: 0;
  max-width: 900px;
  font-family: var(--display);
  font-size: 48px;
  font-weight: 600;
  line-height: 1.25;
}
.detail-hero {
  border-radius: 10px;
  overflow: hidden;
  margin-bottom: 56px;
}
.detail-hero img { width: 100%; height: auto; }
.detail-meta {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 30px;
  margin: 32px 0 0;
  padding: 24px 0;
  border-top: 1px solid #e1e1e4;
  border-bottom: 1px solid #e1e1e4;
}
.detail-meta dt { margin-bottom: 8px; font-size: 14px; color: var(--gray-light); }
.detail-meta dd {
  margin: 0;
  font-family: var(--display);
  font-size: 16px;
  font-weight: 600;
  line-height: 1.5;
}
.detail-body { padding: 8px 0 40px; }
.detail-section { margin-bottom: 48px; }
.detail-section h2 {
  margin: 0 0 20px;
  font-family: var(--display);
  font-size: 32px;
  font-weight: 600;
  line-height: 1.3;
}
.detail-section h3 {
  margin: 24px 0 8px;
  font-family: var(--display);
  font-size: 20px;
  font-weight: 600;
}
.detail-section p { margin: 0 0 14px; max-width: 760px; font-size: 18px; line-height: 30px; }
.detail-section ul { max-width: 760px; }
.detail-section ul li {
  position: relative;
  padding-left: 20px;
  margin-bottom: 10px;
  font-size: 18px;
  line-height: 30px;
}
.detail-section ul li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 13px;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--gray-light);
}
.quote {
  max-width: 760px;
  margin: 0;
  padding-left: 26px;
  border-left: 2px solid var(--ink);
}
.quote p {
  margin: 0 0 12px;
  font-family: var(--display);
  font-size: 24px;
  font-weight: 600;
  line-height: 1.5;
}
.quote footer { font-size: 16px; color: var(--gray-light); }

/* ---------- closing CTA ---------- */
.closing {
  background: #1d1d1f;
  padding: 120px 0;
  text-align: center;
}
.closing h2 {
  margin: 0 0 30px;
  font-family: var(--display);
  font-size: 48px;
  font-weight: 600;
  line-height: 1.2;
  /* Champagne silver. The metallic read comes from the mid stop's lightness
     (~93%), not its hue — drop it to ~81% and it reads as a coloured word
     instead of a reflection. Warm here, iridescent cool on ProX: on one black
     field the temperature is what tells the two tiers apart. */
  background-image: linear-gradient(90deg, #e8cbaa 14%, #f1e8de 31.25%, #fff 49%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.closing p {
  max-width: 640px;
  margin: 0 auto 30px;
  font-size: 18px;
  line-height: 28px;
  color: rgba(255, 255, 255, .65);
}

/* case-study screenshots, interleaved between sections */
.case-shot {
  margin: 0 0 48px;
  border-radius: 10px;
  overflow: hidden;
  background: var(--surface-alt);
}
.case-shot img { width: 100%; height: auto; }

/* ---------- 404 ---------- */
.notfound {
  min-height: calc(100vh - 70px - 240px);
  display: flex;
  align-items: center;
  text-align: center;
  padding: 120px 0;
}
.notfound .wrap { max-width: 620px; }
.nf-code {
  margin: 0 0 16px;
  font-family: var(--display);
  font-size: 20px;
  font-weight: 600;
  letter-spacing: .08em;
  color: var(--gray-light);
}
.notfound h1 {
  margin: 0;
  font-family: var(--display);
  font-size: 48px;
  font-weight: 600;
  line-height: 1.2;
}
.notfound .lede {
  margin: 20px 0 0;
  font-size: 20px;
  line-height: 26px;
  color: var(--gray-light);
}
.notfound .ctas { margin-top: 34px; }

/* ---------- footer ---------- */
.footer { background: #fff; padding: 142px 0 142px; }
/* ponytail: wrap instead of shrink — nothing in the footer may break a line or
   squash, so rows stack once they stop fitting. */
.footer-inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 32px 40px;
}
/* the logo is a fixed-ratio asset: never let flex compress it */
.logo { flex: none; }
.logo img { width: 116px; height: 27px; }
.footer-links {
  display: flex;
  flex-wrap: wrap;
  gap: 20px 60px;
  font-size: 16px;
}
.footer-links a, .copyright { white-space: nowrap; }
.footer-meta {
  display: flex;
  align-items: center;
  gap: 20px;
}
.ig {
  display: flex;
  color: #939393;
  transition: color .2s ease;
}@media (hover: hover) {
.ig:hover { color: var(--ink); }
}
.copyright {
  margin: 0;
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: 14px;
  letter-spacing: -.56px;
}

/* footer email — same monospace/size as the copyright it sits beside, so the
   two read as one meta line rather than a link bolted on */
.footer-mail {
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: 14px;
  letter-spacing: -.56px;
  color: var(--gray);
  white-space: nowrap;
  transition: color .3s var(--ease);
}@media (hover: hover) {
.footer-mail:hover { color: var(--ink); }
}

/* ---------- industrial landing (B2B) ---------- */
/* .hero without a hero-img: same --surface band, just needs its own
   bottom padding since the image normally supplies that weight */
.hero-no-image { padding-bottom: 100px; }
.hero-no-image .hero-text { width: min(700px, calc(100% - 40px)); }

.section-title {
  max-width: 720px;
  margin: 0 auto 20px;
  font-family: var(--display);
  font-size: 48px;
  font-weight: 600;
  line-height: 1.2;
  text-align: center;
}

.pain-grid {
  margin-top: 60px;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 20px;
}
.pain-grid li {
  padding: 28px 26px;
  border-radius: 10px;
  background: #fff;
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.pain-grid .card-note { width: auto; line-height: 25px; }

.solution-list { margin-top: 80px; display: flex; flex-direction: column; gap: 60px; }
.solution-item { display: flex; align-items: center; gap: 50px; }
/* placeholder fill until a real photo lands in solution-media img */
.solution-media {
  width: 280px;
  aspect-ratio: 4 / 3;
  flex: none;
  border-radius: 10px;
  overflow: hidden;
  background: var(--surface-alt);
}
.solution-media img { width: 100%; height: 100%; object-fit: cover; }
.solution-copy { flex: 1; min-width: 0; }
.solution-copy h3 {
  margin: 0 0 16px;
  font-family: var(--display);
  font-size: 32px;
  font-weight: 600;
  line-height: 1.3;
}
.solution-copy p { margin: 0; font-size: 18px; line-height: 30px; color: var(--gray-mid); }

/* ---------- responsive ---------- */
@media (max-width: 1100px) {
  /* nav collapses into a two-bar menu button */
  .menu-btn {
    display: block;
    order: 3;
    cursor: pointer;
    padding: 6px 0;
  }
  .menu-toggle:focus-visible + .menu-btn { outline: 2px solid var(--blue); outline-offset: 4px; }
  /* two 3px black bars, 4px apart */
  .bars {
    display: block;
    position: relative;
    width: 24px;
    height: 10px;
  }
  .bars::before, .bars::after {
    content: "";
    position: absolute;
    left: 0;
    width: 24px;
    height: 3px;
    background: #000;
    transition: transform .2s ease;
  }
  .bars::before { top: 0; }
  .bars::after { bottom: 0; }
  /* closing state: the same button becomes an X while the menu is open */
  .menu-toggle:checked + .menu-btn .bars::before { transform: translateY(3.5px) rotate(45deg); }
  .menu-toggle:checked + .menu-btn .bars::after { transform: translateY(-3.5px) rotate(-45deg); }
  .nav-links {
    display: none;
    position: absolute;
    top: 70px;
    left: 0;
    right: 0;
    flex-direction: column;
    align-items: center;
    gap: 0;
    padding: 16px 0 40px;
    background: #fff;
    box-shadow: 0 8px 24px rgba(0, 0, 0, .08);
  }
  .menu-toggle:checked ~ .nav-links { display: flex; }
  .nav-links a {
    min-width: 0;
    padding: 14px 20px;
    font-size: 16px;
  }
  /* the navbar's 聯絡我們 gives way to the hero CTA inside the menu */
  .nav-contact { display: none; }
  .nav-end { gap: 0; }   /* only the language button is left */
  /* space-between would spread the free space between the language and
     menu buttons; the auto margin absorbs it so the gap is exactly 20px */
  .nav-inner { gap: 20px; }
  .nav-end { margin-left: auto; }
  .menu-cta {
    display: inline-flex;
    margin-top: 60px;
    padding: 11px 21px;
  }@media (hover: hover) {
/* no hover state on touch breakpoints — it sticks after tapping */
  .menu-cta:hover { background: var(--blue); }
}

  /* eyebrow aligns with the start of the heading below it */
  .eyebrow { justify-content: flex-start; }
  .eyebrow::before, .eyebrow::after { display: none; }

  .feature-grid, .plan-head, .manifesto-inner {
    flex-direction: column;
    align-items: flex-start;
    gap: 40px;
  }
  .feature-copy, .feature-list, .plan-intro { width: 100%; }
  /* tablet keeps the 2-column grid, just scaled down */
  .project-list { gap: 60px 30px; }
  .project h2 { font-size: 20px; }
  .project-metrics li { font-size: 15px; }
  .project p { font-size: 15px; line-height: 24px; }
  .plan-cards { flex-wrap: wrap; }
  .plan-cards li { flex-basis: 280px; }
  .puzzle-red { right: 0; top: -40px; }
  .pain-grid { grid-template-columns: 1fr; }
}

@media (max-width: 860px) {
  .hero { padding-top: 50px; }
  .hero-text h1 { font-size: 36px; }
  .hero-text > p { font-size: 17px; line-height: 24px; }
  .feature, .plan, .manifesto { padding: 90px 0; }
  .eyebrow { margin-bottom: 60px; }
  .feature-copy h2 .lead { font-size: 44px; }
  .feature-copy h2 .sub, .manifesto-copy h2, .plan-title { font-size: 32px; }
  .feature-list li { flex-direction: column; align-items: flex-start; gap: 8px; }
  .feature-list .card-note { width: auto; }
  .page-head { padding: 60px 0 50px; }
  .page-head h1 { font-size: 32px; }
  .page-head .lede { font-size: 17px; line-height: 24px; }
  .detail-head { padding: 50px 0 30px; }
  .detail-head h1 { font-size: 28px; }
  .detail-hero { margin-bottom: 50px; }
  .detail-meta { grid-template-columns: 1fr 1fr; gap: 24px; margin: 30px 0 50px; }
  .detail-section { margin-bottom: 50px; }
  .case-shot { margin-bottom: 32px; }
  .detail-section h2 { font-size: 24px; }
  .detail-section p, .detail-section ul li { font-size: 16px; line-height: 27px; }
  .quote p { font-size: 20px; }
  .projects { padding: 50px 0 80px; }
  /* still 2 columns here — same proportions, just smaller */
  .project-list { gap: 40px 20px; }
  .project h2 { font-size: 17px; line-height: 1.45; margin-bottom: 10px; }
  .project .client { font-size: 13px; margin-bottom: 8px; }
  .project-metrics { gap: 4px 14px; margin-bottom: 10px; }
  .project-metrics li { font-size: 13px; }
  .project p { font-size: 14px; line-height: 22px; margin-bottom: 16px; }
  .project .more { font-size: 14px; }
  .project-shot { margin-bottom: 16px; }
  .closing { padding: 90px 0; }
  .closing h2 { font-size: 32px; }
  .closing p { font-size: 16px; line-height: 25px; }
  .hero-no-image { padding-bottom: 60px; }
  .section-title { font-size: 32px; }
  .pain-grid { gap: 16px; }
  .pain-grid li { padding: 22px 20px; }
  .solution-list { gap: 40px; }
  .solution-item { flex-direction: column; align-items: stretch; gap: 20px; }
  .solution-media { width: 100%; aspect-ratio: 3 / 2; }
  .solution-copy h3 { font-size: 24px; }
  .solution-copy p { font-size: 16px; line-height: 26px; }
  .notfound { padding: 80px 0; min-height: 60vh; }
  .notfound h1 { font-size: 32px; }
  .notfound .lede { font-size: 17px; line-height: 24px; }
  .footer { padding: 70px 0; }
  .footer-inner { flex-direction: column; align-items: flex-start; gap: 28px; }
  .footer-links { flex-direction: column; gap: 18px; }
  /* three items now (IG + email + copyright): at 375px they need 471px in a
     single row, so let the row wrap instead of overflowing */
  .footer-meta { flex-direction: row; flex-wrap: wrap; gap: 14px 18px; }
}

/* narrow phones: the 2-column案例 grid finally becomes one column */
@media (max-width: 360px) {
  .puzzle-red { width: 96px; }
}

/* The English eyebrows run two to three times wider than the Chinese ones —
   on a phone they reach the corner decoration and end up underneath it.
   Below this width there is no position left for the puzzle to occupy. */
@media (max-width: 500px) {
  main.lang-en .puzzle-red { display: none; }
}

@media (max-width: 560px) {
  .project-list { grid-template-columns: 1fr; gap: 50px; }
  .project h2 { font-size: 20px; }
  .project .client { font-size: 14px; }
  .project-metrics li { font-size: 15px; }
  .project p { font-size: 15px; line-height: 24px; }
  .project .more { font-size: 16px; }
}

/* ---------- onboarding form ---------- */
/* ponytail: one <form> with real fields; steps are just hidden fieldsets, so it
   still submits natively (Instatic turns it into a CMS form) with JS off. */
.form-page { padding: 90px 0 120px; overflow-x: clip; }
.form-layout { display: flex; align-items: flex-start; gap: 80px; }
.form-main { flex: 1; min-width: 0; }
/* just the artwork, no frame — fixed to the right edge at 2x, bleeding off-screen */
/* absolute, not fixed: it belongs to the page and scrolls away with it.
   .wrap is the positioned ancestor. */
.form-aside {
  position: absolute;
  top: 0;
  right: -9vw;
  /* portrait cut-out: size it by height so it never outgrows the viewport */
  height: 76vh;
  /* held at a fixed tilt — no animation, it should not drift back upright */
  transform: rotate(-4deg);
  pointer-events: none;
}
.form-aside img { width: auto; height: 100%; max-width: none; display: block; }
.form-intro { max-width: 620px; margin-bottom: 48px; }
.form-intro h1 {
  margin: 0 0 18px;
  font-family: var(--display);
  font-size: 48px;
  font-weight: 600;
  line-height: 1.15;
  letter-spacing: -.02em;
}
.form-intro p { margin: 0; font-size: 19px; line-height: 30px; color: var(--gray-mid); }
.form-meta {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 26px;
  padding: 7px 16px;
  border-radius: 100px;
  background: rgba(0, 113, 227, .1);
  color: var(--blue);
  font-size: 15px;
  font-weight: 600;
}
.form-meta .dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; }

.progress { max-width: 620px; margin-bottom: 40px; }
.progress-bar { height: 3px; border-radius: 3px; background: rgba(36, 34, 34, .1); overflow: hidden; }
.progress-bar span {
  display: block;
  height: 100%;
  width: 0;
  background: var(--blue);
  transition: width .45s var(--ease);
}
.progress-label { margin: 12px 0 0; font-size: 14px; color: var(--gray-light); }

.step {
  max-width: 620px;
  /* fieldset ships with a border and padding by default */
  border: 0;
  margin: 0;
  padding: 0;
  min-width: 0;
  scroll-margin-top: 110px;   /* clear the sticky nav */
}
/* .btn and .field set display, which beats the browser's [hidden] rule */
[hidden] { display: none !important; }
.step .q-num { display: block; margin-bottom: 12px; font-size: 14px; letter-spacing: .1em; color: var(--gray-light); }
.step h2 {
  margin: 0 0 8px;
  font-family: var(--display);
  font-size: 32px;
  font-weight: 600;
  line-height: 1.3;
}
.step .hint { margin: 0 0 28px; font-size: 16px; line-height: 25px; color: var(--gray-mid); }

.choices { display: flex; flex-direction: column; gap: 10px; }
.choice { position: relative; display: block; }
.choice input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.choice span {
  display: block;
  padding: 18px 22px;
  border: 1px solid #dcdcdf;
  border-radius: 12px;
  background: #fff;
  font-size: 17px;
  cursor: pointer;
  transition: border-color .2s var(--ease), background-color .2s var(--ease), transform .2s var(--ease);
}
.choice input:checked + span { border-color: var(--blue); background: rgba(0, 113, 227, .06); }
.choice input:focus-visible + span { outline: 2px solid var(--blue); outline-offset: 3px; }@media (hover: hover) {
.choice span:hover { border-color: var(--gray-light); }
}
.choice span:active { transform: scale(.995); }

.field { margin-top: 14px; }
.field label { display: block; margin-bottom: 8px; font-size: 15px; color: var(--gray-mid); }
.field input, .field textarea {
  width: 100%;
  padding: 15px 18px;
  border: 1px solid #dcdcdf;
  border-radius: 12px;
  background: #fff;
  font: inherit;
  font-size: 17px;
  color: var(--ink);
  transition: border-color .2s var(--ease);
}
.field textarea { min-height: 150px; resize: vertical; line-height: 26px; }
.field input:focus, .field textarea:focus { outline: none; border-color: var(--blue); }
.field input::placeholder, .field textarea::placeholder { color: #b6b6ba; }

.step-nav { display: flex; align-items: center; gap: 12px; margin-top: 34px; max-width: 620px; }
.btn-back {
  background: none;
  border: 0;
  padding: 11px 4px;
  font: inherit;
  font-size: 16px;
  color: var(--gray-mid);
  cursor: pointer;
}@media (hover: hover) {
.btn-back:hover { color: var(--ink); }
}
.btn-next { border: 0; cursor: pointer; font: inherit; }
.step-nav .spacer { flex: 1; }

.contact-group {
  max-width: 620px;
  margin-top: 30px;
  padding: 22px;
  border-radius: 16px;
  background: rgba(36, 34, 34, .03);
}
.contact-hint { margin: 0; font-size: 15px; color: var(--gray-mid); }
.field-error { margin: 14px 0 0; font-size: 15px; color: #d02b20; }

/* ---------- form success ---------- */
.done-page { padding: 150px 0 170px; text-align: center; }
.form-done { max-width: 560px; margin-inline: auto; }
.done-mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 64px;
  height: 64px;
  margin-bottom: 34px;
  border-radius: 50%;
  background: rgba(0, 113, 227, .1);
  color: var(--blue);
}
.form-done h1 {
  margin: 0 0 18px;
  font-family: var(--display);
  font-size: 42px;
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: -.02em;
}
.form-done h2 { font-family: var(--display); font-size: 36px; font-weight: 600; margin: 0 0 16px; }
.form-done p { font-size: 18px; line-height: 29px; color: var(--gray-mid); margin: 0; }
.form-done .done-note { margin-top: 10px; font-size: 16px; line-height: 26px; color: var(--gray-light); }
.form-done .ctas { margin-top: 36px; }

@media (max-width: 1400px) {
  .form-aside { height: 64vh; right: -5vw; }
}
/* tablet: still on the right, but the column has to give up room for it */
@media (max-width: 1180px) and (min-width: 861px) {
  .form-main { max-width: 58%; }
  .form-aside { width: 34vw; height: auto; right: -4vw; }
  .form-aside img { width: 100%; height: auto; }
}
/* mobile: out of the corner, into the flow below the form */
@media (max-width: 860px) {
  .form-layout { display: block; }
  /* same size as desktop — it is meant to bleed past both edges here */
  .form-aside {
    /* wider than the column on purpose — auto margins can't centre an
       over-wide box, so shift it by half its own width instead */
    position: relative;
    left: 50%;
    width: max-content;
    height: 76vh;
    margin: 40px 0 0;
    transform: translateX(-50%) rotate(-4deg);
  }
  .form-aside img { width: auto; height: 100%; }
  .form-page { padding: 50px 0 80px; }
  .form-intro h1 { font-size: 32px; }
  .form-intro p { font-size: 17px; line-height: 27px; }
  .step h2 { font-size: 24px; }
  .choice span { padding: 16px 18px; font-size: 16px; }
}



/* ---------- about page ---------- */
/* A numbers strip and a paired card row — the two content shapes the About
   page needed that the system had no component for. Everything else on that
   page reuses .manifesto / .feature-grid / .pain-grid / .quote as-is. */
.about-stats {
  margin-top: 66px;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 24px 20px;
}
.about-stat b {
  display: block;
  font-family: var(--display);
  font-size: 46px;
  font-weight: 600;
  line-height: 1.05;
  letter-spacing: -.03em;
}
.about-stat span {
  display: block;
  margin-top: 10px;
  font-size: 15px;
  line-height: 23px;
  color: var(--gray-mid);
}
/* two cards read better as halves than as two-thirds of a three-column grid */
.pain-grid.pair { grid-template-columns: repeat(2, 1fr); }

@media (max-width: 860px) {
  .about-stats { grid-template-columns: repeat(2, 1fr); margin-top: 46px; }
  .about-stat b { font-size: 34px; }
  .pain-grid.pair { grid-template-columns: 1fr; }
}

/* ============================================================
   Motion layer — milez.jp's motion vocabulary, without its stack.
   milez runs Next.js + Three.js + GSAP (1.28 MB of JS, 22 MB page)
   and drives scroll through WebGL canvases. What reads as "that
   motion" is really: masked line reveals, long expo easing, stagger,
   and stretch-swap hover labels. All of that is CSS.
   Paired with motion.js (~5 kB). Guarded by .js-motion so nothing
   hides when the script is absent, and fully off under
   prefers-reduced-motion.
   ============================================================ */
:root {
  /* long, decelerating curve. */
  --m-ease: cubic-bezier(.16, 1, .3, 1);
  --m-dur: 1.05s;
}

/* ---------- masked line reveal ---------- */
.js-motion .m-split .m-line {
  display: block;
  overflow: hidden;
  /* a mask clipping a rising line would otherwise shave descenders */
  padding-bottom: .12em;
  margin-bottom: -.12em;
}
.js-motion .m-split .m-line-i {
  display: block;
  transform: translateY(110%);
  transition: transform var(--m-dur) var(--m-ease);
  will-change: transform;
}
.js-motion .m-split.in .m-line-i { transform: none; }

/* ---------- block rise ---------- */
.js-motion .m-rise {
  opacity: 0;
  transform: translateY(22px);
  transition: opacity .9s var(--m-ease), transform .9s var(--m-ease);
}
.js-motion .m-rise.in { opacity: 1; transform: none; }

/* ---------- stretch-swap hover label ---------- */
/* Two stacked copies: the resting one leaves at -110%, the incoming one
   arrives from 100%, both stretched on y mid-flight. */
.m-swap-host {
  position: relative;
  overflow: hidden;
  vertical-align: bottom;
}
/* scope the inline-block to the link types that actually need it, so it can
   never override a display:none elsewhere in the system */
.nav-links a.m-swap-host,
.footer-links a.m-swap-host,
a.lang-switch.m-swap-host,
.project .more.m-swap-host,
.back.m-swap-host { display: inline-block; }
.m-swap-host.menu-cta, .m-swap-host.btn { display: none; }
.m-swap-a {
  display: block;
  transition: transform .55s var(--m-ease);
  transform-origin: center bottom;
}
/* the arriving copy is generated content, so the DOM keeps exactly one label */
.m-swap-host::after {
  content: attr(data-label);
  position: absolute;
  inset: 0;
  transform: translateY(100%) scaleY(2.2);
  transform-origin: center top;
  transition: transform .55s var(--m-ease);
}.m-swap-host:focus-visible .m-swap-a { transform: translateY(-110%) scaleY(2.2); }
@media (hover: hover) {
.m-swap-host:hover .m-swap-a { transform: translateY(-110%) scaleY(2.2); }
}.m-swap-host:focus-visible::after { transform: none; }
@media (hover: hover) {
.m-swap-host:hover::after { transform: none; }
}

/* ---------- lerped cursor ---------- */
.m-cursor {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 9999;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--ink);
  pointer-events: none;
  mix-blend-mode: difference;
  transition: width .4s var(--m-ease), height .4s var(--m-ease), opacity .3s;
}
.m-cursor.on { width: 44px; height: 44px; }
/* the OS pointer stays: removing it breaks accessibility and text selection */

/* ---------- scroll rail ---------- */
.m-rail {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 9998;
  width: 100%;
  height: 2px;
  background: var(--ink);
  transform: scaleX(0);
  transform-origin: 0 50%;
  pointer-events: none;
}

/* ---------- editorial typography (Plaid-Alpha direction) ---------- */
/* The reference's voice is geometric, not serif: tight display headings on a
   clean sans, and Latin eyebrows/labels set uppercase with heavy tracking.
   Montserrat would need a webfont; the *treatment* (caps + tracking + weight)
   carries the same feel on the system sans at 0 bytes, keeping the no-webfont
   rule and the 15 kB page. Chinese headings can't be uppercased, so only the
   Latin labels take caps; the CJK display type just tightens. */
.hero-text h1,
.page-head h1,
.detail-head h1,
.form-intro h1,
.form-done h1,
.notfound h1,
.manifesto-copy h2,
.section-title,
.sec-title,
.closing h2,
.feature-copy h2 .lead,
.feature-copy h2 .sub,
.plan-title,
.detail-section h2,
.project h2,
.about-stat b,
.quote p {
  font-family: var(--display);
  letter-spacing: -.022em;
  font-weight: 600;
}
.hero-text h1 { line-height: 1.22; }
.section-title { line-height: 1.28; }

/* uppercase, heavily tracked Latin labels — the Plaid-Alpha signature */
.eyebrow,
.sec-eyebrow,
.list-title,
.plan-fit-title,
.plan-badge,
.detail-meta dt,
.form-meta,
.project .client,
.back {
  text-transform: uppercase;
  letter-spacing: .16em;
  font-weight: 600;
}
/* CJK glyphs must not be letter-spaced into gappy rivers; only space runs of
   Latin/digits inside a label. Chinese-heavy labels opt out via [lang] below. */
.eyebrow:lang(zh), .list-title:lang(zh), .plan-fit-title:lang(zh) { letter-spacing: .04em; }

@media (prefers-reduced-motion: reduce) {
  .m-cursor, .m-rail { display: none; }
  .m-swap-a, .m-swap-host::after { transition: none; }
}


/* ---------- centred reading column: service + blog-article bodies ----------
   The 3 service pages (they carry a .page-head) and the 3 blog articles (their
   back-link points at /blog) get a narrow 700px centred body. Case-study detail
   pages share .detail-body but link back to /projects, so :has() leaves them at
   full width. [href^="/blog"] matches both the local /blog/ and the published
   /blog. .wrap is already margin-inline:auto, so capping its width centres it;
   on phones min(700px, 100% - 80px) keeps the existing narrow padding. */
main:has(.page-head) .detail-body .wrap,
main:has(.back[href^="/blog"]) .detail-body .wrap,
/* the blog article header (back link, date, title) matches its body's column */
main:has(.back[href^="/blog"]) .detail-head .wrap {
  max-width: 700px;
}

/* ============================================================
   Editorial report layout — adapted from the stateofaidesign.com
   register (numbered chapters, oversized display type, one
   viewport-pinned section), rebuilt on this site's own palette
   and content. That reference is a Framer build using JS-driven
   reveals; here the chapter numerals are CSS counters and the pin
   is plain position:sticky, so it costs no JS and cannot break
   if a script fails.
   ============================================================ */


/* ---------- oversized display type ---------- */
/* The reference runs a 120px H1. Chinese sets heavier than Latin at the same
   size, so this tops out lower and scales with the viewport instead. */
.hero-text h1 { font-size: clamp(38px, 6.4vw, 88px); }

/* ---------- viewport-pinned section ----------
   The reference's signature scroll move: a panel pins to the top of the
   viewport and holds while the page scrolls past it. Desktop only — on a
   phone the extra scroll height is a cost with no payoff. */
@media (min-width: 861px) {
  .manifesto {
    /* the hold: parent height beyond 100vh is how far the panel stays pinned */
    min-height: 190vh;
    padding-top: 0;
    padding-bottom: 0;
  }
  .manifesto-inner {
    position: sticky;
    top: 70px;                       /* clears the sticky nav */
    min-height: calc(100vh - 70px);
    display: flex;
    align-items: center;
  }
}


/* ============================================================
   Luminasphere-language homepage.
   Editorial mono grid: hairline rules, numbered rows, oversized
   statements, wide margins. Scoped to body:has(main.lu, main.lu-page) so every other page
   keeps the existing design system untouched.
   ponytail: the reference's identity is one uppercase mono webfont
   (Spline Sans Mono, 58 of its 60 text nodes). Loading a webfont
   contradicts this site's own "no webfont, nothing to load" pitch,
   so this uses the system mono — SF Mono on Apple, close cousin —
   at 0 kB, and lets Chinese fall through to PingFang, which has no
   uppercase and would ignore the transform anyway.
   ============================================================ */
body:has(main.lu, main.lu-page) {
  --lu-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas,
             "PingFang TC", "Noto Sans TC", monospace;
  --lu-line: rgba(36, 34, 34, .16);
  /* #8a8a8e was 2.5:1 on the disc faces — labels are 11px mono, so they need
     the full 4.5:1 against the darkest point they can land on (#dcdcde) */
  --lu-dim: #5e5f64;
  --lu-pad: clamp(20px, 4vw, 56px);
  --lu-orb: #ececee;     /* the flat face of each disc */
  --lu-ground: #f3f3f5;  /* what shows between them */

  /* Large discs with a lit rim, after the reference: flat light-grey faces,
     a white glow hugging each edge and falling off into the ground, one thin
     ring of light crossing them, all under a fine grain. Every stop sits past
     95% of the circle's radius, so each disc reads as a solid body with a
     glowing edge rather than a blur.
     All of it is background layers on one element — first listed is topmost —
     with fixed attachment, so the composition is framed by the viewport and
     the content scrolls across it. Sizes are vmax so the discs keep their
     proportion from phone to wide desktop. */
  background-color: var(--lu-ground);
  background-image: radial-gradient(60% 55% at 72% 62%, rgba(0,0,0,.05) 0%, rgba(0,0,0,0) 70%);
  background-attachment: fixed;
  background-repeat: no-repeat;
  /* the moving layers below sit at z-index -1; isolating body guarantees they
     paint above its ground and below its content, however html is styled */
  isolation: isolate;
}

/* ---------- lumina: the ground in motion ----------
   The discs and the ring used to be background layers on body. Animating a
   background layer repaints the whole viewport every frame; on a site that
   sells millisecond loads that is the wrong trade. So each moving part gets
   its own fixed layer and moves by transform only, which the compositor
   handles without repainting anything.
     disc A          drifts on its own, 5s
     ring + disc B   breathes about the ring's centre, on a different clock,
                     so the ring slides across disc A's rim rather than moving
                     in step with it
     grain           topmost and still: grain that travels reads as crawling */
body:has(main.lu, main.lu-page)::before,
body:has(main.lu, main.lu-page) main::before,
body:has(main.lu, main.lu-page)::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
}
body:has(main.lu, main.lu-page)::before {
  background: radial-gradient(circle 52vmax at 24% 4%, var(--lu-orb) 0 96.5%, #fff 99.2%, rgba(255,255,255,.55) 101.5%, rgba(255,255,255,0) 110%);
  background-repeat: no-repeat;
  will-change: transform;
  animation: lu-drift 5s ease-in-out infinite alternate;
}
body:has(main.lu, main.lu-page) main::before {
  background: radial-gradient(circle 34vmax at 74% 38%, rgba(255,255,255,0) 96.6%, rgba(255,255,255,.95) 98.6%, rgba(255,255,255,0) 101%), radial-gradient(circle 30vmax at 100% 100%, var(--lu-orb) 0 95.5%, #fff 98.8%, rgba(255,255,255,.5) 101.5%, rgba(255,255,255,0) 112%);
  background-repeat: no-repeat;
  transform-origin: 74% 38%;
  will-change: transform;
  animation: lu-breathe 3.5s ease-in-out infinite alternate;
}
body:has(main.lu, main.lu-page)::after {
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.82' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='.07'/%3E%3C/svg%3E");
}
@keyframes lu-drift {
  from { transform: translate3d(0, 0, 0) scale(1); }
  to   { transform: translate3d(-5vmax, 4vmax, 0) scale(1.06); }
}
@keyframes lu-breathe {
  from { transform: translate3d(0, 0, 0) scale(1); }
  to   { transform: translate3d(3vmax, -2vmax, 0) scale(1.12); }
}
@media (prefers-reduced-motion: reduce) {
  body:has(main.lu, main.lu-page)::before,
  body:has(main.lu, main.lu-page) main::before { animation: none; }
}
body:has(main.lu, main.lu-page) main.lu { background: transparent; color: var(--ink); }

/* every latin-only label rides the mono uppercase register */
/* .lu-tag is an <h2> where the section has a topic worth naming — the design
   is unchanged, the heading level is not decorative */
body:has(main.lu, main.lu-page) h2.lu-tag { margin: 0; }
body:has(main.lu, main.lu-page) .lu-tag, body:has(main.lu, main.lu-page) .lu-count, body:has(main.lu, main.lu-page) .lu-meta,
body:has(main.lu, main.lu-page) .lu-num, body:has(main.lu, main.lu-page) .lu-cat, body:has(main.lu, main.lu-page) .lu-post-meta,
body:has(main.lu, main.lu-page) .lu-eyebrow, body:has(main.lu, main.lu-page) .lu-case-more, body:has(main.lu, main.lu-page) .lu-more,
body:has(main.lu, main.lu-page) .lu-btn, body:has(main.lu, main.lu-page) .lu-link, body:has(main.lu, main.lu-page) .lu-srv-note {
  font-family: var(--lu-mono);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: .08em;
  text-transform: uppercase;
  line-height: 1.5;
}

/* ---------- section chrome ---------- */
/* longhands only: the `padding` shorthand here is (0,2,1) and silently
   reset every section's own padding-top/bottom, which is where this
   layout's whitespace lives */
body:has(main.lu, main.lu-page) .lu > section { padding-left: var(--lu-pad); padding-right: var(--lu-pad); }
body:has(main.lu, main.lu-page) .lu-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  padding: 14px 0;
  border-top: 1px solid var(--lu-line);
  margin-bottom: clamp(40px, 7vw, 96px);
}
body:has(main.lu, main.lu-page) .lu-count { color: var(--lu-dim); }

/* ---------- hero ---------- */
body:has(main.lu, main.lu-page) .lu-hero {
  min-height: calc(100vh - 70px);
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding-top: clamp(60px, 12vh, 140px);
  padding-bottom: clamp(48px, 9vh, 110px);
}
body:has(main.lu, main.lu-page) .lu-meta {
  display: flex;
  justify-content: space-between;
  margin: 0 0 auto;
  color: var(--lu-dim);
}
/* the kicker takes the gap the h1 used to hold above itself, and hands the
   h1 exactly 20px — the h1 keeps no top margin of its own */
body:has(main.lu, main.lu-page) .lu-kicker {
  margin: clamp(48px, 9vh, 120px) 0 20px;
  font-size: clamp(14px, 1.15vw, 16px);
  line-height: 1.6;
  color: var(--gray);
}
body:has(main.lu, main.lu-page) .lu-hero h1 {
  margin: 0;
  max-width: 20ch;
  font-family: var(--display);
  font-size: clamp(34px, 6.6vw, 94px);
  font-weight: 600;
  line-height: 1.02;
  letter-spacing: -.035em;
}
body:has(main.lu, main.lu-page) .lu-lede {
  margin: clamp(28px, 4vw, 48px) 0 0 auto;
  max-width: 52ch;
  font-size: clamp(14px, 1.15vw, 16px);
  line-height: 1.75;
  color: var(--gray);
}
body:has(main.lu, main.lu-page) .lu-hero-foot {
  display: flex;
  gap: 28px;
  align-items: center;
  margin-top: clamp(36px, 6vh, 72px);
  padding-top: 18px;
  border-top: 1px solid var(--lu-line);
}
body:has(main.lu, main.lu-page) .lu-btn, body:has(main.lu, main.lu-page) .lu-link, body:has(main.lu, main.lu-page) .lu-more, body:has(main.lu, main.lu-page) .lu-case-more {
  color: var(--ink);
  text-decoration: none;
  transition: opacity var(--dur) var(--ease);
}
body:has(main.lu, main.lu-page) .lu-btn { border-bottom: 1px solid var(--ink); padding-bottom: 3px; }
body:has(main.lu, main.lu-page) .lu-link { color: var(--lu-dim); }@media (hover: hover) {
body:has(main.lu, main.lu-page) a:hover { opacity: .55; }
}

/* ---------- works grid ---------- */
body:has(main.lu, main.lu-page) .lu-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  column-gap: clamp(24px, 5vw, 96px);
  row-gap: clamp(56px, 9vw, 130px);
}
/* the reference staggers its tiles rather than aligning them into rows */
body:has(main.lu, main.lu-page) .lu-case-1 { margin-top: clamp(40px, 8vw, 130px); }
body:has(main.lu, main.lu-page) .lu-case-shot { display: block; overflow: hidden; background: var(--surface); }
body:has(main.lu, main.lu-page) .lu-case-shot img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  filter: grayscale(1);
  transition: filter 700ms var(--ease), transform 700ms var(--ease);
}@media (hover: hover) {
body:has(main.lu, main.lu-page) .lu-case:hover .lu-case-shot img { filter: none; transform: scale(1.03); }
}
body:has(main.lu, main.lu-page) .lu-case-meta {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  margin-top: 16px;
  padding-top: 12px;
  border-top: 1px solid var(--lu-line);
}
body:has(main.lu, main.lu-page) .lu-client { margin: 0; font-size: 15px; font-weight: 500; }
body:has(main.lu, main.lu-page) .lu-cat { margin: 0; color: var(--lu-dim); }
body:has(main.lu, main.lu-page) .lu-case-desc {
  margin: 14px 0 0;
  font-size: 13px;
  line-height: 1.8;
  color: var(--gray);
  max-width: 46ch;
}
body:has(main.lu, main.lu-page) .lu-case-metrics {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 20px;
  margin: 14px 0 0;
  padding: 0;
  list-style: none;
  font-size: 12px;
  color: var(--lu-dim);
}
body:has(main.lu, main.lu-page) .lu-case-more { display: inline-block; margin-top: 16px; border-bottom: 1px solid var(--lu-line); padding-bottom: 3px; }
body:has(main.lu, main.lu-page) .lu-more {
  display: block;
  margin-top: clamp(48px, 7vw, 90px);
  padding-top: 16px;
  border-top: 1px solid var(--lu-line);
}

/* ---------- oversized statement ---------- */
body:has(main.lu, main.lu-page) .lu-statement { padding-top: clamp(90px, 15vw, 200px); padding-bottom: clamp(90px, 15vw, 200px); }
body:has(main.lu, main.lu-page) .lu-statement h2 {
  margin: 0;
  font-family: var(--display);
  font-size: clamp(30px, 5.4vw, 76px);
  font-weight: 600;
  line-height: 1.12;
  letter-spacing: -.03em;
  max-width: 18ch;
}
body:has(main.lu, main.lu-page) .lu-statement p {
  margin: clamp(28px, 4vw, 44px) 0 0 auto;
  max-width: 58ch;
  font-size: clamp(14px, 1.1vw, 16px);
  line-height: 1.85;
  color: var(--gray);
}
body:has(main.lu, main.lu-page) .lu-sign { display: block; margin: 40px 0 0 auto; }

/* ---------- clients ---------- */
body:has(main.lu, main.lu-page) .lu-client-list {
  margin: 0;
  padding: 0;
  list-style: none;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 0;
}
body:has(main.lu, main.lu-page) .lu-client-list li {
  padding: 16px 0;
  border-bottom: 1px solid var(--lu-line);
  font-size: clamp(15px, 1.6vw, 21px);
  font-weight: 500;
}
body:has(main.lu, main.lu-page) .lu-clients-note {
  margin: clamp(32px, 5vw, 56px) 0 0 auto;
  max-width: 46ch;
  font-size: 13px;
  line-height: 1.8;
  color: var(--gray);
}

/* ---------- numbered index rows ---------- */
body:has(main.lu, main.lu-page) .lu-index { padding-top: clamp(80px, 13vw, 170px); }
body:has(main.lu, main.lu-page) .lu-row {
  display: grid;
  grid-template-columns: 64px minmax(0, 1fr) minmax(0, 1.25fr);
  gap: clamp(16px, 3vw, 48px);
  padding: clamp(28px, 4vw, 48px) 0;
  border-top: 1px solid var(--lu-line);
}
body:has(main.lu, main.lu-page) .lu-num { color: var(--lu-dim); }
body:has(main.lu, main.lu-page) .lu-eyebrow { margin: 0 0 10px; color: var(--lu-dim); }
body:has(main.lu, main.lu-page) .lu-row-head h2 {
  margin: 0;
  font-family: var(--display);
  font-size: clamp(20px, 2.3vw, 32px);
  font-weight: 600;
  line-height: 1.24;
  letter-spacing: -.02em;
}
body:has(main.lu, main.lu-page) .lu-row-head h2 span { display: block; }
body:has(main.lu, main.lu-page) .lu-row-head h2 span + span { color: var(--lu-dim); font-weight: 500; }
body:has(main.lu, main.lu-page) .lu-row-body > p { margin: 0; font-size: 13px; line-height: 1.85; color: var(--gray); }
body:has(main.lu, main.lu-page) .lu-row-body ul { margin: 22px 0 0; padding: 0; list-style: none; }
body:has(main.lu, main.lu-page) .lu-row-body li {
  display: flex;
  gap: 16px;
  padding: 9px 0;
  border-top: 1px solid var(--lu-line);
  font-size: 12px;
  color: var(--lu-dim);
}
body:has(main.lu, main.lu-page) .lu-row-body li span { flex: none; min-width: 9em; color: var(--ink); }

/* ---------- services ---------- */
body:has(main.lu, main.lu-page) .lu-services { padding-top: clamp(80px, 13vw, 170px); }
body:has(main.lu, main.lu-page) .lu-srv {
  display: grid;
  grid-template-columns: 64px minmax(0, 1fr) auto;
  gap: clamp(16px, 3vw, 48px);
  align-items: baseline;
  padding: clamp(18px, 2.4vw, 28px) 0;
  border-top: 1px solid var(--lu-line);
  text-decoration: none;
  color: var(--ink);
}
body:has(main.lu, main.lu-page) .lu-srv:last-of-type { border-bottom: 1px solid var(--lu-line); }
body:has(main.lu, main.lu-page) .lu-srv-name { font-size: clamp(18px, 2.4vw, 34px); font-weight: 600; letter-spacing: -.02em; }
body:has(main.lu, main.lu-page) .lu-srv-note { color: var(--lu-dim); text-align: right; }

/* ---------- plans ---------- */
body:has(main.lu, main.lu-page) .lu-plan { padding-top: clamp(80px, 13vw, 170px); }
body:has(main.lu, main.lu-page) .lu-plan-head {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr);
  gap: clamp(24px, 5vw, 80px);
  align-items: start;
}
body:has(main.lu, main.lu-page) .lu-plan-head h2 {
  margin: 0;
  font-family: var(--display);
  font-size: clamp(30px, 4.6vw, 62px);
  font-weight: 600;
  line-height: 1.06;
  letter-spacing: -.03em;
}
body:has(main.lu, main.lu-page) .lu-plan-head h2 span { display: block; }
body:has(main.lu, main.lu-page) .lu-plan-head h2 span + span { font-size: .42em; color: var(--lu-dim); margin-top: 12px; letter-spacing: 0; }
body:has(main.lu, main.lu-page) .lu-price { margin: 0 0 14px; font-family: var(--lu-mono); font-size: 13px; letter-spacing: .04em; }
body:has(main.lu, main.lu-page) .lu-plan-intro > p:not(.lu-price) { margin: 0; font-size: 13px; line-height: 1.85; color: var(--gray); }
body:has(main.lu, main.lu-page) .lu-plan-intro .lu-btn { display: inline-block; margin-top: 24px; }
body:has(main.lu, main.lu-page) .lu-plan-cards { margin: clamp(44px, 7vw, 84px) 0 0; padding: 0; list-style: none; }
body:has(main.lu, main.lu-page) .lu-plan-cards li {
  display: grid;
  grid-template-columns: 64px minmax(0, 1fr) minmax(0, 1.6fr);
  gap: clamp(16px, 3vw, 48px);
  padding: clamp(16px, 2.2vw, 26px) 0;
  border-top: 1px solid var(--lu-line);
  align-items: baseline;
}
body:has(main.lu, main.lu-page) .lu-card-t { font-size: clamp(14px, 1.5vw, 19px); font-weight: 600; }
body:has(main.lu, main.lu-page) .lu-card-n { font-size: 13px; line-height: 1.8; color: var(--gray); }
body:has(main.lu, main.lu-page) .lu-fit { margin: clamp(40px, 6vw, 72px) 0 0; }
body:has(main.lu, main.lu-page) .lu-fit > div {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 2.2fr);
  gap: clamp(16px, 3vw, 48px);
  padding: 16px 0;
  border-top: 1px solid var(--lu-line);
}
body:has(main.lu, main.lu-page) .lu-fit dt { font-size: 13px; font-weight: 600; }
body:has(main.lu, main.lu-page) .lu-fit dd { margin: 0; font-size: 12px; line-height: 1.85; color: var(--lu-dim); }

/* ---------- journal ---------- */
body:has(main.lu, main.lu-page) .lu-journal { padding-top: clamp(80px, 13vw, 170px); }
body:has(main.lu, main.lu-page) .lu-post {
  display: grid;
  grid-template-columns: minmax(0, 200px) minmax(0, 1fr);
  gap: clamp(16px, 3vw, 48px);
  align-items: baseline;
  padding: clamp(20px, 2.6vw, 32px) 0;
  border-top: 1px solid var(--lu-line);
  text-decoration: none;
  color: var(--ink);
}
body:has(main.lu, main.lu-page) .lu-post-meta { color: var(--lu-dim); }
body:has(main.lu, main.lu-page) .lu-post-meta i { font-style: normal; padding: 0 6px; }
body:has(main.lu, main.lu-page) .lu-post-title { font-size: clamp(15px, 1.8vw, 25px); font-weight: 600; line-height: 1.4; letter-spacing: -.015em; }

/* ---------- lets talk ---------- */
body:has(main.lu, main.lu-page) .lu-talk {
  padding-top: clamp(100px, 16vw, 220px);
  padding-bottom: clamp(100px, 16vw, 220px);
  border-top: 1px solid var(--lu-line);
  margin-top: clamp(80px, 13vw, 170px);
}
body:has(main.lu, main.lu-page) .lu-talk .lu-tag { display: block; color: var(--lu-dim); margin: 0 0 clamp(28px, 4vw, 48px); }
body:has(main.lu, main.lu-page) .lu-talk h2 span { display: block; }
body:has(main.lu, main.lu-page) .lu-talk h2 {
  margin: 0;
  font-family: var(--display);
  font-size: clamp(30px, 5.6vw, 80px);
  font-weight: 600;
  line-height: 1.08;
  letter-spacing: -.03em;
}
body:has(main.lu, main.lu-page) .lu-talk-note { margin: clamp(24px, 3.5vw, 40px) 0 0; max-width: 48ch; font-size: 13px; line-height: 1.85; color: var(--gray); }
body:has(main.lu, main.lu-page) .lu-talk-btn {
  display: inline-flex;
  gap: 14px;
  align-items: center;
  margin-top: clamp(32px, 5vw, 56px);
  padding: 16px 30px;
  background: var(--ink);
  color: #fff;
  font-family: var(--lu-mono);
  font-size: 12px;
  letter-spacing: .08em;
  text-transform: uppercase;
  text-decoration: none;
}

/* ---------- nav + footer adopt the same register ---------- */
body:has(main.lu, main.lu-page) .nav { background: rgba(255, 255, 255, .82); backdrop-filter: blur(14px);
                border-bottom: 1px solid var(--lu-line); }
body:has(main.lu, main.lu-page) .nav-links a, body:has(main.lu, main.lu-page) .lang-switch, body:has(main.lu, main.lu-page) .nav-contact span,
body:has(main.lu, main.lu-page) .footer-links a, body:has(main.lu, main.lu-page) .copyright, body:has(main.lu, main.lu-page) .footer-mail {
  font-family: var(--lu-mono);
  font-size: 11px;
  letter-spacing: .08em;
  text-transform: uppercase;
}
body:has(main.lu, main.lu-page) .footer { background: transparent; border-top: 1px solid var(--lu-line); }

@media (max-width: 860px) {
  body:has(main.lu, main.lu-page) .lu-grid { grid-template-columns: 1fr; }
  body:has(main.lu, main.lu-page) .lu-case-1 { margin-top: 0; }
  body:has(main.lu, main.lu-page) .lu-row,
  body:has(main.lu, main.lu-page) .lu-plan-cards li { grid-template-columns: 40px minmax(0, 1fr); }
  body:has(main.lu, main.lu-page) .lu-row-body,
  body:has(main.lu, main.lu-page) .lu-plan-cards li .lu-card-n { grid-column: 2; }
  body:has(main.lu, main.lu-page) .lu-plan-head,
  body:has(main.lu, main.lu-page) .lu-fit > div,
  body:has(main.lu, main.lu-page) .lu-post { grid-template-columns: 1fr; }
  body:has(main.lu, main.lu-page) .lu-srv { grid-template-columns: 40px minmax(0, 1fr); }
  body:has(main.lu, main.lu-page) .lu-srv-note { grid-column: 2; text-align: left; }
  body:has(main.lu, main.lu-page) .lu-lede, body:has(main.lu, main.lu-page) .lu-statement p,
  body:has(main.lu, main.lu-page) .lu-clients-note, body:has(main.lu, main.lu-page) .lu-sign { margin-left: 0; }
}

/* ---------- lumina: interior pages ---------- */
body:has(main.lu, main.lu-page) .lu-hero-page { min-height: 0; padding-top: clamp(72px, 12vh, 150px); padding-bottom: clamp(48px, 8vh, 96px); }
body:has(main.lu, main.lu-page) .lu-hero-page h1 { margin-top: clamp(32px, 6vh, 72px); font-size: clamp(34px, 6vw, 82px); }
body:has(main.lu, main.lu-page) .lu-journal-page .lu-post:last-of-type { border-bottom: 1px solid var(--lu-line); }
body:has(main.lu, main.lu-page) .lu-post-body { display: block; }
body:has(main.lu, main.lu-page) .lu-post-desc {
  display: block;
  margin-top: 10px;
  max-width: 54ch;
  font-size: 13px;
  line-height: 1.8;
  color: var(--gray);
  font-weight: 400;
  letter-spacing: 0;
}

/* ---------- lumina: article pages ----------
   The prose column is left alone — 700px is the readable measure and the
   reason it was set. Only the chrome adopts the new register. */
body:has(main.lu, main.lu-page) .detail-head {
  padding: clamp(64px, 11vh, 132px) var(--lu-pad) clamp(36px, 6vh, 72px);
  background: transparent;
}
/* the reading column belongs to the articles; the base sheet already scopes
   it by the back link, and case studies need their full width for the
   hero and the interleaved screenshots */
body:has(main.lu-page) main:has(.back[href^="/blog"]) .detail-head .wrap { max-width: 700px; }
body:has(main.lu, main.lu-page) .detail-head .back,
body:has(main.lu, main.lu-page) .detail-head .client {
  font-family: var(--lu-mono);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--lu-dim);
}
body:has(main.lu, main.lu-page) .detail-head .back {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  color: var(--ink);
  text-decoration: none;
  padding-bottom: 3px;
  border-bottom: 1px solid var(--lu-line);
}
body:has(main.lu, main.lu-page) .detail-head .back img { display: none; }
body:has(main.lu, main.lu-page) .detail-head .back::before { content: "\2190"; }
body:has(main.lu, main.lu-page) .detail-head .client {
  margin: clamp(40px, 6vh, 72px) 0 0;
  padding-top: 14px;
  border-top: 1px solid var(--lu-line);
}
body:has(main.lu, main.lu-page) .detail-head h1 {
  margin: 18px 0 0;
  font-family: var(--display);
  font-size: clamp(26px, 3.6vw, 46px);
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: -.025em;
}
body:has(main.lu, main.lu-page) .detail-body { background: transparent; padding-bottom: clamp(60px, 10vh, 120px); }
body:has(main.lu, main.lu-page) .detail-section { border-top: 1px solid var(--lu-line); padding-top: clamp(24px, 3.4vw, 40px); }
body:has(main.lu, main.lu-page) .detail-section h2 {
  font-family: var(--display);
  font-size: clamp(19px, 2.1vw, 27px);
  font-weight: 600;
  letter-spacing: -.02em;
}
body:has(main.lu, main.lu-page) .detail-body p,
body:has(main.lu, main.lu-page) .detail-body li { font-size: 15px; line-height: 1.95; color: var(--gray); }
body:has(main.lu, main.lu-page) .detail-body strong { color: var(--ink); }
/* The closing block is authored for a near-black field: the h2 is painted by
   a champagne gradient clipped to the glyphs with `color: transparent`, and
   the copy is translucent white. Dropping the dark background alone left both
   invisible on white — so the whole block is restated here, not just its
   ground. */
body:has(main.lu, main.lu-page) .closing {
  background: transparent;
  border-top: 1px solid var(--lu-line);
  padding: clamp(80px, 13vw, 170px) var(--lu-pad);
  text-align: left;
}
body:has(main.lu, main.lu-page) .closing h2 {
  margin: 0;
  max-width: 20ch;
  font-size: clamp(28px, 4.4vw, 58px);
  line-height: 1.1;
  letter-spacing: -.03em;
  background-image: none;
  -webkit-background-clip: border-box;
  background-clip: border-box;
  /* fill follows the colour, so the accent block's white reaches the heading */
  -webkit-text-fill-color: currentColor;
  color: var(--ink);
}
body:has(main.lu, main.lu-page) .closing p {
  margin: clamp(20px, 3vw, 32px) 0 0;
  max-width: 48ch;
  font-size: 13px;
  line-height: 1.85;
  color: var(--gray);
}
/* the blue pill is the old system's CTA; here it takes the talk button's form */
body:has(main.lu, main.lu-page) .closing .btn {
  display: inline-flex;
  gap: 14px;
  align-items: center;
  margin-top: clamp(28px, 4.5vw, 48px);
  padding: 16px 30px;
  border-radius: 0;
  background: var(--ink);
  color: #fff;
  font-family: var(--lu-mono);
  font-size: 12px;
  letter-spacing: .08em;
  text-transform: uppercase;
}
body:has(main.lu, main.lu-page) .closing .btn .arrow { filter: invert(1); width: 16px; height: 16px; }

/* ---------- lumina: enquiry form ----------
   The markup is left exactly as it is — form.js drives .step / [data-step] /
   .choice and Instatic rebinds the fields by name, so this restyles and never
   restructures. */
body:has(main.lu, main.lu-page) .form-page {
  background: transparent;
  padding: clamp(72px, 12vh, 150px) var(--lu-pad) clamp(80px, 12vw, 160px);
}
body:has(main.lu, main.lu-page) .form-layout {
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(0, .85fr);
  gap: clamp(32px, 6vw, 96px);
  align-items: start;
  max-width: 1240px;
}
body:has(main.lu, main.lu-page) .form-meta,
body:has(main.lu, main.lu-page) .progress-label,
body:has(main.lu, main.lu-page) .btn-back {
  font-family: var(--lu-mono);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--lu-dim);
}
body:has(main.lu, main.lu-page) .form-meta .dot { background: var(--ink); }
body:has(main.lu, main.lu-page) .form-intro h1 {
  margin: 22px 0 0;
  font-family: var(--display);
  font-size: clamp(28px, 4vw, 52px);
  font-weight: 600;
  line-height: 1.12;
  letter-spacing: -.03em;
}
body:has(main.lu, main.lu-page) .form-intro p { font-size: 13px; line-height: 1.85; color: var(--gray); }
body:has(main.lu, main.lu-page) .progress-bar { height: 1px; background: var(--lu-line); border-radius: 0; }
body:has(main.lu, main.lu-page) .progress-bar span { background: var(--ink); border-radius: 0; }
body:has(main.lu, main.lu-page) .step { border-top: 1px solid var(--lu-line); padding-top: clamp(24px, 3.4vw, 40px); }
body:has(main.lu, main.lu-page) .step h2 {
  font-family: var(--display);
  font-size: clamp(19px, 2.1vw, 27px);
  font-weight: 600;
  letter-spacing: -.02em;
}
body:has(main.lu, main.lu-page) .hint,
body:has(main.lu, main.lu-page) .contact-hint { font-size: 12px; line-height: 1.8; color: var(--lu-dim); }

/* Choices become hairline rows rather than pills. The radio itself is
   visually hidden by the base stylesheet and `.choice span` is the real
   control, so the row lives on the span — styling .choice does nothing. */
body:has(main.lu, main.lu-page) .choices { display: block; }
body:has(main.lu, main.lu-page) .choice { display: block; padding: 0; }
body:has(main.lu, main.lu-page) .choice span {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 15px 2px;
  border: 0;
  border-top: 1px solid var(--lu-line);
  border-radius: 0;
  background: transparent;
  font-size: 14px;
  transition: padding-left var(--dur) var(--ease);
}
body:has(main.lu, main.lu-page) .choice:last-child span { border-bottom: 1px solid var(--lu-line); }
/* the hidden radio needs a visible stand-in */
body:has(main.lu, main.lu-page) .choice span::before {
  content: "";
  flex: none;
  width: 9px;
  height: 9px;
  border: 1px solid var(--lu-dim);
  border-radius: 50%;
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease);
}@media (hover: hover) {
body:has(main.lu, main.lu-page) .choice span:hover { padding-left: 10px; border-color: var(--lu-line); }
}
body:has(main.lu, main.lu-page) .choice input:checked + span { font-weight: 600; background: transparent; }
body:has(main.lu, main.lu-page) .choice input:checked + span::before {
  background: var(--ink);
  border-color: var(--ink);
}
body:has(main.lu, main.lu-page) .choice input:focus-visible + span {
  outline: 1px solid var(--ink);
  outline-offset: 2px;
}

body:has(main.lu, main.lu-page) .field label {
  font-family: var(--lu-mono);
  font-size: 11px;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--lu-dim);
}
body:has(main.lu, main.lu-page) .field input,
body:has(main.lu, main.lu-page) .field textarea {
  border: 0;
  border-bottom: 1px solid var(--lu-line);
  border-radius: 0;
  background: transparent;
  padding: 12px 2px;
  font-size: 15px;
}
body:has(main.lu, main.lu-page) .field input:focus,
body:has(main.lu, main.lu-page) .field textarea:focus {
  outline: none;
  border-bottom-color: var(--ink);
}
body:has(main.lu, main.lu-page) .step-nav { border-top: 1px solid var(--lu-line); padding-top: 24px; }
body:has(main.lu, main.lu-page) .step-nav .btn {
  border-radius: 0;
  background: var(--ink);
  color: #fff;
  padding: 15px 30px;
  font-family: var(--lu-mono);
  font-size: 12px;
  letter-spacing: .08em;
  text-transform: uppercase;
}
body:has(main.lu, main.lu-page) .form-aside img { filter: grayscale(1); }

@media (max-width: 860px) {
  body:has(main.lu, main.lu-page) .form-layout { grid-template-columns: 1fr; }
  body:has(main.lu, main.lu-page) .form-aside { display: none; }
}

/* ---------- lumina: case studies ----------
   Shares the article chrome; these add only what a case study has and an
   article does not — the fact table, the full-bleed hero and the interleaved
   screenshots. */
body:has(main.lu-page) .detail-head .client {
  font-family: var(--lu-mono);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--lu-dim);
}
body:has(main.lu-page) .detail-meta {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 0;
  margin: clamp(36px, 5vw, 64px) 0 0;
}
body:has(main.lu-page) .detail-meta > div {
  padding: 16px 0;
  border-top: 1px solid var(--lu-line);
}
body:has(main.lu-page) .detail-meta dt {
  font-family: var(--lu-mono);
  font-size: 11px;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--lu-dim);
  margin-bottom: 8px;
}
body:has(main.lu-page) .detail-meta dd {
  margin: 0;
  font-size: 13px;
  line-height: 1.7;
  max-width: 22ch;
}
/* The gutter is margin, not padding. As padding it sat inside the box, and
   .case-shot's --surface-alt panel showed through it as a pale band down each
   side of the image. As margin the image fills its box edge to edge. The panel
   colour and the 10px radius go too: the image is square-cornered, and a
   rounded box around it only adds a second edge. */
body:has(main.lu-page) .detail-hero,
body:has(main.lu-page) .case-shot {
  max-width: none;
  width: auto;
  padding: 0;
  margin-inline: var(--lu-pad);
  background: transparent;
  border-radius: 0;
}
/* The hero is its own .wrap, so the margin above replaces the wrap's gutter.
   The screenshots sit INSIDE the body's .wrap, which already takes 40px a side
   on a phone, so the same margin put them another --lu-pad further in —
   255px wide beside a 335px hero. They break back out to the hero's edge
   instead: (100cqw - 100%) / 2 is the wrap's own gutter, measured against the
   section rather than 100vw, which counts a Windows scrollbar and would
   overflow by it. */
body:has(main.lu-page) .detail-body { container-type: inline-size; }
body:has(main.lu-page) .detail-body .case-shot {
  margin-inline: calc(var(--lu-pad) - (100cqw - 100%) / 2);
}
body:has(main.lu-page) .detail-hero img,
body:has(main.lu-page) .case-shot img {
  width: 100%;
  border-radius: 0;
  filter: grayscale(1);
  transition: filter 700ms var(--ease);
}@media (hover: hover) {
body:has(main.lu-page) .detail-hero:hover img, body:has(main.lu-page) .case-shot:hover img { filter: none; }
}
body:has(main.lu-page) .quote {
  border: 0;
  border-top: 1px solid var(--lu-line);
  border-bottom: 1px solid var(--lu-line);
  border-radius: 0;
  background: transparent;
  padding: clamp(28px, 4vw, 44px) 0;
  font-family: var(--display);
  font-size: clamp(18px, 2.2vw, 28px);
  font-weight: 600;
  line-height: 1.4;
  letter-spacing: -.02em;
}

/* ---------- lumina: case studies, doubled rules ----------
   Two hairlines were stacking about 30px apart and reading as a stray empty
   band. Both are the same mistake: a border I added on top of one the page
   already had. */
/* The base sheet draws a rule on the table itself, and every cell already
   draws its own. Drop the table's: the cells' rules are the ones that have to
   stay, because this is an auto-fit grid and a rule is needed above each
   wrapped row, not just the first. */
body:has(main.lu-page) .detail-meta { border-top: 0; }
/* a section that holds only the pull quote lets the quote draw the line */
body:has(main.lu-page) .detail-section:has(> .quote) {
  border-top: 0;
  padding-top: 0;
}

/* ---------- lumina: article tables ----------
   A price table is the thing readers scan for, so it gets hairlines and room
   rather than a boxed grid. Wrapped for its own horizontal scroll: the page
   body must never scroll sideways on a phone. */
body:has(main.lu, main.lu-page) .table-wrap {
  overflow-x: auto;
  margin: clamp(22px, 3vw, 32px) 0;
  -webkit-overflow-scrolling: touch;
}
body:has(main.lu, main.lu-page) .table-wrap table {
  width: 100%;
  min-width: 520px;
  border-collapse: collapse;
  font-size: 13px;
}
body:has(main.lu, main.lu-page) .table-wrap th {
  font-family: var(--lu-mono);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--lu-dim);
  text-align: left;
  padding: 12px 14px 12px 0;
  border-bottom: 1px solid var(--ink);
  white-space: nowrap;
}
body:has(main.lu, main.lu-page) .table-wrap td {
  padding: 13px 14px 13px 0;
  border-bottom: 1px solid var(--lu-line);
  line-height: 1.65;
  vertical-align: top;
  color: var(--gray);
}
body:has(main.lu, main.lu-page) .table-wrap td:first-child { color: var(--ink); font-weight: 500; white-space: nowrap; }
body:has(main.lu, main.lu-page) .table-wrap strong { color: var(--ink); }

/* ---------- project images: colour where there is no hover ----------
   Greyscale-until-hover is a desktop idea. A touch screen has no hover, so on
   phones and tablets the images would only ever be seen grey. Both conditions:
   hover:none catches every touch device whatever its width (large iPads
   included); the width catches tablets with a trackpad and narrow windows.
   Same selectors as the rules they override, placed after them, so they win
   on order at equal specificity. The form illustration is not a project and
   keeps its treatment. */
@media (hover: none), (max-width: 1024px) {
  body:has(main.lu, main.lu-page) .lu-case-shot img,
  body:has(main.lu-page) .detail-hero img,
  body:has(main.lu-page) .case-shot img { filter: none; }
}

/* the aspen tokens, readable on every page */
:root {
  --a-ink: #232323;
  --a-grey: #d9d9d9;
  --a-ground: #e0e0e0;
  --a-pink: #151cc5;
  --a-on-pink: #fff;
  --a-pink-hi: #8c91ff;
  --a-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "PingFang TC", monospace;
  --a-row: 420px;
  --a-pad: 20px;
  --a-top: 60px;
  --a-ease: cubic-bezier(.16, 1, .3, 1);
  --a-arrow: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M.75 8h14.1M7.8.9 14.9 8l-7.1 7.1' fill='none' stroke='%23000' stroke-width='1.5'/%3E%3C/svg%3E");
}
/* ============================================================
   aspen 1:1 — the homepage (main.aspen), rebuilt on aspensearch.com's
   measured spec at 1440px: a 60px header, 420px rows on a two-column
   grid whose halves split into 358px quarters, 1px #232323 rules, cells
   in white / #d9d9d9 / #232323 / #a1ffcb, dithered windows on #e0e0e0.
   Type: one weight (450) at -4% tracking — 12.55vw display words,
   22.09cqw slogan, 7.44vw section heads, 2.63vw (37.9px) titles,
   2.15vw (31px) about copy, then 24 / 16 / 14 / 12px.
   Motion lives in aspen.js (scrubs, switchers, clock, inertia) and
   dither.js (canvases). Revert = drop this block and those two files.
   ============================================================ */
body:has(main.aspen) {
  --a-ink: #232323;
  --a-grey: #d9d9d9;
  --a-ground: #e0e0e0;
  --a-pink: #151cc5;
  --a-on-pink: #fff;
  --a-pink-hi: #8c91ff;
  --a-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "PingFang TC", monospace;
  --a-row: 420px;
  --a-pad: 20px;
  --a-top: 60px;
  --a-ease: cubic-bezier(.16, 1, .3, 1);
  --a-arrow: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M.75 8h14.1M7.8.9 14.9 8l-7.1 7.1' fill='none' stroke='%23000' stroke-width='1.5'/%3E%3C/svg%3E");
  background: #fff;
  color: var(--a-ink);
}
/* Aspen has neither a custom cursor nor a progress rail; the shared footer is
   replaced by the page's own (the last section of main) */
body:has(main.aspen) .m-cursor,
body:has(main.aspen) .m-rail,
body:has(main.aspen) .footer { display: none; }

main.aspen { display: block; overflow-x: clip; background: #fff; color: var(--a-ink); font-weight: 450; letter-spacing: -.04em; }
main.aspen h1, main.aspen h2, main.aspen h3, main.aspen p, main.aspen ul, main.aspen ol,
main.aspen dl, main.aspen dd, main.aspen blockquote { margin: 0; padding: 0; font-size: inherit; font-weight: inherit; letter-spacing: inherit; }
main.aspen ul, main.aspen ol { list-style: none; }
main.aspen a { color: inherit; text-decoration: none; }
main.aspen img { display: block; max-width: none; }
main.aspen button { font: inherit; letter-spacing: inherit; color: inherit; }
main.aspen section { position: relative; }

/* ---------- type ---------- */
.aspen .a-display { font-size: 12.55vw; line-height: .8; }
.aspen .a-h107 { display: flex; flex-direction: column; font-size: 7.44vw; line-height: .82; text-transform: uppercase; }
.aspen .a-h107 > span { display: block; overflow: hidden; }
.aspen .a-h107 > span > span { display: block; }
.aspen .a-h107 .a-ind { padding-left: 34%; }
.aspen .a-t38 { font-size: 2.63vw; line-height: 1.1; text-wrap: balance; }
.aspen .a-t31 { font-size: 2.15vw; line-height: 1.1; letter-spacing: -.02em; }
.aspen .a-t24 { font-size: 24px; line-height: 1.1; letter-spacing: -.02em; }
.aspen .a-t16 { font-size: 16px; line-height: 1.3; }
.aspen .a-t38 > span, .aspen .a-t24 > span.a-l { display: block; }
.aspen .a-mono, .aspen .a-label {
  font-family: var(--a-mono);
  font-size: 12px;
  font-weight: 400;
  line-height: 1.1;
  letter-spacing: -.04em;
  text-transform: uppercase;
}
.aspen .a-label { display: flex; align-items: center; gap: 12px; }
.aspen .a-label::before { content: ""; flex: none; width: 8px; height: 8px; background: currentColor; }
.aspen .a-dim { opacity: .65; }

/* ---------- cells ---------- */
.aspen .a-row, .aspen .a-grid2 { display: grid; grid-template-columns: 1fr 1fr; }
.aspen .a-row { height: var(--a-row); }
.aspen .a-cell, .aspen .a-q { position: relative; min-width: 0; }
.aspen .a-split { display: grid; grid-template-columns: 1fr 1fr; min-width: 0; }
.aspen .a-pad { padding: var(--a-pad); }
.aspen .a-white { background: #fff; }
.aspen .a-grey { background: var(--a-grey); }
.aspen .a-ink { background: var(--a-ink); color: #fff; }
.aspen .a-mint { background: var(--a-pink); color: var(--a-on-pink); }
.aspen .a-br { border-right: 1px solid var(--a-ink); }
.aspen .a-bb { border-bottom: 1px solid var(--a-ink); }
.aspen .a-bt { border-top: 1px solid var(--a-ink); }

/* dithered windows: dither.js draws the turning mark; without WebGL the flat
   mark stays as the cell's background. The canvas holds one pixel per 3px dot,
   so it is scaled up hard-edged. */
/* any page's dithered cell (the homepage's, the enquiry form's panel) */
[data-dither] {
  overflow: hidden;
  background: var(--a-ground) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='45 45 90 90'%3E%3Cpath fill='%23232323' fill-rule='evenodd' d='M132.188 45C133.741 45 135 46.2592 135 47.8125V132.188C135 133.741 133.741 135 132.188 135H47.8125C46.2592 135 45 133.741 45 132.188V47.8125C45 46.2592 46.2592 45 47.8125 45H132.188ZM89.9918 48.5925C67.1283 48.5933 48.5933 67.1283 48.5925 89.9918C48.5925 112.856 67.1278 131.393 89.9918 131.394C112.856 131.394 131.394 112.856 131.394 89.9918C131.393 67.1278 112.856 48.5925 89.9918 48.5925Z'/%3E%3C/svg%3E") center / min(50%, 50vh) no-repeat;
}
[data-dither] canvas { position: absolute; inset: 0; display: block; width: 100%; height: 100%; image-rendering: pixelated; }
.aspen .a-dither { position: absolute; inset: 0; z-index: 0; }
.aspen .a-winbox { position: relative; }

/* ---------- buttons: ink block, mono label, arrow; mint sweeps in ---------- */
.aspen .a-btn {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  display: inline-flex;
  align-items: center;
  justify-content: space-between;
  width: 200px;
  height: 36px;
  padding: 0 12px;
  background: var(--a-ink);
  color: #fff;
  font-family: var(--a-mono);
  font-size: 12px;
  font-weight: 400;
  line-height: 1.1;
  text-transform: uppercase;
  transition: color .8s var(--a-ease);
}
.aspen .a-btn::after, .aspen .a-arrow {
  content: "";
  flex: none;
  width: 12px;
  height: 12px;
  background: currentColor;
  -webkit-mask: var(--a-arrow) center / contain no-repeat;
  mask: var(--a-arrow) center / contain no-repeat;
}
.aspen .a-btn::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(--a-pink);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform .8s var(--a-ease);
}@media (hover: hover) {
.aspen .a-btn:hover { color: var(--a-on-pink); }
}@media (hover: hover) {
.aspen .a-btn:hover::before { transform: none; }
}
.aspen .a-btn-full { width: 100%; }
.aspen .a-arrows { display: grid; grid-template-columns: 1fr 1fr; height: 60px; }
.aspen .a-arrows button {
  position: relative;
  display: grid;
  place-items: center;
  border: 0;
  background: #fff;
  cursor: pointer;
  transition: background-color .3s var(--ease);
}
.aspen .a-arrows button + button { border-left: 1px solid var(--a-ink); }
.aspen .a-arrows button { isolation: isolate; overflow: hidden; transition: color .8s var(--a-ease); }
.aspen .a-arrows button::before { content: ""; position: absolute; inset: 0; z-index: -1; background: var(--a-ink); transform: scaleX(0); transform-origin: left; transition: transform .8s var(--a-ease); }@media (hover: hover) {
.aspen .a-arrows button:hover { color: #fff; }
}@media (hover: hover) {
.aspen .a-arrows button:hover::before { transform: none; }
}
.aspen .a-arrows .a-arrow { width: 16px; height: 16px; }
/* Instatic drops empty elements on publish, so each arrow span holds a "→";
   the mask draws the arrow and the character is pushed out of the box */
.aspen .a-arrow { overflow: hidden; text-indent: 200%; white-space: nowrap; }
.aspen .a-arrows .a-prev .a-arrow { transform: scaleX(-1); }
/* Instatic publishes a <button> without its children, so the prev/next arrow
   is drawn on the button itself; the span stays in the source for no-publish previews only */
.aspen .a-arrows .a-arrow { display: none; }
/* …but it keeps the span's TEXT, so the bare "→" was rendering next to the
   drawn arrow and prev read as "↔". Zero the button's own text instead of
   chasing whatever markup survives publishing; ::after is sized in px. */
.aspen .a-arrows button { font-size: 0; }
.aspen .a-arrows button::after {
  content: ""; position: absolute; inset: 0; margin: auto; width: 16px; height: 16px;
  background: currentColor;
  -webkit-mask: var(--a-arrow) center / contain no-repeat;
  mask: var(--a-arrow) center / contain no-repeat;
}
.aspen .a-arrows .a-prev::after { transform: scaleX(-1); }

/* ---------- entry: after Aspen's, measured on load ----------
   an ink sheet covers the page from the first paint; the mark fades and
   grows in (scale .3 → .45), then from .55s the sheet is cut away from the
   right over 1.2s on a slow-fast-slow curve. Pure CSS, so a script failure
   can never leave the sheet up. */
.aspen .a-intro {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: grid;
  place-items: center;
  background: var(--a-ink);
  color: var(--a-grey);
  pointer-events: none;
  animation: a-wipe 1.17s cubic-bezier(.9, 0, .15, .95) .68s forwards;
}
/* fitted to Aspen's loader sampled every 16ms: the outer layer grows .4 → 1
   hidden over .68s, then shows; from .68s the inner one takes the mark from
   .3 to full while the sheet is cut away from the right, both on one
   slow-fast-slow curve over 1.17s */
.aspen .a-intro .a-in1 { opacity: 0; transform: scale(.4); animation: a-in1 .68s cubic-bezier(.75, .1, .05, 1) forwards, a-show 0s .68s forwards; }
.aspen .a-intro .a-in2 { transform: scale(.3); animation: a-in2 1.17s cubic-bezier(.9, 0, .15, .95) .68s forwards; }
.aspen .a-intro svg { display: block; width: min(30vw, 300px); }
@keyframes a-wipe { from { clip-path: inset(0); } to { clip-path: inset(0 100% 0 0); visibility: hidden; } }
@keyframes a-in1 { to { transform: none; } }
@keyframes a-show { to { opacity: 1; } }
@keyframes a-in2 { to { transform: none; } }
@media (prefers-reduced-motion: reduce) { .aspen .a-intro { display: none; } }

/* ---------- header (the shared nav, re-cut for this page) ---------- */
body:is(:has(main.aspen), :has(main.lu), :has(main.lu-page)) .nav { height: 60px; border-bottom: 1px solid var(--a-ink); background: #fff; }
body:is(:has(main.aspen), :has(main.lu), :has(main.lu-page)) .nav-inner {
  display: grid;
  /* links start right after the clock (not at the half line) so they get room to breathe */
  grid-template-columns: 60px auto minmax(0, 1fr) auto;
  align-items: stretch;
  gap: 0;
  width: 100%;
  height: 100%;
}
body:is(:has(main.aspen), :has(main.lu), :has(main.lu-page)) .nav .logo { display: grid; place-items: center; background: var(--a-ink); perspective: 240px; }
body:is(:has(main.aspen), :has(main.lu), :has(main.lu-page)) .nav .logo img { width: 26px; height: 26px; }
body:is(:has(main.aspen), :has(main.lu), :has(main.lu-page)) .a-clock {
  display: flex;
  align-items: center;
  gap: .25em;
  padding: 0 20px 0 80px;
  border-right: 1px solid var(--a-ink);
  font-size: 14px;
  line-height: 1;
  letter-spacing: -.04em;
  font-variant-numeric: tabular-nums;
  color: var(--a-ink);
}
body:is(:has(main.aspen), :has(main.lu), :has(main.lu-page)) .a-roll { display: inline-flex; height: 1em; overflow: hidden; }
body:is(:has(main.aspen), :has(main.lu), :has(main.lu-page)) .a-roll .a-dg > span, .aspen .a-odo .a-dg > span {
  display: flex;
  flex-direction: column;
  transition: transform .65s var(--ease);
}
body:is(:has(main.aspen), :has(main.lu), :has(main.lu-page)) .a-roll .a-dg > span > span { height: 1em; }
body:is(:has(main.aspen), :has(main.lu), :has(main.lu-page)) .nav-links {
  display: flex;
  align-items: center;
  /* as wide as the half allows; 1024–1379px sets them tighter, and only
     below 1024px does the Menu button take over */
  gap: 36px;
  min-width: 0;
  overflow: hidden;
  padding: 0 16px;
  font-size: 16px;
  font-weight: 450;
  letter-spacing: -.04em;
  color: var(--a-ink);
}
body:is(:has(main.aspen), :has(main.lu), :has(main.lu-page)) .nav-links a { min-width: 0; white-space: nowrap; }
/* inner pages inherit an 11px mono size for these from the old theme; keep the homepage's */
body:is(:has(main.aspen), :has(main.lu), :has(main.lu-page)) .nav-links a,
body:is(:has(main.aspen), :has(main.lu), :has(main.lu-page)) .nav-contact span { font-size: inherit; }
body:is(:has(main.aspen), :has(main.lu), :has(main.lu-page)) .nav-links .menu-cta { display: none; }@media (hover: hover) {
body:is(:has(main.aspen), :has(main.lu), :has(main.lu-page)) .nav-links a:hover { color: var(--a-ink); opacity: .55; }
}
body:is(:has(main.aspen), :has(main.lu), :has(main.lu-page)) .nav-end { display: flex; align-items: stretch; gap: 0; }
/* the switch is a motion.js swap host: its hover slides a copy in from one
   line-height below, so the box must stay text-height, centred — not the
   header's full 60px, where the copy landed inside the box on top of the label */
body:is(:has(main.aspen), :has(main.lu), :has(main.lu-page)) .lang-switch { align-self: center; margin: 0 12px; padding: 0; font-size: 16px; line-height: 1.3; color: var(--a-ink); }
body:is(:has(main.aspen), :has(main.lu), :has(main.lu-page)) .nav-contact {
  justify-content: space-between;
  gap: 12px;
  width: 160px;
  padding: 0 20px;
  background: var(--a-ink);
  color: #fff;
  font-size: 16px;
  font-weight: 450;
}@media (hover: hover) {
body:is(:has(main.aspen), :has(main.lu), :has(main.lu-page)) .nav-contact:hover { color: var(--a-pink-hi); }
}
body:is(:has(main.aspen), :has(main.lu), :has(main.lu-page)) .nav-contact img { display: none; }
body:is(:has(main.aspen), :has(main.lu), :has(main.lu-page)) .nav-contact::after {
  content: "";
  width: 16px;
  height: 16px;
  background: currentColor;
  -webkit-mask: var(--a-arrow) center / contain no-repeat;
  mask: var(--a-arrow) center / contain no-repeat;
}

/* ---------- hero ---------- */
.aspen .a-hero { background: var(--a-ground); }
.aspen .a-hero .a-row { position: relative; z-index: 1; }
.aspen .a-pin { position: sticky; top: var(--a-top); }
.aspen .a-word { display: flex; align-items: flex-end; padding: var(--a-pad); }
.aspen .a-hero-q { display: flex; flex-direction: column; justify-content: space-between; padding: var(--a-pad); }
.aspen .a-hero-q.a-mint { padding: 0; }
.aspen .a-hero-q.a-mint .a-t24 { padding: var(--a-pad); }
/* paragraphs only — not the masked lines motion.js splits a heading into */
.aspen .a-hero .a-t24 > * + *:not(.m-line) { margin-top: 1.1em; }
.aspen .a-marq { display: flex; height: 80px; overflow: hidden; }
.aspen .a-marq-in {
  display: flex;
  flex: none;
  align-items: center;
  gap: 8px;
  padding-right: 8px;
  /* 12 boxes × 108px ≈ 1296px a copy; at Aspen's ~50px/s that is 26s a lap */
  animation: a-marq 26s linear infinite;
}
/* client logos: trimmed, cut out, shown as ink silhouettes. A wide wordmark
   and a square mark look equally heavy when height falls with aspect ratio
   (h ∝ aspect^-0.35); --lh is that factor, per file */
.aspen .a-logo { display: flex; flex: none; align-items: center; justify-content: center; width: auto; min-width: 100px; height: 80px; padding: 0 20px; }
/* in their own colours, like Aspen's; --lh keeps a wordmark and a square mark
   visually level inside the same box */
/* every logo is the same ink silhouette at the same height and stroke
   weight (normalised in assets/clients), so nothing needs a per-logo factor */
/* clients as wordmarks in the site's own sans — one size, one weight, nothing to mismatch */
.aspen .a-hx-band .a-logo { min-width: 0; padding: 0 28px; font-family: var(--sans); font-size: 20px; font-weight: 500; letter-spacing: .02em; white-space: nowrap; color: inherit; }
/* the band sits at the fold: show it with the hero, not on scroll */
.js-motion .aspen .a-hx-band .m-rise { opacity: 1; transform: none; transition: none; }
/* language switch: a cross-document view transition fades the other language in, no white flash */
@view-transition { navigation: auto; }
::view-transition-old(root), ::view-transition-new(root) { animation-duration: .45s; animation-timing-function: cubic-bezier(0, 0, .2, 1); }
@keyframes a-marq { to { transform: translateX(-100%); } }
.aspen .a-row-tall { height: 585px; }
.aspen .a-slogan-cell { container-type: inline-size; padding: var(--a-pad); }
.aspen .a-slogan { display: flex; flex-direction: column; font-size: 22.09cqw; line-height: .82; text-transform: uppercase; }
.aspen .a-slogan > span { display: block; overflow: hidden; }
/* Aspen's .82 leading is set for Latin capitals; Chinese glyphs are taller
   and collided at it */
main.aspen:not(.lang-en) .a-slogan, main.aspen:not(.lang-en) .a-h107 { line-height: 1; }
.aspen .a-slogan > span > span { display: block; will-change: transform; }

/* ---------- about + odometer stats ---------- */
.aspen .a-about { background: #fff; }
.aspen .a-about-txt { padding: var(--a-pad) var(--a-pad) 348px; }
.aspen .a-about-txt > * + * { margin-top: 1.1em; }
.aspen .a-about .a-sign { width: 156px; height: auto; margin-top: 60px; }
.aspen .a-stats { display: grid; grid-template-columns: repeat(4, 1fr); grid-template-rows: repeat(5, 200px); }
.aspen .a-stat { display: flex; flex-direction: column; justify-content: space-between; padding: var(--a-pad); }
.aspen .a-s1 { grid-area: 1 / 3 / 2 / 4; position: sticky; top: var(--a-top); }
.aspen .a-s2 { grid-area: 2 / 1 / 6 / 3; border-top: 1px solid var(--a-ink); border-right: 1px solid var(--a-ink); }
.aspen .a-s3 { grid-area: 2 / 4 / 4 / 5; position: sticky; top: var(--a-top); border-top: 1px solid var(--a-ink); border-left: 1px solid var(--a-ink); }
.aspen .a-s2 .a-t16 { align-self: flex-end; text-align: right; }
.aspen .a-odo { display: flex; line-height: 1; }
.aspen .a-odo .a-dg { display: inline-block; height: 1em; overflow: hidden; }
.aspen .a-odo .a-dg > span > span { display: block; height: 1em; }
.aspen .a-n80 { font-size: 5.58vw; }
.aspen .a-n132 { font-size: 9.18vw; }
.aspen .a-n115 { font-size: 7.97vw; }

/* ---------- grey sticky panel | ink column of numbered rows ---------- */
.aspen .a-conn { display: grid; grid-template-columns: 1fr 1fr; border-top: 1px solid var(--a-ink); }
.aspen .a-conn-l {
  position: sticky;
  top: var(--a-top);
  align-self: start;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  height: calc(var(--a-row) * 2);
  padding: var(--a-pad);
  border-right: 1px solid var(--a-ink);
}
.aspen .a-conn-top > * + * { margin-top: 24px; }
.aspen .a-conn-cta { display: flex; flex-direction: column; align-items: flex-start; gap: 60px; margin-left: 50%; }
.aspen .a-price { font-size: 24px; line-height: 1.1; letter-spacing: -.02em; }
.aspen .a-conn-r { background: var(--a-ink); color: #fff; }
.aspen .a-crow {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0 60px;
  min-height: var(--a-row);
  padding: 40px;
  border-bottom: 1px solid rgba(255, 255, 255, .2);
}
.aspen .a-crow:last-child { border-bottom: 0; }
.aspen .a-crow-l { display: grid; grid-template-columns: auto 1fr; gap: 0 19px; }
.aspen .a-crow-l > div { display: flex; flex-direction: column; justify-content: space-between; gap: 40px; }
.aspen .a-num { font-family: var(--a-mono); font-size: 14px; font-weight: 400; line-height: 1; padding-top: 2.8px; }
.aspen .a-crow-r { display: flex; flex-direction: column; justify-content: space-between; gap: 32px; }
.aspen .a-eyebrow { margin-bottom: 12px; font-family: var(--a-mono); font-size: 14px; font-weight: 400; line-height: 1; text-transform: uppercase; opacity: .6; }
.aspen .a-list li { display: flex; gap: 8px; font-family: var(--a-mono); font-size: 14px; font-weight: 400; line-height: 1.2; text-transform: uppercase; }
.aspen .a-list li::before { content: ""; flex: none; width: 8px; height: 8px; margin-top: .15em; background: var(--a-pink); }
.aspen .a-list li + li { margin-top: 8px; }
.aspen .a-list li span { opacity: .6; }
.aspen .a-list dt { font-family: var(--a-mono); font-size: 14px; font-weight: 400; line-height: 1.2; text-transform: uppercase; }
.aspen .a-list dd { margin: 6px 0 0; font-size: 16px; line-height: 1.3; opacity: .7; }
.aspen .a-list dd + dt { margin-top: 20px; }

/* pictograms: they run on their own, like Aspen's */
@property --a-t { syntax: '<angle>'; inherits: true; initial-value: 0deg; }
.aspen .a-pic { animation: a-turn 8s linear infinite; }
@keyframes a-turn { to { --a-t: 360deg; } }
.aspen .a-pic ellipse { transform: scaleX(cos(calc(var(--a-t) + var(--o, 0) * 1deg))); }
.aspen .a-pic .a-mv-y { animation: a-stripes 3s linear infinite; }
@keyframes a-stripes { to { transform: translateY(-100px); } }
.aspen .a-pic .a-rot { animation: a-rot 14s linear infinite; }
@keyframes a-rot { to { transform: rotate(-360deg); } }
.aspen .a-pic .a-mv-d { animation: a-drift 3.2s var(--a-ease) infinite alternate; }
@keyframes a-drift { to { transform: translate(-60px, -60px); } }
.aspen .a-pic .a-sy { animation: a-breathe 3.2s ease-in-out infinite alternate; }
@keyframes a-breathe { to { transform: scaleY(1.25); } }
@media (prefers-reduced-motion: reduce) { .aspen .a-pic, .aspen .a-pic * { animation: none; } }

/* ---------- lists: title | category rows, ink sweeps up behind ---------- */
.aspen .a-rows li { border-bottom: 1px solid var(--a-ink); }
.aspen .a-rows li:last-child { border-bottom: 0; }
.aspen .a-rows li > * {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  display: grid;
  grid-template-columns: 1fr 1fr;
  align-items: end;
  gap: 0 20px;
  min-height: 120px;
  padding: 12px;
  transition: color .45s var(--ease);
}
.aspen .a-rows li > *::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(--a-ink);
  transform: scaleY(0);
  transform-origin: bottom;
  transition: transform .45s var(--ease);
}.aspen .a-rows li.is-on > * { color: #fff; }
@media (hover: hover) {
.aspen .a-rows li:hover > * { color: #fff; }
}.aspen .a-rows li.is-on > *::before { transform: none; }
@media (hover: hover) {
.aspen .a-rows li:hover > *::before { transform: none; }
}

/* ---------- clients ---------- */
.aspen .a-cl-top { height: 585px; border-top: 1px solid var(--a-ink); }
.aspen .a-bigcell { padding: 0 var(--a-pad); }
.aspen .a-bigcell h2 { position: sticky; top: var(--a-top); padding: var(--a-pad) 0; }
.aspen .a-cl-body { border-top: 1px solid var(--a-ink); background: #fff; }
.aspen .a-cl-l {
  position: sticky;
  top: var(--a-top);
  align-self: start;
  display: grid;
  grid-template-columns: 1fr 1fr;
  height: calc(var(--a-row) * 2);
  border-right: 1px solid var(--a-ink);
}
.aspen .a-cl-q1 { display: grid; grid-template-rows: 1fr 1fr; border-right: 1px solid var(--a-ink); }
.aspen .a-cl-lab { display: flex; flex-direction: column; justify-content: space-between; padding: var(--a-pad); border-bottom: 1px solid var(--a-ink); }
.aspen .a-cl-foot { display: flex; align-items: flex-end; justify-content: space-between; gap: 12px; }
.aspen .a-cycler { height: 1em; overflow: hidden; line-height: 1; }
.aspen .a-cycler > span { display: flex; flex-direction: column; transition: transform .6s var(--ease); }
.aspen .a-cycler > span > span { height: 1em; white-space: nowrap; }
.aspen .a-cl-panels { position: relative; overflow: hidden; }
.aspen .a-cl-stack { position: absolute; inset: 0; transition: transform .8s var(--ease); }
.aspen .a-cl-stack > * { height: 100%; }
/* client logos, taken from each client's own site, as ink on grey; a client
   whose site has no logo to take stays an empty grey panel */
.aspen .a-cl-stack > div { display: grid; place-items: center; padding: 20%; background: var(--a-grey); }
.aspen .a-cl-stack > div { font-family: var(--sans); font-size: clamp(20px, 2vw, 30px); font-weight: 500; letter-spacing: .02em; line-height: 1.2; text-align: center; color: var(--a-ink); }
.aspen .a-cl-q2 .a-in { position: sticky; top: var(--a-top); display: flex; flex-direction: column; align-items: flex-start; gap: 60px; padding: var(--a-pad); }

/* ---------- case notes (Aspen's testimonials, fed by our case studies) ---------- */
.aspen .a-notes { display: grid; grid-template-columns: 1fr 2fr 1fr; border-top: 1px solid var(--a-ink); }
.aspen .a-nt-c1 { display: grid; grid-template-rows: var(--a-row) var(--a-row); background: #fff; border-right: 1px solid var(--a-ink); }
.aspen .a-nt-lab { display: flex; flex-direction: column; justify-content: space-between; border-bottom: 1px solid var(--a-ink); }
.aspen .a-nt-lab .a-label { padding: var(--a-pad); }
.aspen .a-nt-lab .a-arrows { border-top: 1px solid var(--a-ink); }
.aspen .a-nt-img { position: relative; overflow: hidden; background: var(--a-grey); }
.aspen .a-nt-img img { position: absolute; left: -4.5%; top: -4.5%; width: 109%; height: 109%; object-fit: cover; }
.aspen .a-nt-c2 { display: flex; flex-direction: column; justify-content: space-between; padding: var(--a-pad); background: #fff; border-right: 1px solid var(--a-ink); }
.aspen .a-nt-stage { transition: opacity .5s var(--ease), transform .5s var(--ease); }
.aspen .a-nt-stage:not(.in) { opacity: 0; transform: translateY(12px); }
.aspen .a-nt-foot { display: flex; align-items: flex-end; justify-content: space-between; margin-top: 40px; }
.aspen .a-nt-foot .a-mono { margin-top: 8px; }
.aspen .a-nt-c4 { display: grid; grid-template-rows: var(--a-row) var(--a-row); }
.aspen .a-nt-card { position: sticky; top: var(--a-top); display: flex; flex-direction: column; gap: 20px; height: var(--a-row); padding: var(--a-pad); }
.aspen .a-k { margin-bottom: 8px; font-size: 14px; font-weight: 500; line-height: 1; }
.aspen .a-bar { margin-top: auto; height: 2px; background: rgba(255, 255, 255, .2); }
.aspen .a-bar i { display: block; height: 100%; background: var(--a-pink); transform: scaleX(0); transform-origin: left; }
.aspen .a-bar.run i { animation: a-bar 5s linear forwards; }
@keyframes a-bar { to { transform: none; } }

/* ---------- work (Aspen's team): header rows, then a drifting card track ---------- */
.aspen .a-team { background: #fff; border-top: 1px solid var(--a-ink); }
.aspen .a-tm-top, .aspen .a-tm-mid { height: var(--a-row); }
.aspen .a-tm-top { border-bottom: 1px solid var(--a-ink); }
.aspen .a-tm-stmt { display: flex; align-items: flex-end; padding: var(--a-pad); }
.aspen .a-tm-arrows .a-arrows { border-bottom: 1px solid var(--a-ink); border-left: 1px solid var(--a-ink); }
.aspen .a-tm-p { display: flex; flex-direction: column; align-items: flex-start; gap: 60px; padding: var(--a-pad); }
.aspen .a-tm-track { position: relative; clip-path: inset(0); border-top: 1px solid var(--a-ink); }
.aspen .a-tm-bg { position: fixed; inset: 0; z-index: 0; }
.aspen .a-tm-rail {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: flex-start;
  width: 100%;
  padding: 0;
  will-change: transform;
}
/* the track is as tall as the rail is wide: while it passes, this frame stays
   pinned and aspen.js slides the rail sideways; then the page scrolls on */
.aspen .a-tm-pin { position: sticky; top: var(--a-top); z-index: 1; display: flex; align-items: center; height: calc(100vh - var(--a-top)); overflow: hidden; }
.aspen .a-tm-rail::-webkit-scrollbar { display: none; }
.aspen .a-card { flex: 0 0 25%; scroll-snap-align: start; }
.aspen .a-card:nth-child(6n+2) { margin-top: 157px; }
.aspen .a-card:nth-child(6n+3) { margin-top: 67px; }
.aspen .a-card:nth-child(6n+4) { margin-top: 224px; }
.aspen .a-card:nth-child(6n+5) { margin-top: 89px; }
.aspen .a-card:nth-child(6n+6) { margin-top: 22px; }
.aspen .a-card > a { position: relative; display: block; aspect-ratio: 358 / 447; overflow: hidden; background: var(--a-grey); will-change: transform; }
.aspen .a-card img { width: 100%; height: 100%; object-fit: cover; }
.aspen .a-card-tag { position: absolute; top: 0; right: 0; padding: 10px; background: #fff; border-bottom: 1px solid var(--a-ink); border-left: 1px solid var(--a-ink); color: var(--a-ink); }
.aspen .a-card-name {
  position: absolute;
  inset: auto 0 0;
  isolation: isolate;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 125px;
  padding: 52px 20px 20px;
  background: var(--a-ink);
  color: #fff;
  font-size: 24px;
  line-height: 1.1;
  letter-spacing: -.02em;
  transition: color .8s cubic-bezier(0, 0, .2, 1);
}
.aspen .a-card-name > span:first-child > span { display: block; }
.aspen .a-card-name .a-arrow { width: 24px; height: 24px; }
/* Aspen's team cards: the ink name bar fills with the accent from the left, and the tag in the corner inverts — all over .8s ease-out */
.aspen .a-card-name::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(--a-pink);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform .8s cubic-bezier(0, 0, .2, 1);
}
.aspen .a-card-tag { transition: background-color .8s cubic-bezier(0, 0, .2, 1), color .8s cubic-bezier(0, 0, .2, 1); }.aspen .a-card > a:focus-visible .a-card-name { color: var(--a-on-pink); }
@media (hover: hover) {
.aspen .a-card > a:hover .a-card-name { color: var(--a-on-pink); }
}.aspen .a-card > a:focus-visible .a-card-name::before { transform: none; }
@media (hover: hover) {
.aspen .a-card > a:hover .a-card-name::before { transform: none; }
}.aspen .a-card > a:focus-visible .a-card-tag { background: var(--a-ink); color: #fff; }
@media (hover: hover) {
.aspen .a-card > a:hover .a-card-tag { background: var(--a-ink); color: #fff; }
}

/* a work card opens its case study in a side panel, as Aspen's team modal:
   half the page wide from the right over a 60% ink scrim, the close square
   outside its top-left corner; full width below 1024px. aspen.js builds it. */
.a-modal { position: fixed; inset: 0; width: 100%; height: 100%; max-width: none; max-height: none; margin: 0; padding: 0; border: 0; background: transparent; overflow: hidden; }
.a-modal::backdrop { background: transparent; }
.a-modal-bg { position: absolute; inset: 0; background: rgb(35 35 35 / .6); cursor: pointer; animation: a-scrim-in .8s var(--a-ease) both; }
.a-modal-panel { position: absolute; top: 0; right: 0; bottom: 0; width: 50%; border-left: 1px solid var(--a-ink); background: #fff; animation: a-panel-in .8s var(--a-ease) both; }
.a-modal-x { position: absolute; top: 0; right: 100%; z-index: 1; width: 60px; height: 60px; padding: 0; border: 0; background: var(--a-pink); color: var(--a-on-pink); cursor: pointer; transition: background-color .3s, color .3s; animation: a-scrim-in .28s var(--a-ease) .8s both; }
.a-modal-x::before, .a-modal-x::after { content: ""; position: absolute; top: 50%; left: 50%; width: 22px; height: 1.5px; background: currentColor; transform: translate(-50%, -50%) rotate(45deg); }
.a-modal-x::after { transform: translate(-50%, -50%) rotate(-45deg); }.a-modal-x:focus-visible { background: var(--a-ink); color: #fff; }
@media (hover: hover) {
.a-modal-x:hover { background: var(--a-ink); color: #fff; }
}
/* what the panel holds, measured on Aspen's: the scroll lives inside, so the
   close square can sit outside the panel's edge without being clipped */
.a-mo { height: 100%; overflow-x: hidden; overflow-y: auto; overscroll-behavior: contain; touch-action: pan-y; color: var(--a-ink); font-size: 16px; line-height: 1.3; letter-spacing: -.04em; }
/* :where keeps this at zero weight, so the enquiry bar and the link cells set their own colours */
.a-mo :where(a) { color: inherit; text-decoration: none; }
.a-mo img { display: block; width: 100%; }
/* dvh, not vh: on a phone the address bar changes vh mid-scroll and the sheet jumps */
.a-mo-hero { position: relative; height: max(420px, calc(100dvh - 122px)); background: var(--a-grey); }
.a-mo-hero img { height: 100%; object-fit: cover; }
.a-mo-tag { position: absolute; top: 0; right: 0; padding: 10px; border-bottom: 1px solid var(--a-ink); border-left: 1px solid var(--a-ink); background: #fff; font-family: var(--a-mono); font-size: 12px; line-height: 1.1; text-transform: uppercase; }
.a-mo-tag:empty { display: none; }
.a-mo-cta, .a-mo-links a { display: flex; align-items: center; justify-content: space-between; height: 60px; padding: 0 20px; transition: background-color .3s, color .3s; }
.a-mo-cta::after, .a-mo-links a::after { content: ""; flex: none; width: 16px; height: 16px; background: currentColor; -webkit-mask: var(--a-arrow) center / contain no-repeat; mask: var(--a-arrow) center / contain no-repeat; }
.a-mo-cta { position: absolute; right: 0; bottom: 0; width: 50%; background: var(--a-pink); color: var(--a-on-pink); }@media (hover: hover) {
.a-mo-cta:hover { background: var(--a-ink); color: #fff; }
}
.a-mo-row { display: grid; grid-template-columns: 1fr 1fr; border-top: 1px solid var(--a-ink); }
.a-mo-l { display: flex; flex-direction: column; }
.a-mo-name { display: flex; align-items: flex-end; height: 125px; padding: 52px 20px 20px; background: var(--a-ink); color: #fff; }
.a-mo-name h2 { margin: 0; font-size: 24px; font-weight: 450; line-height: 1.1; letter-spacing: -.02em; }
.a-mo-pic { flex: 1; min-height: 360px; background: var(--a-ground); }
.a-mo-pic img { height: 100%; object-fit: cover; }
.a-mo-links { display: grid; grid-template-columns: 1fr 1fr; margin: 0; padding: 0; list-style: none; border-top: 1px solid var(--a-ink); }
.a-mo-links li + li { border-left: 1px solid var(--a-ink); }@media (hover: hover) {
.a-mo-links a:hover { background: var(--a-pink); color: var(--a-on-pink); }
}
.a-mo-r { display: flex; flex-direction: column; gap: 16px; padding: 20px; background: var(--a-grey); }
.a-mo-r > * { margin: 0; }
.a-mo-title { font-size: 24px; line-height: 1.1; letter-spacing: -.02em; }
.a-mo-meta { display: grid; gap: 8px; padding: 12px 0; border-top: 1px solid var(--a-ink); border-bottom: 1px solid var(--a-ink); }
.a-mo-meta div { display: grid; grid-template-columns: 7.5em minmax(0, 1fr); gap: 12px; }
.a-mo-meta dt { font-family: var(--a-mono); font-size: 12px; line-height: 1.6; text-transform: uppercase; }
.a-mo-meta dd { margin: 0; }
.a-mo-r h3, .a-mo-r h4 { font-size: 16px; font-weight: 600; line-height: 1.3; }
.a-mo-r h3 { margin-top: 12px; }
.a-mo-r ul { padding-left: 1.1em; }
.a-mo-r p a { text-decoration: underline; }
.a-mo-r blockquote { margin: 0; padding-top: 16px; border-top: 1px solid var(--a-ink); }
.a-mo-r blockquote footer { margin-top: 12px; font-family: var(--a-mono); font-size: 12px; text-transform: uppercase; color: inherit; }
/* The case quote arrives with the old theme's .quote on it: a 2px left rule,
   26px of indent and 24px semibold display type, against a panel set in 16px.
   It read as a slab pasted in from another site. Drop the rule and the indent,
   and let it sit one step above the body copy — the panel already draws its own
   hairline above the block, which is the only line it needs. */
.a-mo .quote { max-width: none; padding-left: 0; border-left: 0; }
.a-mo .quote p { margin: 0; font-family: inherit; font-size: 17px; font-weight: 500; line-height: 1.55; }
/* the pictures below the fold cost nothing until they are scrolled to */
.a-mo-shots img { border-top: 1px solid var(--a-ink); content-visibility: auto; contain-intrinsic-size: auto 280px; }
/* character reveal (aspen.js cuts the characters): the block is held nearly
   invisible until cut; then each character waits under its own mask and rises
   when its block scrolls in, .015s after the one before (Aspen's chars stagger).
   Units are atomic so words and CJK-with-punctuation never split across lines. */
.a-mo .a-rv:not(.is-cut) { opacity: .001; }
.a-mo .a-un { display: inline-block; max-width: 100%; white-space: nowrap; }
/* a word too long for the column breaks rather than pushing the sheet sideways */
.a-mo .a-un-long { white-space: normal; overflow-wrap: anywhere; }
.a-mo .a-ch { display: inline-block; clip-path: inset(-.25em -.05em); }
.a-mo .a-ch-i { display: inline-block; transform: translateY(100%); transition: transform 1s cubic-bezier(.23, 1, .32, 1) calc(var(--ch) * .015s); }
.a-mo .in .a-ch-i { transform: none; }
/* measured from Aspen's source: the same .8s easeOut on the way out; the close square takes .28s */
.a-modal.is-out .a-modal-bg { animation: a-scrim-out .8s var(--a-ease) both; }
.a-modal.is-out .a-modal-panel { animation: a-panel-out .8s var(--a-ease) both; }
.a-modal.is-out .a-modal-x { animation: a-scrim-out .28s var(--a-ease) both; }
@keyframes a-panel-in { from { transform: translateX(100%); } }
@keyframes a-panel-out { to { transform: translateX(100%); } }
@keyframes a-scrim-in { from { opacity: 0; } }
@keyframes a-scrim-out { to { opacity: 0; } }
html.a-modal-open { overflow: hidden; }
@media (max-width: 1023px) {
  .a-modal-panel { width: 100%; border-left: 0; }
  .a-modal-x { right: auto; left: 0; }
  .a-mo-hero { height: 75dvh; }
  .a-mo-cta { width: 100%; }
  .a-mo-row { grid-template-columns: 1fr; }
  .a-mo-pic { min-height: 0; aspect-ratio: 4 / 3; flex: none; }
  .a-mo-r { padding: 20px 12px; }
  /* a full-screen sheet reads as a push, not a snap: slow–fast–slow, and a little longer */
  .a-modal-panel { animation: a-panel-in 1s cubic-bezier(.76, 0, .24, 1) both; }
  .a-modal.is-out .a-modal-panel { animation: a-panel-out .7s cubic-bezier(.76, 0, .24, 1) both; }
  .a-modal.is-out .a-modal-bg { animation-duration: .7s; }
}
@media (prefers-reduced-motion: reduce) { .a-modal-bg, .a-modal-panel { animation: none !important; } }

/* ---------- services / journal: sticky word | rows ---------- */
.aspen .a-ls { display: grid; grid-template-columns: 1fr 1fr; border-top: 1px solid var(--a-ink); background: #fff; }
.aspen .a-ls-l {
  position: sticky;
  top: var(--a-top);
  align-self: start;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  height: var(--a-row);
  padding: var(--a-pad);
  border-right: 1px solid var(--a-ink);
}
.aspen .a-ls .a-rows { align-self: start; }
.aspen .a-ls .a-rows .a-t38 { font-size: 1.9vw; }

/* ---- rows that are not links -------------------------------------------
   .a-rows was built for the services and journal lists, where every row is
   an anchor and the ink sweep on hover is the affordance. The symptom,
   process and FAQ rows are not destinations, so they keep the rule and the
   type but drop the sweep — a hover fill on something you cannot click
   reads as a broken link. */
.aspen .a-rows-static li > *::before { content: none; }
@media (hover: hover) {
  .aspen .a-rows-static li:hover > * { color: inherit; }
}
.aspen .a-rows-static li > * { align-items: start; gap: 6px 20px; min-height: 0; padding: 22px 12px; }
.aspen .a-rows-static .a-mono { align-self: start; max-width: 42ch; text-transform: none; line-height: 1.5; }

/* the process rows count themselves, so the steps cannot drift out of order */
.aspen .a-rows-num { counter-reset: step; }
.aspen .a-rows-num li { counter-increment: step; }
.aspen .a-rows-num li > * { grid-template-columns: 44px 1fr 1fr; }
.aspen .a-rows-num li > *::after {
  content: counter(step, decimal-leading-zero);
  grid-row: 1 / -1; grid-column: 1;
  font-family: var(--a-mono); font-size: 12px; line-height: 1.5; opacity: .5;
}
.aspen .a-rows-num li h3, .aspen .a-rows-num li .a-mono { grid-row: 1; }
.aspen .a-rows-num li h3 { grid-column: 2; }
.aspen .a-rows-num li .a-mono { grid-column: 3; }

/* FAQ: a native <details>, so it works with no JS and is findable in-page */
.aspen .a-faq li > * { display: block; padding: 0; }
.aspen .a-faq summary {
  display: grid; grid-template-columns: 1fr 24px; align-items: center; gap: 20px;
  padding: 22px 12px; cursor: pointer; list-style: none;
}
.aspen .a-faq summary::-webkit-details-marker { display: none; }
.aspen .a-faq summary::after {
  content: ""; width: 14px; height: 14px;
  background: linear-gradient(currentColor, currentColor) center / 14px 2px no-repeat,
              linear-gradient(currentColor, currentColor) center / 2px 14px no-repeat;
  transition: transform .3s var(--a-ease), background-size .3s var(--a-ease);
}
.aspen .a-faq summary h3 { margin: 0; }
.aspen .a-faq details[open] summary::after { background-size: 14px 2px, 2px 0; transform: rotate(180deg); }
.aspen .a-faq details > p { margin: 0; padding: 0 12px 24px; max-width: 60ch; }
.aspen .a-ls-note { margin: 0; padding: 22px 12px; border-top: 1px solid var(--a-ink); grid-column: 2; max-width: 56ch; }
/* journal titles are sentences: one wide column, a smaller size */
.aspen #journal .a-rows li > * { grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: 0 40px; min-height: 96px; }
.aspen #journal .a-rows .a-t38 { font-size: clamp(18px, 1.4vw, 22px); line-height: 1.3; }
.aspen .a-ls-more { display: flex; align-items: center; justify-content: space-between; min-height: 60px; padding: 0 12px; border-top: 1px solid var(--a-ink); font-size: 16px; }@media (hover: hover) {
.aspen .a-ls-more:hover { background: var(--a-pink); color: var(--a-on-pink); }
}

/* ---------- let's talk: blocks of type over the dither ---------- */
.aspen .a-cta { height: 95.8vw; overflow: hidden; border-top: 1px solid var(--a-ink); background: var(--a-ground); }
.aspen .a-cta-h { position: absolute; inset: 62.8% 0 auto; z-index: 1; font-size: 8.62vw; line-height: .9; text-transform: uppercase; }
.aspen .a-cta-h > span { display: flex; }
.aspen .a-cta-l1 { display: grid !important; grid-template-columns: 36.2% auto 1fr; }
.aspen .a-cta-l1 > * { justify-self: start; }
.aspen .a-cta-l1 > :last-child { justify-self: end; }
.aspen .a-cta-l2 { padding-left: 21.2%; }
.aspen .a-blk { display: block; padding: .05em .05em .04em; }
.aspen .a-blk.a-ink { color: #fff; }
.aspen .a-blk.a-white { background: #fff; }
.aspen .a-cta-btn { display: grid; place-items: center; flex: none; width: .99em; background: var(--a-pink); color: var(--a-on-pink); transition: background-color .3s var(--ease), color .3s var(--ease); }@media (hover: hover) {
.aspen .a-cta-btn:hover { background: #fff; color: var(--a-ink); }
}
.aspen .a-cta-btn .a-arrow { width: .4em; height: .4em; }

/* ---------- footer (this page's own) ---------- */
.aspen .a-foot { border-top: 1px solid var(--a-ink); }
.aspen .a-ft-top { height: var(--a-row); background: #fff; border-bottom: 1px solid var(--a-ink); }
.aspen .a-ft-r { display: flex; flex-direction: column; }
.aspen .a-ft-links { flex: 1; border-bottom: 1px solid var(--a-ink); }
.aspen .a-ft-nav a { display: inline-flex; align-items: center; height: 29px; font-size: 16px; }@media (hover: hover) {
.aspen .a-ft-nav a:hover { opacity: .55; }
}
.aspen .a-ft-nav li + li { margin-top: 8px; }
.aspen .a-ft-clock p + p { margin-top: 4px; }
.aspen .a-ft-contacts { display: grid; grid-template-columns: 2fr 1fr 1fr; height: 60px; }
.aspen .a-ft-contacts a { display: flex; align-items: center; padding: 0 20px; font-size: 16px; transition: background-color .3s var(--ease); }
.aspen .a-ft-contacts a + a { border-left: 1px solid var(--a-ink); }@media (hover: hover) {
.aspen .a-ft-contacts a:hover { background: var(--a-pink); color: var(--a-on-pink); }
}
.aspen .a-ft-bot { height: var(--a-row); }
.aspen .a-ft-legal { display: flex; align-items: flex-end; justify-content: space-between; gap: 20px; padding: var(--a-pad); border-right: 1px solid var(--a-ink); }
.aspen .a-ft-legal .a-mono { color: rgba(255, 255, 255, .65); }
.aspen .a-ft-cta {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  padding: 20px 12px;
  background: var(--a-pink);
  color: var(--a-on-pink);
  transition: color .6s var(--ease);
}
.aspen .a-ft-cta::before { content: ""; position: absolute; inset: 0; z-index: -1; background: var(--a-ink); clip-path: inset(0 100% 0 0); transition: clip-path .6s var(--ease); }@media (hover: hover) {
.aspen .a-ft-cta:hover { color: #fff; }
}@media (hover: hover) {
.aspen .a-ft-cta:hover::before { clip-path: inset(0); }
}
.aspen .a-ft-cta-b { display: flex; align-items: flex-end; justify-content: space-between; }
.aspen .a-ft-cta-b .a-arrow { width: 114px; height: 114px; }

/* ---------- 1024–1379px: all six links stay in the bar, set tighter ---------- */
@media (min-width: 1024px) and (max-width: 1379px) {
  body:is(:has(main.aspen), :has(main.lu), :has(main.lu-page)) .a-clock { padding: 0 16px; }
  body:is(:has(main.aspen), :has(main.lu), :has(main.lu-page)) .nav-links { gap: 26px; font-size: 15px; }
  body:is(:has(main.aspen), :has(main.lu), :has(main.lu-page)) .nav-contact { width: 132px; padding: 0 16px; }
  /* the old theme folds its nav at 1100px; undo that fold here */
  body:is(:has(main.aspen), :has(main.lu), :has(main.lu-page)) .menu-btn { display: none; }
  body:is(:has(main.aspen), :has(main.lu), :has(main.lu-page)) .nav-inner { gap: 0; }
  body:is(:has(main.aspen), :has(main.lu), :has(main.lu-page)) .nav-links { position: static; display: flex; flex-direction: row; align-items: center; padding: 0 16px; background: none; box-shadow: none; }
  body:is(:has(main.aspen), :has(main.lu), :has(main.lu-page)) .nav-links a { padding: 0; font-size: inherit; }
  body:is(:has(main.aspen), :has(main.lu), :has(main.lu-page)) .nav-contact { display: flex; }
  body:is(:has(main.aspen), :has(main.lu), :has(main.lu-page)) .nav-end { margin-left: 0; }
}

/* ---------- tablet and phone: the links fold into the Menu button ---------- */
@media (max-width: 1023px) {
  body:is(:has(main.aspen), :has(main.lu), :has(main.lu-page)) .nav-inner { grid-template-columns: 60px 1fr auto auto; }
  body:is(:has(main.aspen), :has(main.lu), :has(main.lu-page)) .a-clock { padding: 0 12px; border-right: 0; }
  body:is(:has(main.aspen), :has(main.lu), :has(main.lu-page)) .nav-contact { display: none; }
  body:is(:has(main.aspen), :has(main.lu), :has(main.lu-page)) .menu-btn {
    grid-column: 4;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    width: 116px;
    padding: 0 12px;
    background: var(--a-pink);
    color: var(--a-on-pink);
    font-size: 16px;
    cursor: pointer;
  }
  body:is(:has(main.aspen), :has(main.lu), :has(main.lu-page)) .menu-btn::before { content: "Menu"; }
  /* the old theme paints the two bars black; follow the button's text colour */
  body:is(:has(main.aspen), :has(main.lu), :has(main.lu-page)) .menu-btn .bars::before, body:is(:has(main.aspen), :has(main.lu), :has(main.lu-page)) .menu-btn .bars::after { background: currentColor; }
  body:is(:has(main.aspen), :has(main.lu), :has(main.lu-page)) .menu-toggle:checked + .menu-btn::before { content: "Close"; }
  /* the Chinese header says it in Chinese */
  body:is(:has(main.aspen), :has(main.lu), :has(main.lu-page)) .nav[data-lang="zh"] .menu-btn::before { content: "選單"; }
  body:is(:has(main.aspen), :has(main.lu), :has(main.lu-page)) .nav[data-lang="zh"] .menu-toggle:checked + .menu-btn::before { content: "關閉"; }
  body:is(:has(main.aspen), :has(main.lu), :has(main.lu-page)) .nav-links {
    position: absolute;
    top: 60px;
    left: 0;
    right: 0;
    display: none;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    padding: 0;
    background: #fff;
    border-bottom: 1px solid var(--a-ink);
  }
  body:is(:has(main.aspen), :has(main.lu), :has(main.lu-page)) .menu-toggle:checked ~ .nav-links { display: flex; }
  body:is(:has(main.aspen), :has(main.lu), :has(main.lu-page)) .nav-links a { display: flex; align-items: center; height: 60px; padding: 0 12px; border-top: 1px solid var(--a-ink); text-align: left; }
  body:is(:has(main.aspen), :has(main.lu), :has(main.lu-page)) .nav-links .menu-cta { display: flex; justify-content: flex-start; border-radius: 0; background: var(--a-ink); color: #fff; }
}

/* ---------- below 1024px: Aspen's tablet / phone column ----------
   measured on aspensearch.com at 768px and 375px: one column, 12px side
   padding, the hero's word rows keep their two halves (188px of air above
   each word), the slogan and the two copy blocks go full width, every
   other section stacks — white panel, ink rows, window first in clients,
   work cards full width one under another. */
@media (max-width: 1023px) {
  body:has(main.aspen) { --a-pad: 12px; }
  /* header: logo + clock (+ language) | half the bar is the mint menu */
  body:is(:has(main.aspen), :has(main.lu), :has(main.lu-page)) .nav-inner { grid-template-columns: 60px minmax(0, 1fr) auto 50%; }
  body:is(:has(main.aspen), :has(main.lu), :has(main.lu-page)) .a-clock { overflow: hidden; white-space: nowrap; }
  body:is(:has(main.aspen), :has(main.lu), :has(main.lu-page)) .nav-end { border-right: 1px solid var(--a-ink); }
  body:is(:has(main.aspen), :has(main.lu), :has(main.lu-page)) .menu-btn { width: auto; }

  .aspen .a-display { font-size: 13.5vw; }
  .aspen .a-h107 { font-size: 15.2vw; }
  .aspen .a-t38 { font-size: clamp(24px, 3.8vw, 29px); }
  .aspen .a-t31 { font-size: clamp(24px, 3.5vw, 27px); }
  .aspen .a-br { border-right: 0; }
  .aspen .a-q:empty { display: none; }

  /* hero: words, words, slogan, ink copy, pink copy */
  .aspen .a-hero { display: flex; flex-direction: column; }
  .aspen .a-hero-pin { display: contents; }
  .aspen .a-hero .a-row { height: auto; }
  .aspen .a-pin { order: 1; position: relative; top: auto; }
  .aspen .a-hero > .a-bb { order: 2; }
  .aspen .a-row-tall { order: 3; grid-template-columns: 1fr; }
  .aspen .a-row-copy { order: 4; grid-template-columns: 1fr; }
  .aspen .a-row-tall > .a-cell:last-child, .aspen .a-row-copy > .a-cell:first-child { display: none; }
  .aspen .a-pin > .a-cell:first-child { border-right: 1px solid var(--a-ink); }
  .aspen .a-hero > .a-bb > .a-cell:first-child { border-right: 1px solid var(--a-ink); }
  .aspen .a-word { padding: 188px 12px 20px; }
  .aspen .a-slogan-cell { padding: 20px 12px; }
  .aspen .a-hero .a-split { grid-template-columns: 1fr; }
  .aspen .a-hero-q { gap: 188px; padding: 20px 12px; }
  .aspen .a-hero-q.a-mint { gap: 0; }
  .aspen .a-hero-q.a-mint .a-t24 { padding: 20px 12px 188px; }
  .aspen .a-hero .a-btn-full { align-self: flex-end; width: auto; min-width: 189px; background: #fff; color: var(--a-ink); }

  /* about + bands */
  .aspen .a-grid2 { grid-template-columns: 1fr; }
  .aspen .a-about .a-pad { padding: 20px 12px; }
  .aspen .a-about-txt { padding: 168px 12px 20px; }
  .aspen .a-stats { grid-template-columns: 1fr; grid-template-rows: none; }
  .aspen .a-stat { grid-area: auto; position: static; height: 200px; padding: 20px 12px; border: 0; }
  .aspen .a-n80 { font-size: 80px; }
  .aspen .a-n132 { font-size: clamp(80px, 13vw, 99px); }
  .aspen .a-n115 { font-size: clamp(80px, 12.2vw, 93px); }

  /* white panel, then the ink rows: [number | pictogram], title, copy, list */
  .aspen .a-conn { grid-template-columns: 1fr; }
  .aspen .a-conn-l { position: static; height: auto; min-height: max(603px, 95vw); gap: 60px; padding: 20px 12px; border-right: 0; background: #fff; }
  .aspen .a-conn-cta { margin-left: auto; width: min(400px, 100%); gap: 60px; }
  .aspen .a-conn-cta .a-btn { align-self: flex-end; }
  .aspen .a-crow { grid-template-columns: 1fr 1fr; grid-template-areas: "num pic" "ttl ttl" "body body"; gap: 0; padding: 20px 12px; min-height: 0; }
  .aspen .a-crow-l, .aspen .a-crow-l > div { display: contents; }
  .aspen .a-crow .a-num { grid-area: num; }
  .aspen .a-crow .a-pic { grid-area: pic; width: min(200px, 44vw); height: min(200px, 44vw); }
  .aspen .a-crow h3 { grid-area: ttl; margin-top: 80px; }
  .aspen .a-crow-r { grid-area: body; gap: 24px; margin-top: 24px; }

  /* clients: window, white block, rows */
  .aspen .a-cl-top { height: auto; }
  .aspen .a-cl-top .a-winbox { order: -1; aspect-ratio: 1; }
  .aspen .a-bigcell { padding: 20px 12px 0; }
  .aspen .a-bigcell h2, .aspen .a-cl-q2 .a-in, .aspen .a-ls-l, .aspen .a-nt-card { position: static; }
  .aspen .a-cl-body { border-top: 0; }
  .aspen .a-cl-l { display: block; position: static; height: auto; border-right: 0; }
  .aspen .a-cl-q1 { display: block; border-right: 0; }
  .aspen .a-cl-lab { padding: 20px 12px 0; border-bottom: 0; }
  .aspen .a-cl-foot, .aspen .a-cl-panels { display: none; }
  .aspen .a-cl-q2 .a-in { padding: 20px 12px; }
  .aspen .a-cl-q2 .a-btn { align-self: flex-end; }
  .aspen .a-cl-body .a-rows { border-top: 1px solid var(--a-ink); }
  .aspen .a-rows li > * { min-height: 100px; }

  /* case notes: label, quote, name; the ink pair; the arrows */
  .aspen .a-notes { display: flex; flex-direction: column; }
  .aspen .a-nt-c1, .aspen .a-nt-lab, .aspen .a-nt-c4 { display: contents; }
  .aspen .a-nt-lab .a-label { order: 1; padding: 24px 12px 0; background: #fff; }
  .aspen .a-nt-c2 { order: 2; min-height: 0; padding: 60px 12px 24px; border-right: 0; }
  .aspen .a-nt-card { order: 3; display: grid; grid-template-columns: 1fr 1fr; gap: 20px; height: auto; }
  .aspen .a-bar { grid-column: 1 / -1; }
  .aspen .a-nt-lab .a-arrows { order: 4; border-top: 0; }
  .aspen .a-nt-img, .aspen .a-nt-c4 > .a-winbox { display: none; }

  /* work: one white block, then the cards full width, one under another */
  .aspen .a-tm-top, .aspen .a-tm-mid { display: block; height: auto; border-bottom: 0; }
  .aspen .a-tm-top .a-split, .aspen .a-tm-mid .a-split { display: block; }
  .aspen .a-tm-stmt { padding: 28px 12px 0; }
  .aspen .a-tm-mid .a-pad, .aspen .a-tm-p { padding: 20px 12px; }
  .aspen .a-tm-arrows { display: none; }
  .aspen .a-tm-rail { display: block; overflow: visible; padding: 0; }
  .aspen .a-tm-pin { position: static; display: block; height: auto; overflow: visible; }
  .aspen .a-tm-track { height: auto !important; }
  .aspen .a-card { margin-top: 0 !important; border-bottom: 1px solid var(--a-ink); }
  .aspen .a-card-name { padding: 52px 12px 20px; }

  /* services / journal */
  .aspen .a-ls { grid-template-columns: 1fr; }
  .aspen .a-ls-l { height: auto; gap: 80px; padding: 20px 12px; border-right: 0; border-bottom: 1px solid var(--a-ink); }
  .aspen .a-ls .a-rows .a-t38 { font-size: clamp(20px, 3.4vw, 26px); }

  /* talk */
  .aspen .a-cta { height: 160vw; }
  .aspen .a-cta-h { font-size: 12vw; inset: auto 0 12vw; }
  .aspen .a-cta-l1 { grid-template-columns: auto auto 1fr; }
  .aspen .a-cta-l2 { padding-left: 0; }

  /* footer */
  .aspen .a-ft-top, .aspen .a-ft-bot { height: auto; }
  .aspen .a-ft-top > .a-cell { min-height: 50vw; padding: 20px 12px; }
  .aspen .a-ft-links { display: grid; grid-template-columns: 1fr 1fr; border-top: 1px solid var(--a-ink); }
  .aspen .a-ft-links > :first-child { border-right: 1px solid var(--a-ink); }
  .aspen .a-ft-contacts { grid-template-columns: 1fr; height: auto; }
  .aspen .a-ft-contacts a { height: 60px; border-top: 1px solid var(--a-ink); }
  .aspen .a-ft-contacts a + a { border-left: 0; }
  .aspen .a-ft-legal { min-height: 50vw; flex-direction: column; align-items: flex-start; justify-content: flex-end; padding: 20px 12px; }
  .aspen .a-ft-cta { min-height: 100vw; }
  .aspen .a-ft-cta-b .a-arrow { width: 72px; height: 72px; }
}
/* a phone's half bar can't hold "TPE: 05:55 PM" and EN: drop the city */
@media (max-width: 479px) {
  body:is(:has(main.aspen), :has(main.lu), :has(main.lu-page)) .a-clock { padding: 0 8px; }
  body:is(:has(main.aspen), :has(main.lu), :has(main.lu-page)) .a-clock > span:first-child { display: none; }
  body:is(:has(main.aspen), :has(main.lu), :has(main.lu-page)) .lang-switch { margin: 0 8px; }
}
@media (prefers-reduced-motion: reduce) {
  .aspen .a-marq-in { animation: none; }
}

/* ============================================================
   interior pages on the homepage's system — the grid language
   without its set pieces: white ground, 1px ink rules, one weight at
   -4%, mono labels led by a small square, pink as the one accent.
   Articles keep a readable column; everything else sits in cells.
   (body main.x selectors: enough weight to outrank the old lumina
   rules, which stay for nothing but this layer to override)
   ============================================================ */
body:is(:has(main.aspen), :has(main.lu), :has(main.lu-page)) .nav { backdrop-filter: none; -webkit-backdrop-filter: none; }
body:is(:has(main.aspen), :has(main.lu), :has(main.lu-page)) .nav-links a, body:is(:has(main.aspen), :has(main.lu), :has(main.lu-page)) .lang-switch, body:is(:has(main.aspen), :has(main.lu), :has(main.lu-page)) .nav-contact span { font-family: var(--sans); text-transform: none; letter-spacing: -.04em; }
body:is(:has(main.lu), :has(main.lu-page)) { background: #fff; color: var(--a-ink); }
body:is(:has(main.lu), :has(main.lu-page))::before,
body:is(:has(main.lu), :has(main.lu-page))::after,
body:is(:has(main.lu), :has(main.lu-page)) main::before,
body:is(:has(main.lu), :has(main.lu-page)) .m-cursor,
body:is(:has(main.lu), :has(main.lu-page)) .m-rail { display: none; }
body main.lu, body main.lu-page { background: #fff; color: var(--a-ink); font-weight: 450; letter-spacing: -.04em; }

/* labels: mono, uppercase, a square before */
body main.lu-page .detail-head .client, body main.lu .lu-meta, body main.lu .lu-tag,
body main.lu-page .detail-meta dt, body main.lu .lu-post-meta, body main.lu .lu-cat {
  display: flex; align-items: center; gap: 12px;
  font-family: var(--a-mono); font-size: 12px; font-weight: 400; line-height: 1.1;
  letter-spacing: -.04em; text-transform: uppercase; color: var(--a-ink);
}
body main.lu-page .detail-head .client::before, body main.lu .lu-meta > span:first-child::before, body main.lu .lu-tag::before {
  content: ""; flex: none; width: 8px; height: 8px; background: currentColor;
}

/* ---------- head: back link, label, title, standfirst, facts ---------- */
body main.lu-page .detail-head { padding: 0; background: #fff; border-bottom: 1px solid var(--a-ink); }
body main.lu-page .detail-head .wrap { width: 100%; max-width: none !important; margin: 0; padding: var(--a-pad) var(--a-pad) 48px; }
body main.lu-page .detail-head .back { display: inline-flex; align-items: center; gap: 8px; font-family: var(--a-mono); font-size: 12px; font-weight: 400; text-transform: uppercase; letter-spacing: -.04em; color: var(--a-ink); }
body main.lu-page .detail-head .back img { display: none; }
body main.lu-page .detail-head .back::before { content: ""; width: 12px; height: 12px; background: currentColor; -webkit-mask: var(--a-arrow) center / contain no-repeat; mask: var(--a-arrow) center / contain no-repeat; transform: scaleX(-1); }
body main.lu-page .detail-head .client { margin: 140px 0 20px; }
body main.lu-page .detail-head h1 { margin: 0; max-width: 20ch; font-size: clamp(34px, 5.2vw, 84px); font-weight: 450; line-height: 1.04; letter-spacing: -.04em; text-wrap: balance; }
body main.lu-page .detail-head .lede { margin: 40px 0 0 50%; max-width: none; font-size: clamp(18px, 1.7vw, 24px); line-height: 1.3; letter-spacing: -.02em; color: var(--a-ink); }
body main.lu-page .detail-meta { display: grid; grid-template-columns: repeat(4, 1fr); margin: 60px calc(var(--a-pad) * -1) -48px; border-top: 1px solid var(--a-ink); }
body main.lu-page .detail-meta > div { margin: 0; padding: var(--a-pad); border: 0; border-right: 1px solid var(--a-ink); }
body main.lu-page .detail-meta > div:last-child { border-right: 0; }
body main.lu-page .detail-meta dd { margin: 12px 0 0; font-size: 16px; line-height: 1.4; letter-spacing: 0; color: var(--a-ink); }

/* ---------- screenshots: full width, in colour, ruled ---------- */
body main.lu-page .detail-hero, body main.lu-page .case-shot {
  width: 100%; max-width: none; margin: 0 !important; padding: 0; border-radius: 0;
  background: var(--a-ground); border-bottom: 1px solid var(--a-ink);
}
body main.lu-page .detail-hero img, body main.lu-page .case-shot img { display: block; width: 100%; height: auto; border-radius: 0; filter: none; }

/* ---------- body: each section a row, sticky title | readable column ---------- */
body main.lu-page .detail-body { padding: 0; background: #fff; }
body main.lu-page .detail-body .wrap { width: 100%; max-width: none !important; margin: 0; padding: 0; container-type: normal; }
body main.lu-page .detail-section {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 2fr); align-content: start;
  margin: 0; padding: 0 0 60px; border-bottom: 1px solid var(--a-ink);
  background: linear-gradient(var(--a-ink), var(--a-ink)) calc(100% / 3) 0 / 1px 100% no-repeat;
}
body main.lu-page .detail-section > h2 {
  grid-column: 1; grid-row: 1 / span 99; align-self: start; position: sticky; top: calc(var(--a-top) + 1px);
  margin: 0; padding: var(--a-pad); font-size: clamp(22px, 2.2vw, 32px); font-weight: 450; line-height: 1.15; letter-spacing: -.03em; text-wrap: balance;
}
body main.lu-page .detail-section > :not(h2) { grid-column: 2; max-width: 720px; margin: 16px var(--a-pad) 0; }
body main.lu-page .detail-section > h2 + * { margin-top: var(--a-pad); }
body main.lu-page .detail-section:not(:has(> h2)) > * { grid-column: 1 / -1; max-width: none; }
body main.lu-page .detail-section:not(:has(> h2)) { background: none; }
body main.lu-page .detail-section p, body main.lu-page .detail-section li { font-size: 16px; line-height: 1.8; letter-spacing: 0; color: var(--a-ink); }
body main.lu-page .detail-section h3 { margin-top: 36px; font-size: 20px; font-weight: 500; line-height: 1.3; letter-spacing: -.02em; }
body main.lu-page .detail-section strong { font-weight: 600; }
body main.lu-page .detail-section a { color: inherit; text-decoration: underline; text-decoration-color: var(--a-pink); text-decoration-thickness: 2px; text-underline-offset: 3px; }
body main.lu-page .detail-section ul { padding: 0; list-style: none; }
body main.lu-page .detail-section ul li { position: relative; padding-left: 20px; }
body main.lu-page .detail-section ul li + li { margin-top: 10px; }
body main.lu-page .detail-section ul li::before { content: ""; position: absolute; left: 0; top: .72em; width: 8px; height: 8px; background: var(--a-pink); }
body main.lu-page .table-wrap { overflow-x: auto; border-top: 1px solid var(--a-ink); }
body main.lu-page .detail-section table { width: 100%; min-width: 0; border-collapse: collapse; font-size: 14px; }
body main.lu-page .detail-section th { padding: 12px 10px; text-align: left; font-family: var(--a-mono); font-size: 12px; font-weight: 400; text-transform: uppercase; background: var(--a-grey); border-bottom: 1px solid var(--a-ink); }
body main.lu-page .detail-section td { padding: 12px 10px; vertical-align: top; line-height: 1.6; border-bottom: 1px solid var(--a-ink); }
body main.lu-page .quote { margin: 0; padding: 60px var(--a-pad) 0; border: 0; }
body main.lu-page .quote p { max-width: 30ch; font-size: clamp(24px, 2.63vw, 38px); line-height: 1.15; letter-spacing: -.03em; }
body main.lu-page .quote footer { margin-top: 24px; font-family: var(--a-mono); font-size: 12px; text-transform: uppercase; }

/* ---------- list pages: hero, case grid, post rows ---------- */
body main.lu .lu-hero-page { min-height: 0; margin: 0; padding: var(--a-pad) var(--a-pad) 48px; border-bottom: 1px solid var(--a-ink); }
body main.lu .lu-hero-page .lu-meta { justify-content: space-between; margin: 0; }
body main.lu .lu-hero-page h1 { margin: 140px 0 0; max-width: none; font-size: clamp(48px, 9vw, 150px); font-weight: 450; line-height: .98; letter-spacing: -.04em; }
body main.lu .lu-hero-page .lu-lede { margin: 40px 0 0 50%; max-width: none; font-size: clamp(18px, 1.7vw, 24px); line-height: 1.3; letter-spacing: -.02em; color: var(--a-ink); }
/* the old lumina rule pads every section; cells run edge to edge here */
body main.lu > section { padding-left: 0 !important; padding-right: 0 !important; }
/* …except the page head and the closing block, whose text sits on the 20px grid inset */
body main.lu > .lu-hero-page, body main.lu > .lu-talk { padding-left: var(--a-pad) !important; padding-right: var(--a-pad) !important; }
body main.lu .lu-works, body main.lu .lu-journal { padding-top: 0; padding-bottom: 0; }
body main.lu .lu-head { margin: 0; padding: 14px var(--a-pad); border-top: 0; border-bottom: 1px solid var(--a-ink); }
body main.lu .lu-count { font-family: var(--a-mono); font-size: 12px; color: var(--a-ink); }
body main.lu .lu-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 0; }
body main.lu .lu-case { display: grid; align-content: start; margin: 0 !important; padding-bottom: 24px; border-right: 1px solid var(--a-ink); border-bottom: 1px solid var(--a-ink); }
body main.lu .lu-case:nth-child(3n) { border-right: 0; }
body main.lu .lu-case-shot { position: relative; grid-area: 1 / 1; aspect-ratio: 4 / 5; overflow: hidden; background: var(--a-grey); }body main.lu .lu-case-shot img { width: 100%; height: 100%; aspect-ratio: auto; object-fit: cover; filter: none; }
@media (hover: hover) {
body main.lu .lu-case:hover .lu-case-shot img { width: 100%; height: 100%; aspect-ratio: auto; object-fit: cover; filter: none; }
}
body main.lu .lu-case-meta { display: contents; }
body main.lu .lu-client, body main.lu .lu-case .lu-cat { position: relative; z-index: 1; grid-area: 1 / 1; margin: 0; pointer-events: none; }
body main.lu .lu-client { align-self: end; min-height: 28%; padding: var(--a-pad); background: var(--a-ink); color: #fff; font-size: clamp(18px, 1.7vw, 24px); font-weight: 450; line-height: 1.2; }
body main.lu .lu-case .lu-cat { align-self: start; justify-self: end; padding: 10px; background: #fff; border-bottom: 1px solid var(--a-ink); border-left: 1px solid var(--a-ink); }
body main.lu .lu-case .lu-cat::before { display: none; }
body main.lu .lu-case-desc { margin: 20px var(--a-pad) 0; max-width: none; font-size: 15px; line-height: 1.7; letter-spacing: 0; color: var(--a-ink); }
body main.lu .lu-case-metrics { margin: 14px var(--a-pad) 0; padding: 0; gap: 8px 16px; font-family: var(--a-mono); font-size: 12px; text-transform: uppercase; color: var(--a-ink); }
body main.lu .lu-case-metrics li { display: flex; align-items: center; gap: 8px; }
body main.lu .lu-case-metrics li::before { content: ""; width: 8px; height: 8px; background: var(--a-pink); }
body main.lu .lu-case-more { margin: 20px var(--a-pad) 0; justify-self: start; border: 0; padding: 0; font-family: var(--a-mono); font-size: 12px; text-transform: uppercase; }

/* free templates: two to a row, because a template is sold on the screenshot.
   The shots are 4:3 browser captures, not the 4:5 crops the case grid uses, and
   each card carries the template's other screens as a 3-up strip. The 1023px
   and 640px rules below already take this grid to 2 and then 1 column. */
body main.lu .tpl-grid { grid-template-columns: repeat(2, 1fr); }
body main.lu .tpl-grid .lu-case:nth-child(3n) { border-right: 1px solid var(--a-ink); }
body main.lu .tpl-grid .lu-case:nth-child(2n) { border-right: 0; }
body main.lu .tpl-grid .lu-case-shot { aspect-ratio: 4 / 3; }
body main.lu .lu-tpl-shots {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 1px;
  margin: 20px var(--a-pad) 0; padding: 0; list-style: none;
  background: var(--a-ink); border: 1px solid var(--a-ink);
}
body main.lu .lu-tpl-shots img { display: block; width: 100%; aspect-ratio: 4 / 3; object-fit: cover; background: var(--a-grey); }
body main.lu .lu-more { margin: 0; padding: 18px var(--a-pad); border-top: 0; border-bottom: 1px solid var(--a-ink); }
body main.lu .lu-post { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 2fr); gap: 0; align-items: stretch; min-height: 150px; padding: 0; border-top: 0; border-bottom: 1px solid var(--a-ink); transition: background-color .3s var(--a-ease); }@media (hover: hover) {
body main.lu .lu-post:hover { background: var(--a-pink); color: var(--a-on-pink); opacity: 1; }
}@media (hover: hover) {
body main.lu .lu-post:hover :is(.lu-post-meta, .lu-post-title, .lu-post-desc) { color: inherit; }
}
body main.lu .lu-post-meta { align-items: flex-start; padding: var(--a-pad); border-right: 1px solid var(--a-ink); }
body main.lu .lu-post-body { padding: var(--a-pad); }
body main.lu .lu-post-title { display: block; max-width: 34ch; font-size: clamp(20px, 1.8vw, 28px); font-weight: 450; line-height: 1.25; letter-spacing: -.03em; }
body main.lu .lu-post-desc { margin-top: 12px; max-width: 60ch; font-size: 15px; line-height: 1.7; letter-spacing: 0; color: var(--a-ink); }

/* ---------- closing: an ink block with the accent button ---------- */
body main.lu-page .closing, body main.lu .lu-talk { margin: 0; padding: 0; background: var(--a-ink); border-top: 0; color: #fff; text-align: left; }
body main.lu-page .closing .wrap, body main.lu .lu-talk {
  display: flex; flex-direction: column; justify-content: space-between; align-items: flex-start; gap: 60px;
  width: 100%; max-width: none; min-height: 420px; margin: 0; padding: var(--a-pad);
}
body main.lu-page .closing h2, body main.lu .lu-talk h2 { max-width: 20ch; margin: 0; font-size: clamp(26px, 2.63vw, 38px); font-weight: 450; line-height: 1.1; letter-spacing: -.03em; color: inherit; text-align: left; }
body main.lu .lu-talk h2 span { display: block; }
body main.lu-page .closing p, body main.lu .lu-talk-note { max-width: 44ch; margin: 0; font-size: 16px; line-height: 1.6; letter-spacing: 0; color: inherit; }
body main.lu-page .closing .btn, body main.lu .lu-talk-btn {
  display: inline-flex; align-items: center; justify-content: space-between; gap: 12px;
  width: 200px; height: 36px; margin: 0; padding: 0 12px; border: 0; border-radius: 0;
  background: var(--a-pink); color: var(--a-on-pink); box-shadow: none;
  font-family: var(--a-mono); font-size: 12px; font-weight: 400; letter-spacing: -.04em; text-transform: uppercase;
  transition: background-color .3s var(--ease), color .3s var(--ease);
}@media (hover: hover) {
body main.lu-page .closing .btn:hover, body main.lu .lu-talk-btn:hover { background: #fff; color: var(--a-ink); transform: none; }
}
body main.lu-page .closing .btn img { display: none; }
body main.lu-page .closing .btn::after { content: ""; width: 12px; height: 12px; background: currentColor; -webkit-mask: var(--a-arrow) center / contain no-repeat; mask: var(--a-arrow) center / contain no-repeat; }
body main.lu .lu-talk .lu-tag { display: none; }

/* ---------- footer (shared): the homepage's grid, in short ---------- */
body:is(:has(main.lu), :has(main.lu-page)) .footer { padding: 0; background: #fff; border-top: 1px solid var(--a-ink); }
body:is(:has(main.lu), :has(main.lu-page)) .footer-inner { display: grid; grid-template-columns: 1fr 1fr; width: 100%; max-width: none; margin: 0; padding: 0; gap: 0; }
body:is(:has(main.lu), :has(main.lu-page)) .footer .logo { grid-column: 1; min-height: 240px; padding: var(--a-pad); border-right: 1px solid var(--a-ink); }
body:is(:has(main.lu), :has(main.lu-page)) .footer-links { grid-column: 2; display: grid; grid-template-columns: 1fr 1fr; align-content: start; gap: 12px var(--a-pad); padding: var(--a-pad); }
body:is(:has(main.lu), :has(main.lu-page)) .footer-links a { font-family: var(--sans); font-size: 16px; text-transform: none; letter-spacing: -.04em; color: var(--a-ink); }
body:is(:has(main.lu), :has(main.lu-page)) .footer-meta { grid-column: 1 / -1; display: flex; align-items: center; justify-content: space-between; gap: var(--a-pad); padding: var(--a-pad); background: var(--a-ink); color: rgba(255, 255, 255, .65); }
body:is(:has(main.lu), :has(main.lu-page)) .footer-meta a, body:is(:has(main.lu), :has(main.lu-page)) .footer-meta .copyright { color: rgba(255, 255, 255, .8); font-family: var(--a-mono); font-size: 12px; text-transform: uppercase; }

@media (max-width: 1023px) {
  body main.lu-page .detail-head .wrap, body main.lu .lu-hero-page { padding: 20px 12px 40px; }
  body main.lu-page .detail-head .client, body main.lu .lu-hero-page h1 { margin-top: 100px; }
  body main.lu-page .detail-head .lede, body main.lu .lu-hero-page .lu-lede { margin-left: 0; }
  body main.lu-page .detail-meta { grid-template-columns: 1fr 1fr; margin: 40px -12px -40px; }
  body main.lu-page .detail-meta > div { padding: 12px; border-bottom: 1px solid var(--a-ink); }
  body main.lu-page .detail-meta > div:nth-child(2n) { border-right: 0; }
  body main.lu-page .detail-section { grid-template-columns: 1fr; background: none; padding-bottom: 40px; }
  body main.lu-page .detail-section > h2 { position: static; grid-row: auto; padding: 20px 12px 0; }
  body main.lu-page .detail-section > :not(h2) { grid-column: 1; margin-left: 12px; margin-right: 12px; }
  body main.lu .lu-grid { grid-template-columns: 1fr 1fr; }
  body main.lu .lu-case:nth-child(3n) { border-right: 1px solid var(--a-ink); }
  body main.lu .lu-case:nth-child(2n) { border-right: 0; }
  body main.lu .lu-post { grid-template-columns: 1fr; }
  body main.lu .lu-post-meta { border-right: 0; padding-bottom: 0; }
  body main.lu-page .closing .wrap, body main.lu .lu-talk { min-height: 300px; padding: 20px 12px; }
  body:is(:has(main.lu), :has(main.lu-page)) .footer-inner { grid-template-columns: 1fr; }
  body:is(:has(main.lu), :has(main.lu-page)) .footer .logo { min-height: 120px; border-right: 0; border-bottom: 1px solid var(--a-ink); }
  body:is(:has(main.lu), :has(main.lu-page)) .footer-links { grid-column: 1; }
  body:is(:has(main.lu), :has(main.lu-page)) .footer-meta { flex-wrap: wrap; }
}
@media (max-width: 640px) {
  body main.lu .lu-grid { grid-template-columns: 1fr; }
  body main.lu .lu-case { border-right: 0 !important; }
  body main.lu-page .detail-meta { grid-template-columns: 1fr; }
  body main.lu-page .detail-meta > div { border-right: 0; }
}

/* ============================================================
   hero, our own: thirds instead of Aspen's checkerboard of halves.
   left third — label, the word, the H1, copy, two buttons; the other
   two thirds — one large dithered stage with the turning mark; a pink
   band of client logos; the slogan on one ink line.
   ============================================================ */
.aspen .a-hero { background: #fff; }
/* Hero in three bands: a rule of small type, the mark across the middle with the
   standfirst and the two calls to action as a full-height column beside it, and
   the name set as large as the width allows along the bottom. The old version
   put the name in a narrow left column, which left a third of the screen empty
   above it and cropped the mark into a strip. */
.aspen .a-hx {
  /* minmax(0, 1fr), not the implicit auto column: the floor's nowrap wordmark is
     max-content, and an auto column sizes to it — on a phone that stretched the
     whole hero to 678px inside a 390px screen */
  display: grid; grid-template-columns: minmax(0, 1fr); grid-template-rows: auto minmax(0, 1fr) auto;
  height: calc(100vh - var(--a-top) - 81px); min-height: 640px;
  border-bottom: 1px solid var(--a-ink);
}
.aspen .a-hx-top {
  display: flex; align-items: center; justify-content: space-between; gap: var(--a-pad);
  padding: 14px var(--a-pad); border-bottom: 1px solid var(--a-ink);
}
.aspen .a-hx-mid { display: grid; grid-template-columns: minmax(0, 1fr) min(400px, 33%); min-height: 0; }
.aspen .a-hx-stage { position: relative; min-height: 0; border-right: 1px solid var(--a-ink); }
/* the standfirst column: copy at the top, the calls to action on the floor */
.aspen .a-hx-note {
  display: flex; flex-direction: column; justify-content: space-between; gap: 32px;
  min-width: 0; padding: var(--a-pad);
}
.aspen .a-hx-txt { color: #fff; font-size: clamp(15px, 1.15vw, 18px); line-height: 1.5; letter-spacing: -.01em; }
.aspen .a-hx-txt > * + * { margin-top: 1em; }
.aspen .a-hx-btns { display: grid; gap: 8px; }
.aspen .a-hx-btns .a-btn { background: #fff; color: var(--a-ink); }
.aspen .a-hx-btns .a-btn-line { background: transparent; color: #fff; box-shadow: inset 0 0 0 1px #fff; }
@media (hover: hover) { .aspen .a-hx-btns .a-btn:hover { color: var(--a-on-pink); } }
/* the floor: tagline small, then the name at the largest size the row can hold */
.aspen .a-hx-foot {
  display: flex; flex-direction: column; justify-content: flex-end; gap: 14px;
  padding: 22px var(--a-pad) 26px; border-top: 1px solid var(--a-ink);
}
.aspen .a-hx-foot h1 { font-size: clamp(14px, 1.15vw, 18px); font-weight: 400; letter-spacing: -.02em; }
/* On the floor the two halves sit on ONE line so the name can run the full
   width and still be short: stacked, a full-width lockup is ~370px tall and
   leaves the mark a strip. Elsewhere (nothing uses it today) it stays stacked. */
/* line-height .84 crops the box above the descender, so the g in Design hangs
   below it; reserve that in the type's own em rather than guessing pixels */
.aspen .a-hx-foot .a-display { font-size: 9.86vw; line-height: .84; white-space: nowrap; padding-bottom: .12em; }
.aspen .a-hx-foot .a-lockup > span { display: inline; }
.aspen .a-hx-foot .a-lockup .a-le { margin-top: 0; }
.aspen .a-lockup > span { display: block; white-space: nowrap; }
.aspen .a-lockup .a-lz { line-height: 1; letter-spacing: 0; }
.aspen .a-lockup .a-le { margin-top: .04em; font-size: .79em; line-height: .9; letter-spacing: -.045em; }
.aspen .a-about-txt p.a-t31 { font-size: max(18px, 1.6vw); line-height: 1.35; }
.aspen .a-hx-band { display: grid; grid-template-columns: 1fr 2fr; height: 80px; background: var(--a-pink); color: var(--a-on-pink); border-bottom: 1px solid var(--a-ink); }
.aspen .a-hx-band .a-label { padding: 0 var(--a-pad); border-right: 1px solid var(--a-ink); }
.aspen .a-hx-band .a-marq { height: 80px; }
.aspen .a-hx-slogan { container-type: inline-size; padding: 28px var(--a-pad) 36px; }
.aspen .a-hx-slogan .a-slogan { flex-direction: row; flex-wrap: wrap; column-gap: .22em; font-size: 13.5cqw; line-height: 1; }
@media (max-width: 1023px) {
  /* phone: the same three bands, stacked — rule, square mark, standfirst,
     then the name across the floor */
  .aspen .a-hx { grid-template-rows: auto auto auto; height: auto; min-height: 0; }
  .aspen .a-hx-top { padding: 12px 12px; }
  .aspen .a-hx-mid { grid-template-columns: 1fr; }
  .aspen .a-hx-stage { aspect-ratio: 1 / 1; min-height: 0; border-right: 0; border-bottom: 1px solid var(--a-ink); }
  .aspen .a-hx-note { gap: 40px; padding: 20px 12px; }
  .aspen .a-hx-foot { gap: 12px; padding: 18px 12px 22px; }
  /* stacked again here: one line would have to drop to ~10vw to fit */
  .aspen .a-hx-foot .a-display { font-size: 19.5vw; white-space: normal; }
  .aspen .a-hx-foot .a-lockup > span { display: block; }
  .aspen .a-hx-foot .a-lockup .a-le { margin-top: .04em; }
  .aspen .a-hx-band { grid-template-columns: 1fr; height: auto; }
  .aspen .a-hx-band .a-label { padding: 14px 12px; border-right: 0; border-bottom: 1px solid var(--a-ink); }
  .aspen .a-hx-slogan { padding: 20px 12px 28px; }
  .aspen .a-hx-slogan .a-slogan { font-size: 17cqw; }
}

/* ============================================================
   the enquiry form, on the site system: a ruled two-column page,
   questions left, a pink panel right; choices are ruled cells that
   turn pink when picked; fields are underlines; buttons are ink.
   ============================================================ */
body main.lu-page .form-page { padding: 0; background: #fff; overflow: visible; }
body main.lu-page .form-layout { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 0; width: 100%; max-width: none; margin: 0; padding: 0; min-height: calc(100vh - var(--a-top)); }
body main.lu-page .form-main { max-width: none; padding: var(--a-pad) var(--a-pad) 80px; border-right: 1px solid var(--a-ink); }
/* the old aside was an absolute, tilted cut-out bleeding off the edge: reset all of it */
body main.lu-page .form-aside { transform: none; left: auto; margin: 0; position: sticky; top: var(--a-top); inset: auto; right: auto; width: auto; height: calc(100vh - var(--a-top)); display: flex; align-items: flex-end; justify-content: center; overflow: hidden; background: var(--a-pink); }
body main.lu-page .form-aside { background: var(--a-ground); }
body main.lu-page .form-intro { max-width: none; margin: 0 0 60px; }
body main.lu-page .form-meta { display: flex; align-items: center; gap: 12px; margin: 0 0 120px; padding: 0; border: 0; background: none; font-family: var(--a-mono); font-size: 12px; font-weight: 400; text-transform: uppercase; letter-spacing: -.04em; color: var(--a-ink); }
body main.lu-page .form-meta .dot { width: 8px; height: 8px; border-radius: 0; background: currentColor; }
body main.lu-page .form-intro h1 { margin: 0; max-width: 16ch; font-family: var(--sans); font-size: clamp(34px, 3.6vw, 56px); font-weight: 450; line-height: 1.06; letter-spacing: -.04em; text-wrap: balance; }
body main.lu-page .form-intro p { margin: 24px 0 0; max-width: 40ch; font-size: 16px; line-height: 1.6; letter-spacing: 0; color: var(--a-ink); }
body main.lu-page .progress { max-width: none; margin: 0 0 40px; }
body main.lu-page .progress-bar { height: 2px; border-radius: 0; background: var(--a-grey); }
body main.lu-page .progress-bar span { border-radius: 0; background: var(--a-pink); }
body main.lu-page .progress-label { font-family: var(--a-mono); font-size: 12px; text-transform: uppercase; color: var(--a-ink); }
body main.lu-page .step .q-num { font-family: var(--a-mono); font-size: 12px; letter-spacing: -.04em; text-transform: uppercase; color: var(--a-ink); }
body main.lu-page .step h2 { font-family: var(--sans); font-size: clamp(24px, 2.2vw, 32px); font-weight: 450; line-height: 1.15; letter-spacing: -.03em; }
body main.lu-page .step .hint, body main.lu-page .contact-hint { font-size: 15px; line-height: 1.6; letter-spacing: 0; color: var(--a-ink); opacity: .7; }
body main.lu-page .choices { gap: 0; max-width: 560px; }
body main.lu-page .choice + .choice span { margin-top: -1px; }
body main.lu-page .choice span { display: block; padding: 18px 20px; border: 1px solid var(--a-ink); border-radius: 0; background: #fff; font-size: 16px; letter-spacing: 0; color: var(--a-ink); transition: background-color .25s var(--a-ease); }@media (hover: hover) {
body main.lu-page .choice span:hover { padding-left: 20px; border-color: var(--a-ink); background: var(--a-grey); }
}
/* the old lumina form drew a bar before each choice and slid the text on
   hover; the ruled cells mark the choice on their own */
body main.lu-page .choice span::before { content: none; display: none; }
body main.lu-page .choice input:checked + span { border-color: var(--a-ink); background: var(--a-pink); color: var(--a-on-pink); }
body main.lu-page .choice input:focus-visible + span { outline: 2px solid var(--a-ink); outline-offset: 2px; }
body main.lu-page .field { max-width: 560px; }
body main.lu-page .field label { font-family: var(--a-mono); font-size: 12px; text-transform: uppercase; letter-spacing: -.04em; color: var(--a-ink); }
body main.lu-page .field input, body main.lu-page .field textarea { width: 100%; padding: 12px 0; border: 0; border-bottom: 1px solid var(--a-ink); border-radius: 0; background: transparent; font-size: 16px; letter-spacing: 0; color: var(--a-ink); }
body main.lu-page .field textarea { padding: 12px; border: 1px solid var(--a-ink); }
body main.lu-page .field input:focus, body main.lu-page .field textarea:focus { border-color: var(--a-pink); box-shadow: 0 1px 0 var(--a-pink); }
body main.lu-page .step-nav { max-width: 560px; margin-top: 40px; }
body main.lu-page .step-nav .btn { display: inline-flex; align-items: center; justify-content: space-between; gap: 12px; width: 200px; height: 36px; padding: 0 12px; border: 0; border-radius: 0; background: var(--a-ink); color: #fff; box-shadow: none; font-family: var(--a-mono); font-size: 12px; font-weight: 400; letter-spacing: -.04em; text-transform: uppercase; }
body main.lu-page .step-nav .btn::after { content: ""; width: 12px; height: 12px; background: currentColor; -webkit-mask: var(--a-arrow) center / contain no-repeat; mask: var(--a-arrow) center / contain no-repeat; }
body main.lu-page .step-nav .btn[hidden] { display: none; }
body main.lu-page .btn-back { font-family: var(--a-mono); font-size: 12px; text-transform: uppercase; letter-spacing: -.04em; color: var(--a-ink); }
body main.lu-page .form-done h1, body main.lu-page .form-done h2 { font-family: var(--sans); font-weight: 450; letter-spacing: -.04em; }
body main.lu-page .form-done p { font-size: 16px; line-height: 1.6; letter-spacing: 0; color: var(--a-ink); }
@media (max-width: 1023px) {
  body main.lu-page .form-layout { grid-template-columns: 1fr; min-height: 0; }
  body main.lu-page .form-main { padding: 20px 12px 60px; border-right: 0; }
  body main.lu-page .form-meta { margin-bottom: 80px; }
  body main.lu-page .form-aside { position: relative; top: auto; left: auto; width: auto; height: 60vw; margin: 0; transform: none; border-top: 1px solid var(--a-ink); }
}
