@font-face {
  font-family: "Schibsted Grotesk";
  src: url(fonts/schibsted-grotesk.woff2) format("woff2");
  font-weight: 400 900;
  font-display: swap;
}

:root {
  --paper: #f4f4f1;
  --stone: #e6e5e0;
  --stone-2: #d3d2cb;
  --white: #ffffff;
  --ink: #15130e;
  --ink-2: #211e17;
  --ink-3: #2d2920;
  --honey: #ffd43b;
  --honey-2: #ffe486;
  --honey-3: #f4c51c;
  --honey-ink: #8f6a00;
  --on-ink: #f4f4f1;

  --m: clamp(20px, 3.4vw, 48px);
  --gap: 8px;
  --f-display: clamp(44px, 8.2vw, 118px);
  --f-h2: clamp(36px, 4.6vw, 66px);
  --f-lead: clamp(19px, 1.6vw, 23px);
  --f-body: 18px;
  --f-small: 16px;
  --ease: cubic-bezier(0.16, 1, 0.3, 1);
  --nav-h: 68px;

  --font: "Schibsted Grotesk", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
}
:root:lang(zh-Hant) { --font: "Schibsted Grotesk", "PingFang TC", "Noto Sans TC", "Noto Sans CJK TC", "Microsoft JhengHei", "Heiti TC", sans-serif; }
:root:lang(zh-Hans) { --font: "Schibsted Grotesk", "PingFang SC", "Noto Sans SC", "Noto Sans CJK SC", "Microsoft YaHei", "Heiti SC", sans-serif; }

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; scroll-padding-top: var(--nav-h); }
body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font);
  font-size: var(--f-body);
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
img, svg { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }
p { margin: 0; text-wrap: pretty; }
h1, h2, h3 { margin: 0; font-weight: 700; text-wrap: balance; }
h2 { font-size: var(--f-h2); line-height: 1; letter-spacing: -0.035em; }
h3 { font-size: var(--f-lead); line-height: 1.2; letter-spacing: -0.01em; font-weight: 650; }
ul, ol { margin: 0; padding: 0; list-style: none; }
button, input, select, textarea { font: inherit; color: inherit; }
:focus-visible { outline: 3px solid var(--honey-ink); outline-offset: 3px; border-radius: 4px; }
::selection { background: var(--honey); color: var(--ink); }
.lead { font-size: var(--f-lead); line-height: 1.45; }
.wrap { width: 100%; max-width: 1680px; margin-inline: auto; padding-inline: var(--m); }
.skip { position: absolute; left: var(--m); top: -60px; z-index: 50; background: var(--ink); color: var(--on-ink); padding: 10px 16px; border-radius: 999px; }
.skip:focus { top: 10px; }

/* ------------------------------------------------------------ buttons */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 10px;
  min-height: 48px; padding: 0 22px; border: 0; border-radius: 999px;
  font-size: 16px; font-weight: 600; line-height: 1.1; letter-spacing: -0.005em;
  cursor: pointer; white-space: nowrap;
  transition: transform 0.25s var(--ease), background-color 0.25s ease, color 0.25s ease;
}
.btn:active { transform: scale(0.97); }
.btn .ar { width: 18px; height: 18px; flex: none; transition: transform 0.3s var(--ease); }
.btn:hover .ar { transform: translateX(3px); }
.btn-lg { min-height: 56px; padding: 0 28px; font-size: var(--f-body); }
.btn-honey { background: var(--honey); color: var(--ink); }
.btn-honey:hover { background: var(--honey-3); }
.btn-stone { background: var(--stone); color: var(--ink); }
.btn-stone:hover { background: var(--stone-2); }
.btn-ink { background: var(--ink); color: var(--on-ink); }
.btn-ink:hover { background: var(--ink-3); }

/* ------------------------------------------------------------ header: one plain bar, the same everywhere */
.nav { position: sticky; top: 0; z-index: 30; background: var(--paper); color: var(--ink); }
.nav-inner { display: flex; align-items: center; gap: 40px; height: var(--nav-h); }
.brand { display: flex; align-items: center; flex: none; }
.brand .logo { height: 27px; width: auto; }
.nav-links { display: flex; gap: 30px; font-size: 16px; font-weight: 500; }
.nav-links a, .lang a { text-decoration: underline 2px transparent; text-underline-offset: 6px; transition: text-decoration-color 0.2s ease; }
.nav-links a:hover, .lang a:hover { text-decoration-color: var(--honey); }
.nav-right { margin-left: auto; display: flex; align-items: center; gap: 28px; }
.lang { display: flex; gap: 14px; font-size: 16px; font-weight: 500; }
.lang a[aria-current] { font-weight: 700; text-decoration-color: currentColor; }
.nav-toggle { display: none; width: 44px; height: 44px; border: 0; background: none; cursor: pointer; }
.nav-toggle span, .nav-toggle span::before { display: block; width: 20px; height: 2px; margin: auto; background: currentColor; transition: transform 0.3s var(--ease); }
.nav-toggle span { position: relative; transform: translateY(-3px); }
.nav-toggle span::before { content: ""; position: absolute; left: 0; top: 6px; }
.nav-toggle[aria-expanded="true"] span { transform: rotate(45deg); }
.nav-toggle[aria-expanded="true"] span::before { transform: translateY(-6px) rotate(-90deg); }
.nav-mobile { position: absolute; left: 0; right: 0; top: var(--nav-h); background: var(--paper); box-shadow: 0 24px 40px -24px rgba(21, 19, 14, 0.35); } /* taste-skill-ignore: the open menu really floats */
.nav-mobile nav { display: flex; flex-direction: column; gap: 6px; padding-block: 12px 28px; font-size: 23px; font-weight: 650; letter-spacing: -0.02em; }
.nav-mobile nav a:not(.btn) { padding: 6px 0; }
.nav-mobile .btn { margin-top: 14px; align-self: stretch; }

/* ------------------------------------------------------------ hero (original composition, original copy) */
.hero {
  position: relative; display: flex; align-items: center; overflow: hidden;
  min-height: calc(100svh - var(--nav-h)); padding: 72px 0 104px; background: var(--paper);
}
.hero-pipe { position: absolute; inset: 0; pointer-events: none; contain: strict; }
.hero-pipe canvas { position: absolute; inset: 0; width: 100%; height: 100%; }
.hero-pipe .pipes-static { opacity: 0; transition: opacity 1.2s ease; }
.hero-pipe.on .pipes-static { opacity: 1; }
.hero-inner { position: relative; z-index: 1; text-align: center; }
.hero-h { max-width: 16ch; margin: 0 auto; font-size: var(--f-display); line-height: 0.98; letter-spacing: -0.035em; }
.hero-h .line { display: block; overflow: hidden; padding-bottom: 0.1em; margin-bottom: -0.1em; }
.hero-h .line-in { display: inline-block; }
.hero-h .hl { color: var(--honey-ink); }
.hero-sub { max-width: 58ch; margin: 30px auto 0; font-size: var(--f-lead); line-height: 1.5; }
.hero-sub strong { font-weight: 650; }
.hero-cta { display: flex; flex-wrap: wrap; justify-content: center; gap: 12px; margin-top: 40px; }
.hero-scroll { position: absolute; z-index: 1; left: calc(50% - 22px); bottom: 18px; width: 44px; height: 64px; display: grid; place-items: center; }
.hero-scroll span { position: relative; width: 2px; height: 44px; background: color-mix(in srgb, var(--ink) 18%, transparent); overflow: hidden; border-radius: 2px; }
.hero-scroll span::after { content: ""; position: absolute; left: 0; top: 0; width: 2px; height: 14px; background: var(--honey-3); animation: drip 2.4s var(--ease) infinite 2s; transform: translateY(-14px); }
@keyframes drip { 0% { transform: translateY(-14px); } 70%, 100% { transform: translateY(46px); } }

@media (prefers-reduced-motion: no-preference) {
  .hero-h .line-in { animation: rise 1.1s var(--ease) both; animation-delay: calc(var(--i) * 120ms + 60ms); }
  .hero-sub { animation: fade-up 0.9s var(--ease) both 0.42s; }
  .hero-cta > * { animation: fade-up 0.8s var(--ease) both; }
  .hero-cta > :first-child { animation-delay: 0.56s; }
  .hero-cta > :last-child { animation-delay: 0.66s; }
  .hero-scroll { animation: fade-up 0.8s var(--ease) both 0.9s; }
}
@keyframes rise { from { transform: translateY(108%); } }
@keyframes fade-up { from { opacity: 0; transform: translateY(22px); } }

/* ------------------------------------------------------------ below the hero
   Paper and ink, honey for action and emphasis. Sizes: 16 / 18 / 23 / h2 / display (the
   hero's own size, reused for the big moments). One 12-column grid, one pair of margins.
   Everything is visible without script; motion only adds an entrance once in view. */
:root {
  --f-h2: clamp(32px, 3.6vw, 52px);
  --line: rgba(21, 19, 14, 0.24);
  --on-ink-2: rgba(244, 244, 241, 0.72);
  --sec: clamp(120px, 12vw, 200px);
  --g: 24px;                              /* the one column gap */
  --gap-head: clamp(28px, 3vw, 48px);     /* a heading to the text it opens */
  --gap-block: clamp(48px, 5vw, 80px);    /* one block to the next inside a section */
  --mx: max(var(--m), (100% - 1680px) / 2 + var(--m)); /* a full-bleed field's padding that lands on the container's edge */
}
.grid, .stack .wrap, .work .wrap, .start-grid, .contact-grid, .foot-grid, .legal-grid {
  display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: var(--g);
}
main > section:not(.hero) { position: relative; padding-block: var(--sec) 0; }
/* a section on its own field closes with the same space it opens with */
main > section.work { padding-bottom: var(--sec); }
main > section:last-child { padding-bottom: var(--sec); }
.display { font-size: var(--f-display); line-height: 0.96; letter-spacing: -0.045em; font-weight: 700; }
.statement { font-size: clamp(23px, 2.1vw, 30px); line-height: 1.28; letter-spacing: -0.015em; font-weight: 500; }
.mask { display: block; overflow: hidden; padding-bottom: 0.12em; margin-bottom: -0.12em; }
.mask > span { display: block; }
a.u, .visit a, .steps a, .contact-mail a, .foot a, .note a, .legal-body a {
  text-decoration: underline 2px; text-decoration-color: color-mix(in srgb, currentColor 32%, transparent);
  text-underline-offset: 6px; transition: text-decoration-color 0.2s ease, color 0.2s ease;
}
.visit a:hover, .steps a:hover, .contact-mail a:hover, .foot a:hover, .note a:hover, .legal-body a:hover { text-decoration-color: var(--honey); }

/* the thread: pipes in the hero's style, in the gaps between sections */
.thread { position: relative; grid-column: 1 / -1; height: clamp(72px, 8vw, 128px); margin-top: calc(var(--sec) * -1 + 8px); margin-bottom: clamp(24px, 2.4vw, 40px); pointer-events: none; }
.thread svg { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
.pipe-line, .pipe-pulse { fill: none; vector-effect: non-scaling-stroke; stroke-linecap: round; }
.pipe-line { stroke: var(--line); stroke-width: 1.25; }
.pipe-pulse { stroke: var(--honey); stroke-width: 2.6; stroke-dasharray: 0.06 1; opacity: 0; }
.node { position: absolute; width: 9px; height: 9px; margin: -4.5px 0 0 -4.5px; border-radius: 50%; background: var(--paper); box-shadow: inset 0 0 0 1.25px rgba(21, 19, 14, 0.5); } /* taste-skill-ignore: a pipe node's ring, as in the hero */
.node-end { background: var(--ink); box-shadow: none; } /* taste-skill-ignore: removes the ring */
.thread.px .pipe-line, .thread.px .pipe-pulse { vector-effect: none; }
.thread-ink .pipe-line { stroke: rgba(244, 244, 241, 0.3); }
.thread-ink .node { background: var(--ink); box-shadow: inset 0 0 0 1.25px rgba(244, 244, 241, 0.6); } /* taste-skill-ignore: a pipe node's ring */
.thread-ink .node-end { background: var(--honey); box-shadow: none; } /* taste-skill-ignore: removes the ring */
/* Hero to Stack: the thread starts just under the hero's scroll cue, so the cue plugs into it. */
.thread-hero { margin-top: calc(var(--sec) * -1 - 10px); height: calc(clamp(72px, 8vw, 128px) + 18px); }
/* Stack to Work: the pipe leaves the services down the left lane and runs on, unbroken, into the
   ink, where .thread-ink picks it up at the section's top edge and ends on the Work heading. */
.thread-out { margin: var(--gap-block) 0 0; height: var(--sec); }
.thread-ink { margin-top: calc(var(--sec) * -1); }

/* The seam: the ink of Work rises first under the right half, on the column-7 line where the
   service sentences sit, and steps down to the left in an S of two quarter turns, the same
   rounded corner the pipe takes down "Get started". The left lane, where the pipe crosses, meets
   the ink last. Flat fills only; the fillet is a paper quarter-circle over an ink square. */
:root { --seam: clamp(48px, 7vw, 120px); --sx: calc(50% + var(--g) / 2); }
.seam { position: absolute; left: 0; right: 0; bottom: 0; height: var(--seam); pointer-events: none; }
.seam::before { content: ""; position: absolute; top: 0; bottom: 0; left: var(--sx); right: 0; background: var(--ink); border-top-left-radius: calc(var(--seam) / 2); }
.seam i { position: absolute; bottom: 0; left: calc(var(--sx) - var(--seam) / 2); width: calc(var(--seam) / 2); height: calc(var(--seam) / 2); background: var(--ink); }
.seam i::before { content: ""; position: absolute; inset: 0; background: var(--paper); border-bottom-right-radius: 100%; }

/* stack: the heading at display size, the lede as a statement, the services as a large list */
.stack h2 { grid-column: 1 / -1; }
.stack-lede { grid-column: 1 / span 8; margin-top: var(--gap-head); }
.services { grid-column: 1 / -1; margin-top: var(--gap-block); }
.services li {
  --svc-pad: clamp(14px, 1.4vw, 22px);
  position: relative; display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: var(--g); align-items: baseline;
  padding-block: var(--svc-pad); transition: opacity 0.35s ease;
}
.services h3 { grid-column: 1 / span 6; font-size: var(--f-h2); line-height: 1.04; letter-spacing: -0.03em; font-weight: 700; }
.svc-link { display: flex; align-items: center; }
/* the whole row is the link's hit area */
.svc-link::after { content: ""; position: absolute; inset: 0; }
.svc-link:focus-visible { outline: none; }
.services li:has(.svc-link:focus-visible) { outline: 3px solid var(--honey-ink); outline-offset: 2px; }
.svc-link > span:first-child { flex: none; max-width: calc(100% - 64px); position: relative; z-index: 0; }
.svc-link > span:first-child::after {
  content: ""; position: absolute; z-index: -1; left: -0.08em; right: -0.08em; bottom: 0.04em; height: 0.36em;
  background: var(--honey); transform: scaleX(0); transform-origin: left; transition: transform 0.5s var(--ease);
}
.services p { grid-column: 7 / -1; max-width: min(52ch, 100% - 48px); } /* the last 48px are the arrow's lane */
/* Side by side, a name and its sentence share one top line: the cap height in English, the top of
   the ideographs in Chinese (offsets measured from the face's baseline and glyph heights), and
   every row takes the height of the tallest, so the sentences fall on one even pitch. */
@media (min-width: 1101px) {
  .services { display: grid; grid-auto-rows: 1fr; }
  .services li { align-items: start; }
  /* both boxes start at their own cap line, so top-aligned boxes are aligned type */
  .svc-link > span:first-child, .services p { text-box: trim-start cap alphabetic; }
  /* ideographs stand above the Latin cap line by 0.135em (bold name) and 0.111em (sentence) */
  :lang(zh-Hant) .services p, :lang(zh-Hans) .services p { margin-top: calc(var(--f-h2) * -0.135 + 0.111em); }
  .svc-go { top: calc(var(--svc-pad) + var(--f-h2) * 0.347 - 11px); }
}
/* the affordance: an arrow at the row's end, level with the name; it firms up and steps forward on
   hover, and stays shown on touch screens, where a press gives the same answer */
.svc-go { position: absolute; right: 6px; top: calc(var(--svc-pad) + var(--f-h2) * 0.52 - 11px); width: 22px; height: 22px; display: grid; place-items: center; color: var(--ink); opacity: 0.32; transition: opacity 0.25s ease, transform 0.35s var(--ease); pointer-events: none; }
.svc-go .ar { width: 22px; height: 22px; }
/* the hover pipe runs from the end of the name to the column line where the sentence starts */
.svc-pipe { position: relative; flex: 1 1 auto; min-width: 40px; height: 12px; margin-left: 28px; }
.svc-pipe b { position: absolute; left: 4px; right: 4px; top: 5.5px; height: 1.25px; background: var(--line); transform: scaleX(0); transform-origin: left; transition: transform 0.6s var(--ease); }
.svc-pipe em { position: absolute; left: 4px; right: 4px; top: 4.8px; height: 2.6px; opacity: 0; }
.svc-pipe em::after { content: ""; position: absolute; left: 0; top: 0; width: 36px; height: 100%; border-radius: 2px; background: var(--honey-3); }
.svc-pipe .node { top: 6px; left: 0; opacity: 0; transition: opacity 0.3s ease; }
.svc-pipe .node-end { left: 100%; background: var(--honey); }
@media (hover: hover) {
  .services:hover li:not(:hover) { opacity: 0.34; }
  .services li:hover .svc-link > span:first-child::after { transform: scaleX(1); }
  .services li:hover .svc-pipe b { transform: scaleX(1); }
  .services li:hover .svc-pipe .node { opacity: 1; }
  .services li:hover .svc-pipe .node-end { transition-delay: 0.45s; }
  .services li:hover .svc-pipe em { animation: pulse-run 1.1s var(--ease) 0.25s both; }
  .services li:hover .svc-go, .services li:has(.svc-link:focus-visible) .svc-go { opacity: 1; transform: translateX(6px); }
}
@media (hover: none) {
  .svc-go { opacity: 0.8; }
  .services li:active .svc-go { opacity: 1; transform: translateX(6px); }
  .services li:active .svc-link > span:first-child::after { transform: scaleX(1); transition-duration: 0.2s; }
}
@keyframes pulse-run { 0% { opacity: 1; transform: translateX(0); } 85% { opacity: 1; } 100% { opacity: 0; transform: translateX(calc(100% - 36px)); } }

/* work: the ink field. Big names, real screenshots layered in browser windows */
.work { background: var(--ink); color: var(--on-ink); }
.work ::selection { background: var(--honey); color: var(--ink); }
.work-head { grid-column: 1 / -1; display: grid; grid-template-columns: subgrid; row-gap: var(--gap-head); }
.work-head h2 { grid-column: 1 / -1; }
.work-head .lead { grid-column: 7 / -1; color: var(--on-ink-2); }
.proj { grid-column: 1 / -1; margin-top: var(--sec); }
/* the name takes what the meta leaves and breaks in balance; the meta sits on its last baseline */
.proj-top { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: end; gap: 12px var(--g); }
.proj-name { font-size: var(--f-display); line-height: 0.96; letter-spacing: -0.045em; font-weight: 700; }
.proj-meta { display: flex; flex-direction: column; align-items: flex-end; text-align: right; padding-bottom: 0.6em; font-size: 16px; color: var(--on-ink-2); }
.proj-meta span:first-child { color: var(--on-ink); font-weight: 600; }

/* The stage is its own 12-column grid. Every main window spans --span0 columns, every plate 4.
   Each layer's height is known from its picture's ratio (--r, set by build.py) and the bar, so a
   "low" plate hangs exactly --hang below the main window and a "high" plate rises --hang above it. */
.stage {
  position: relative; container-type: inline-size; display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: var(--sg);
  margin-top: clamp(40px, 4vw, 64px); --sg: var(--g); --span0: 9; --hang: clamp(32px, 4.4vw, 72px); --barh: clamp(22px, 2.2vw, 32px);
}
.layer {
  grid-row: 1; position: relative; align-self: start; --span: 4;
  grid-column: var(--col) / span var(--span);
  --w: calc(var(--span) * (100cqw - 11 * var(--sg)) / 12 + (var(--span) - 1) * var(--sg));
  --h: calc(var(--w) * var(--r) + var(--bar) * var(--barh));
}
.layer.main { --span: var(--span0); }
.layer.low { margin-top: calc((var(--span0) * (100cqw - 11 * var(--sg)) / 12 + (var(--span0) - 1) * var(--sg)) * var(--r0) + var(--barh) - var(--h) + var(--hang)); }
.stage:has(.high) .layer.main { margin-top: var(--hang); }
.frame { margin: 0; overflow: hidden; border-radius: 8px; background: var(--ink-3); transition: transform 0.7s var(--ease); }
/* a window laid over another is cut out of it by a band of the ground: depth from the ground itself */
.layer:not(.layer-0) .frame { outline: clamp(6px, 0.7vw, 12px) solid var(--ink); }
.frame-bar { display: flex; align-items: center; gap: 6px; height: var(--barh); padding-inline: 12px; background: #2a2720; color: var(--on-ink-2); font-size: 13px; }
.frame-bar i { width: 8px; height: 8px; border-radius: 50%; background: rgba(244, 244, 241, 0.22); flex: none; }
.frame-bar span { flex: 1; text-align: center; padding-right: 42px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; letter-spacing: 0.01em; }
.frame img { width: 100%; height: auto; }
.layer-0 { z-index: 1; } .layer-1 { z-index: 2; } .layer-2 { z-index: 3; } .layer-3 { z-index: 4; }
/* main windows alternate sides; plates lie over the main window's outer column only */
/* GoPlace: the guest's home screen on the left, the two booking steps over its right edge, one above, one below */
.stage-fan .layer-0 { --col: 1; } .stage-fan .layer-1, .stage-fan .layer-2 { --col: 9; }
/* Tai Tat Dei: the site on the right, its three tools in a row over the bottom edge */
.stage-spread .layer-0 { --col: 4; } .stage-spread .layer-1 { --col: 1; } .stage-spread .layer-2 { --col: 5; } .stage-spread .layer-3 { --col: 9; }
/* WP Legal: on the left, a detail plate over the bottom right */
.stage-wide .layer-0 { --col: 1; } .stage-wide .layer-1 { --col: 9; }
/* Help Me Clean: on the right, the plate leaning in from the left */
.stage-lean .layer-0 { --col: 4; } .stage-lean .layer-1 { --col: 1; }
/* Yuki Yellow: on the left, its own navigation and language switch above the top right corner */
.stage-crown .layer-0 { --col: 1; } .stage-crown .layer-1 { --col: 9; }
@media (hover: hover) {
  .stage:hover .layer-0 .frame { transform: scale(1.012); }
  .stage:hover .layer-1 .frame { transform: translate(-14px, 10px) rotate(-0.6deg); }
  .stage:hover .layer-2 .frame { transform: translate(10px, 18px) rotate(0.5deg); }
  .stage:hover .layer-3 .frame { transform: translate(16px, -8px) rotate(0.6deg); }
  .stage .high .frame, .stage:hover .high .frame { transform: none; }
  .stage:hover .layer.high .frame { transform: translate(10px, -10px) rotate(0.5deg); }
}

.proj-copy { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: var(--g); margin-top: var(--gap-block); }
.proj-desc { grid-column: 1 / span 5; display: grid; gap: 14px; align-content: start; }
.proj-desc p:first-child { font-size: var(--f-lead); line-height: 1.4; }
.proj-desc p:not(:first-child):not(.visit) { color: var(--on-ink-2); }
.visit { margin-top: 14px; font-size: var(--f-lead); font-weight: 650; }
.work .visit a { color: var(--honey); text-decoration-color: rgba(255, 212, 59, 0.35); }
.work .visit a:hover { text-decoration-color: var(--honey); }
.proj-list { grid-column: 7 / span 6; display: grid; align-content: start; gap: 12px; font-size: 16px; line-height: 1.5; color: var(--on-ink-2); }
.proj-list li { position: relative; padding-left: 22px; }
.proj-list li::before { content: ""; position: absolute; left: 0; top: 0.62em; width: 8px; height: 8px; border-radius: 50%; background: var(--honey); }

/* get started: the heading holds while four steps descend a pipe */
.start-head { grid-column: 1 / -1; }
.start-head h2 { font-size: var(--f-h2); line-height: 1.02; letter-spacing: -0.035em; }
.steps-wrap { grid-column: 1 / -1; position: relative; margin-top: var(--gap-block); }
/* desktop: four equal steps of three columns each, each a tread lower than the last; the pipe
   runs along the top of every tread and drops down the gutter in front of the next */
.steps {
  position: relative; display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); column-gap: var(--g); align-items: start;
  --stair: clamp(40px, 4.4vw, 72px); --tread: 32px; padding-top: var(--tread);
}
.step { margin-top: calc(var(--k) * var(--stair)); }
.step h3 { font-size: var(--f-h2); line-height: 1.02; letter-spacing: -0.03em; font-weight: 700; }
.step p { margin-top: 16px; }
.step a { display: inline-block; margin-top: 14px; font-weight: 650; }
.steps-pipe { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; pointer-events: none; }
.steps-pipe .pipe-line, .steps-pipe .pipe-pulse { vector-effect: none; }
.steps-pipe circle { fill: var(--paper); stroke: rgba(21, 19, 14, 0.5); stroke-width: 1.25; }
.steps-pipe circle:last-of-type { fill: var(--honey); stroke: none; }

/* the closing band: one honey field, the call to action at display size */
section.band { padding: var(--sec) 0 0; }
.band-link {
  position: relative; display: grid; grid-template-columns: auto 1fr auto; grid-template-rows: 1fr auto; column-gap: clamp(24px, 3vw, 48px); isolation: isolate; overflow: hidden;
  min-height: min(64svh, 640px); padding: var(--gap-head) var(--mx); background: var(--honey); color: var(--ink);
}
.band-link::before { content: ""; position: absolute; inset: 0; z-index: -1; background: var(--ink); transform: scaleY(0); transform-origin: bottom; transition: transform 0.6s var(--ease); }
.band-note { grid-column: 1; grid-row: 1; max-width: 30ch; font-size: var(--f-lead); line-height: 1.4; font-weight: 600; transition: color 0.3s ease; }
.band-ar { grid-column: 3; grid-row: 1; width: clamp(40px, 4.4vw, 64px); height: auto; transition: transform 0.5s var(--ease), color 0.3s ease; }
.band-word { grid-column: 1 / -1; grid-row: 2; padding-bottom: 0.1em; /* the descenders, so the word clears the edge by the same space as the note */ font-size: clamp(48px, 14.4vw, 246px); line-height: 0.9; letter-spacing: -0.05em; font-weight: 800; white-space: nowrap; transition: color 0.3s ease; }
:lang(zh-Hant) .band-word, :lang(zh-Hans) .band-word { font-size: clamp(64px, 22.6vw, 370px); letter-spacing: 0; }
/* the pipe across the band's top row, from the sentence to the arrow */
.band-pipe { grid-column: 2; grid-row: 1; position: relative; height: 12px; margin-top: 0.7em; }
.band-pipe b { position: absolute; left: 4px; right: 4px; top: 5.4px; height: 1.25px; background: currentColor; opacity: 0.45; }
.band-pipe .node { top: 6px; left: 0; background: var(--honey); box-shadow: inset 0 0 0 1.25px currentColor; } /* taste-skill-ignore: a pipe node's ring */
.band-pipe .node-end { left: 100%; background: currentColor; box-shadow: none; } /* taste-skill-ignore: removes the ring */
.band-pipe em { position: absolute; left: 4px; right: 4px; top: 4.8px; height: 2.6px; opacity: 0; }
.band-pipe em::after { content: ""; position: absolute; left: 0; top: 0; width: 48px; height: 100%; border-radius: 2px; background: var(--honey); }
.band-link:hover .band-pipe em { animation: pulse-run-band 1.2s var(--ease) both; }
.band-link:hover .band-pipe .node { background: var(--ink); }
@keyframes pulse-run-band { 0% { opacity: 1; transform: translateX(0); } 85% { opacity: 1; } 100% { opacity: 0; transform: translateX(calc(100% - 48px)); } }
.band-link:hover::before, .band-link:focus-visible::before { transform: scaleY(1); }
.band-link:hover, .band-link:focus-visible { color: var(--honey); }
.band-link:hover .band-note, .band-link:focus-visible .band-note { color: var(--on-ink); }
.band-link:hover .band-ar { transform: translate(6px, -6px); }
.band-link:focus-visible { outline: 3px solid var(--ink); outline-offset: 4px; border-radius: 0; }

/* contact */
.contact h2 { grid-column: 1 / -1; }
.contact-copy { grid-column: 1 / span 5; grid-row: 2; display: flex; flex-direction: column; justify-content: space-between; gap: 36px; margin-top: var(--gap-block); align-self: stretch; }
.contact-mail a { font-size: var(--f-h2); line-height: 1.05; letter-spacing: -0.03em; font-weight: 700; text-decoration-thickness: 4px; text-underline-offset: 10px; text-decoration-color: var(--honey); overflow-wrap: anywhere; }
.contact-mail a:hover { text-decoration-color: var(--ink); }
/* The form sits on an ink panel that rises out of the footer on the right half: the same step
   as the seam between Stack and Work, so the page opens and closes its ink the same way. The
   panel is the form's ::before, so every field keeps its place on the grid; it runs from just
   above the first field to the footer and out to the page's right edge. */
main > section.contact { padding-bottom: var(--gap-block); overflow-x: clip; }
.contact-grid { position: relative; z-index: 0; }
.form {
  --pad: clamp(24px, 3vw, 48px); --rx: max(var(--m), (100vw - 1680px) / 2 + var(--m));
  position: relative; grid-column: 7 / span 6; grid-row: 2; margin-top: var(--gap-block);
  display: grid; grid-template-columns: 1fr 1fr; gap: 28px var(--g); color: var(--on-ink);
}
.form::before {
  content: ""; position: absolute; z-index: -1; top: calc(var(--pad) * -1); left: calc(var(--pad) * -1);
  right: calc(var(--rx) * -1); bottom: calc(var(--gap-block) * -1);
  background: var(--ink); border-top-left-radius: calc(var(--seam) / 2);
}
.form ::selection { background: var(--honey); color: var(--ink); }
/* the concave quarter turn where the panel meets the footer */
.seam-foot { position: absolute; bottom: 0; left: calc(var(--sx) - var(--pad, clamp(24px, 3vw, 48px)) - var(--seam) / 2); width: calc(var(--seam) / 2); height: calc(var(--seam) / 2); background: var(--ink); pointer-events: none; }
.seam-foot::before { content: ""; position: absolute; inset: 0; background: var(--paper); border-bottom-right-radius: 100%; }
.field { display: flex; flex-direction: column; gap: 10px; margin: 0; padding: 0; border: 0; min-width: 0; }
.field > span, .field legend { font-size: 16px; font-weight: 650; padding: 0; color: var(--on-ink-2); transition: color 0.2s ease; }
.field:focus-within > span, .field:focus-within > legend { color: var(--honey); }
.field legend { margin-bottom: 12px; }
.field-wide { grid-column: 1 / -1; }
.field input:not([type=checkbox]), .field select, .field textarea {
  width: 100%; min-height: 56px; padding: 14px 18px; border: 0; border-radius: 6px;
  background: var(--ink-2); color: var(--on-ink); font-size: var(--f-body); outline: none;
  box-shadow: inset 0 0 0 1.5px rgba(244, 244, 241, 0.14); transition: box-shadow 0.2s ease, background-color 0.2s ease; /* taste-skill-ignore: a form field's own edge */
}
.field input:not([type=checkbox]):hover, .field select:hover, .field textarea:hover { background: var(--ink-3); }
.field input:focus, .field select:focus, .field textarea:focus { background: var(--ink-3); box-shadow: inset 0 0 0 2px var(--honey); } /* taste-skill-ignore: a form field's own edge */
.field input:user-invalid, .field select:user-invalid, .field textarea:user-invalid { box-shadow: inset 0 0 0 2px #ff9a7a; } /* taste-skill-ignore: a form field's own edge */
.field ::placeholder { color: rgba(244, 244, 241, 0.46); }
.field select { -webkit-appearance: none; appearance: none; cursor: pointer; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3E%3Cpath d='M5 8l5 5 5-5' fill='none' stroke='%23ffd43b' stroke-width='2'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: right 16px center; background-size: 18px; padding-right: 48px; }
.field select:invalid { color: rgba(244, 244, 241, 0.46); }
.field select option { color: var(--ink); background: var(--white); }
.field textarea { resize: vertical; min-height: 160px; line-height: 1.5; }
.checks { display: flex; flex-wrap: wrap; gap: 10px; }
.check { position: relative; display: flex; align-items: center; min-height: 44px; cursor: pointer; }
.check input { position: absolute; opacity: 0; width: 1px; height: 1px; } /* taste-skill-ignore: the real checkbox stays in the form; its label is the visible control */
.check span { display: inline-flex; align-items: center; gap: 10px; min-height: 44px; padding: 0 18px 0 14px; border-radius: 999px; background: var(--ink-2); box-shadow: inset 0 0 0 1.5px rgba(244, 244, 241, 0.14); font-size: 16px; font-weight: 550; transition: background-color 0.2s ease, color 0.2s ease, box-shadow 0.2s ease, transform 0.2s var(--ease); } /* taste-skill-ignore: a form control's own edge */
/* each topic carries a pipe node: a ring when off, filled honey when chosen */
.check span::before { content: ""; flex: none; width: 9px; height: 9px; border-radius: 50%; box-shadow: inset 0 0 0 1.5px rgba(244, 244, 241, 0.6); transition: background-color 0.2s ease, box-shadow 0.2s ease; } /* taste-skill-ignore: a pipe node's ring */
.check:hover span { background: var(--ink-3); }
.check input:checked + span { background: var(--honey); color: var(--ink); font-weight: 650; box-shadow: none; } /* taste-skill-ignore: removes the edge */
.check input:checked + span::before { background: var(--ink); box-shadow: none; } /* taste-skill-ignore: removes the ring */
.check input:focus-visible + span { outline: 2px solid var(--honey); outline-offset: 3px; }
.check:active span { transform: scale(0.97); }
.other { margin-top: 12px; }
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; opacity: 0; } /* taste-skill-ignore: honeypot field, never visible */
.form-actions { display: flex; align-items: center; flex-wrap: wrap; gap: 16px 24px; margin-top: 8px; }
.form-actions .btn { min-width: 220px; justify-content: space-between; gap: 28px; }
.form-actions .btn:hover { background: var(--white); }
.form-actions .btn:focus-visible { outline: 2px solid var(--honey); outline-offset: 4px; }
.form-actions .btn[disabled] { opacity: 0.6; cursor: progress; }
.note { font-size: 16px; font-weight: 600; }
.form .note a { color: var(--honey); }
.note.err { color: #8a2200; }
.form .note.err { color: #ff9a7a; }

/* footer: the second ink field, the name across the whole width */
.foot { background: var(--ink); color: var(--on-ink); padding-block: clamp(72px, 7vw, 112px) 32px; font-size: 16px; line-height: 1.5; }
.foot-cols { grid-column: 1 / span 9; display: grid; grid-template-columns: subgrid; row-gap: 32px; }
.foot-col { grid-column: span 3; }
.foot-h { font-weight: 650; margin-bottom: 8px; color: var(--on-ink-2); }
.foot-cols ul { display: grid; gap: 4px; }
.foot-cols a { font-size: var(--f-lead); font-weight: 600; letter-spacing: -0.01em; }
.foot a { text-decoration-color: transparent; }
.foot a:hover { color: var(--honey); text-decoration-color: transparent; }
.foot-lang { grid-column: 10 / -1; justify-self: end; display: flex; gap: 18px; font-size: var(--f-lead); font-weight: 600; }
.foot-lang a[aria-current] { color: var(--honey); }
.foot-mark { grid-column: 1 / -1; display: block; margin-top: clamp(80px, 9vw, 160px); color: var(--on-ink); }
.foot-mark .logo { width: 100%; height: auto; }
.foot-mark:hover { color: var(--on-ink); }
.foot-base { grid-column: 1 / -1; display: flex; flex-wrap: wrap; gap: 6px 28px; margin-top: clamp(28px, 3vw, 44px); color: var(--on-ink-2); }
.foot-base span { margin-right: auto; }

/* legal pages */
.legal { padding-block: clamp(72px, 8vw, 128px) 0; }
.legal-h { grid-column: 1 / -1; padding-bottom: var(--gap-block); }
.legal-side { grid-column: 1 / span 5; grid-row: 2; display: flex; flex-direction: column; align-items: flex-start; gap: 12px; }
.back { font-weight: 650; text-decoration: underline 2px; text-decoration-color: var(--honey); text-underline-offset: 6px; }
.back:hover { text-decoration-color: var(--ink); }
.legal-body { display: contents; }
.legal-body .lead { grid-column: 7 / -1; grid-row: 2; max-width: 70ch; }
.legal-sec { grid-column: 1 / -1; display: grid; grid-template-columns: subgrid; align-items: baseline; padding-top: clamp(32px, 3vw, 48px); }
.legal-sec h2 { grid-column: 1 / span 5; font-size: var(--f-lead); line-height: 1.25; letter-spacing: -0.01em; }
.legal-sec p { grid-column: 7 / -1; max-width: 70ch; }
.legal-sec p + p { margin-top: 12px; }

/* ------------------------------------------------------------ entrances
   Nothing is ever held hidden. At rest every part is in its final place; site.js adds .in only
   at the moment a part crosses into the viewport from below, and the animation plays backwards
   from below. A page that is never scrolled, printed, or captured whole shows everything. */
.motion [data-rv].in { animation: rv-rise 0.9s var(--ease) backwards; animation-delay: calc(var(--d, 0) * 80ms); }
.motion .stage[data-rv].in { animation-name: rv-rise-far; animation-duration: 1.1s; }
.motion .mask.in > span { animation: mask-rise 1s var(--ease) backwards; }
.motion .thread.px.in .pipe-line, .motion .px > .steps-pipe.in .pipe-line { stroke-dasharray: 1 1; animation: pipe-draw 1.4s var(--ease) backwards; }
.motion .thread.in .node, .motion .steps-pipe.in circle { animation: node-in 0.4s ease 0.9s backwards; }
.motion .thread.in .pipe-pulse, .motion .steps-pipe.in .pipe-pulse { animation: pipe-pulse 2.2s var(--ease) 0.5s both; }
/* "Get started": the pipe draws along the staircase and each step rises as the line reaches it,
   name, then sentence, then link; each corner node pops in on cue and the honey pulse runs once the
   line is through. One step every 350ms, the line over 1.5s. */
.motion .px > .steps-pipe.in .pipe-line { animation: pipe-draw 1.5s cubic-bezier(0.45, 0, 0.25, 1) 0.1s backwards; }
.motion .steps-pipe.in circle { transform-box: fill-box; transform-origin: center; animation: node-pop 0.5s var(--ease) backwards; animation-delay: calc(var(--k, 0) * 350ms + 0.1s); }
.motion .steps-pipe.in .pipe-pulse { animation-delay: 1.6s; }
.motion .step > [data-rv].in { animation-duration: 0.8s; animation-delay: calc(var(--k) * 350ms + var(--j) * 90ms + 0.15s); }
@keyframes node-pop { from { opacity: 0; transform: scale(0.2); } }
@media (max-width: 1100px) {
  /* stacked, each step rises as it enters; only the parts within it are staggered */
  .motion .step > [data-rv].in { animation-delay: calc(var(--j) * 90ms); }
}
@keyframes rv-rise { from { opacity: 0; transform: translateY(28px); } }
@keyframes rv-rise-far { from { opacity: 0; transform: translateY(64px); } }
@keyframes mask-rise { from { transform: translateY(108%); } }
@keyframes pipe-draw { from { stroke-dashoffset: 1; } }
@keyframes node-in { from { opacity: 0; } }
@keyframes pipe-pulse { 0% { opacity: 1; stroke-dashoffset: 0.06; } 92% { opacity: 1; } 100% { opacity: 0; stroke-dashoffset: -0.94; } }
/* the layered screenshots drift at different depths as the page scrolls */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .layer { animation: drift linear none; animation-timeline: view(); animation-range: cover; }
  }
}
/* From the layer's own place, upward only, and nothing outside the scroll range: a page that has
   not been scrolled (or a full-page capture) shows every window where the layout put it. */
/* The seam rises out of the Work field as it comes up the screen: flat when it enters, the full
   step by mid-screen. It moves down only from its own place (under the ink of Work, which paints
   over it), so outside the range, or with no scroll timeline, the step is simply there. */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .seam { animation: seam-rise linear none; animation-timeline: view(); animation-range: entry 0% cover 45%; }
  }
}
@keyframes seam-rise { from { transform: translateY(100%); } }
@keyframes drift { from { translate: 0 0; } to { translate: 0 calc(var(--par) * -1); } }
.layer.high { --par: 24px !important; }
@media (max-width: 640px) { .layer { animation: none !important; } }

/* ------------------------------------------------------------ tablet */
@media (max-width: 1100px) {
  .nav-links { gap: 22px; }
  .nav-inner { gap: 28px; }
  /* tablet: the second text edge moves to column 4 */
  .stack-lede { grid-column: 1 / span 10; }
  .services h3 { grid-column: 1 / -1; padding-right: 48px; }
  .svc-pipe { display: none; }
  .svc-link > span:first-child { max-width: none; }
  .services p { grid-column: 4 / -1; margin-top: 10px; }
  .work-head .lead { grid-column: 4 / -1; }
  .proj-desc { grid-column: 1 / span 6; }
  .proj-list { grid-column: 7 / -1; }
  /* the steps become a list: name on the left half, sentence and link on the right, the pipe
     running down the gutter between them */
  .steps { display: block; padding-top: 0; }
  .step { margin-top: 0; display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: var(--g); align-items: baseline; }
  .step + .step { margin-top: clamp(48px, 6vw, 64px); }
  .step h3 { grid-column: 1 / span 6; grid-row: 1 / span 2; }
  .step p { grid-column: 7 / -1; margin-top: 0; }
  .step a { grid-column: 7 / -1; justify-self: start; }
  .contact-copy { grid-column: 1 / span 8; grid-row: auto; justify-content: start; }
  .form { grid-column: 1 / -1; grid-row: auto; --pad: var(--m); margin-top: calc(var(--gap-block) + var(--m)); }
  .form::before { left: calc(var(--rx) * -1); }
  .seam-foot { display: none; }
  .foot-cols { grid-column: 1 / span 9; }
  .legal-side { grid-column: 1 / span 4; }
  .legal-body .lead, .legal-sec p { grid-column: 5 / -1; }
  .legal-sec h2 { grid-column: 1 / span 4; }
}
@media (max-width: 900px) {
  .nav-links { display: none; }
  .nav-toggle { display: block; }
  .nav-right { gap: 16px; }
  .proj-desc, .proj-list { grid-column: 1 / -1; }
  .proj-list { margin-top: 32px; }
  .legal-side, .legal-body .lead { grid-column: 1 / -1; grid-row: auto; }
  .legal-body .lead { margin-top: 32px; }
  .legal-sec { display: block; }
  .legal-sec h2 { margin-bottom: 12px; }
  .foot-cols { grid-column: 1 / -1; grid-template-columns: repeat(3, minmax(0, 1fr)); column-gap: var(--g); }
  .foot-col { grid-column: auto; }
  .foot-lang { grid-column: 1 / -1; justify-self: start; margin-top: 40px; }
}
/* ------------------------------------------------------------ phone */
@media (max-width: 640px) {
  :root { --nav-h: 62px; --f-body: 17px; --f-h2: clamp(30px, 8.4vw, 36px); --sec: 104px; --g: 16px; --gap-head: 24px; --gap-block: 40px; }
  .brand .logo { height: 24px; }
  .nav-cta { display: none; }
  .hero { padding: 48px 0 92px; }
  .hero-h { font-size: clamp(34px, 9.4vw, 44px); line-height: 1.06; letter-spacing: -0.04em; max-width: none; }
  .hero-sub { margin-top: 22px; font-size: 17px; max-width: 34ch; }
  .hero-cta { flex-direction: column; align-items: stretch; margin-top: 30px; }
  .stack .wrap, .work .wrap, .start-grid, .contact-grid, .foot-grid, .legal-grid { display: block; }
  .display, .proj-name { font-size: clamp(34px, 9.4vw, 44px); line-height: 1.02; letter-spacing: -0.04em; }
  .thread { height: 56px; margin-bottom: 20px; }
  .thread-hero { height: 74px; }
  .thread-out { height: var(--sec); margin-bottom: 0; }
  .statement { font-size: var(--f-lead); }
  .services li { display: block; --svc-pad: 14px; padding-block: var(--svc-pad); }
  /* the names use the full width here, so the arrow ends the sentence's last line instead */
  .services h3 { padding-right: 0; }
  .services p { max-width: none; padding-right: 40px; }
  .svc-go { top: auto; bottom: calc(var(--svc-pad) + (1.55em - 22px) / 2); }
  .services p { margin: 8px 0 0; }
  .work-head { display: block; }
  .work-head .lead { margin-top: var(--gap-head); }
  .proj-top { display: block; }
  .proj-meta { margin-top: 12px; align-items: flex-start; text-align: left; padding: 0; }
  .stage { --sg: 8px; --span0: 11; --hang: 20px; --barh: 16px; margin-top: 28px; }
  .layer { --span: 6; }
  .stage-fan .layer-1, .stage-fan .layer-2, .stage-wide .layer-1, .stage-crown .layer-1 { --col: 7; }
  .stage-spread .layer-0, .stage-lean .layer-0 { --col: 2; }
  .stage-spread .layer { --span: 4; }
  .stage-spread .layer.main { --span: var(--span0); }
  .frame { border-radius: 5px; }
  .frame-bar { padding-inline: 7px; gap: 4px; font-size: 9px; }
  .frame-bar i { width: 5px; height: 5px; }
  .frame-bar span { display: none; }
  .frame-plate, .frame:not(.frame-plate) { border-radius: 5px; }
  .proj-copy { display: block; }
  .steps { padding-left: 28px; }
  .step { display: block; }
  .step p { margin-top: 12px; }
  .step a { white-space: normal; }
  .band-link { min-height: 52svh; grid-template-columns: 1fr auto; column-gap: 16px; }
  .band-ar { grid-column: 2; grid-row: 1; align-self: start; }
  .band-link { grid-template-rows: 1fr auto auto; }
  .band-word { grid-row: 2; }
  .band-note { grid-column: 1 / -1; grid-row: 3; margin-top: 16px; }
  .band-note { font-size: var(--f-body); max-width: 22ch; }
  .band-pipe { display: none; }
  .band-word { font-size: 12.6vw; }
  :lang(zh-Hant) .band-word, :lang(zh-Hans) .band-word { font-size: 21vw; }
  .contact-copy { margin-top: 32px; }
  .form { grid-template-columns: 1fr; gap: 24px; }
  .form-actions .btn { width: 100%; }
  .foot-cols { grid-template-columns: 1fr 1fr; gap: 28px var(--g); }
  .foot-mark { margin-top: 64px; }
  .foot-base { flex-direction: column; }
}

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

:lang(zh-Hant) :is(h1, h2, h3), :lang(zh-Hans) :is(h1, h2, h3) { letter-spacing: 0; }
:lang(zh-Hant) h2, :lang(zh-Hans) h2 { word-break: keep-all; overflow-wrap: anywhere; }
