/* ==========================================================================
   Tricos.AI — 三宇智源
   Visual language referenced from lightwheel.ai
   ========================================================================== */

/* ---------- Fonts (self-hosted, no Google Fonts CDN) ----------
   Latin: Plus Jakarta Sans — geometric, rounded terminals, large x-height;
   the closest open stand-in for the Apple/SF Pro feel.
   CJK: MiSans — free for commercial use, round and full, PingFang-adjacent.
   The CJK files are subsets of the site's own text (~67 KB each instead of
   6.4 MB); re-run _ref/subset-fonts.py after editing copy. Characters that
   fall outside the subset drop through to the system CJK font below. */
@font-face {
  font-family: 'Plus Jakarta Sans';
  src: url('../fonts/plus-jakarta-sans.woff2') format('woff2-variations');
  font-weight: 200 800;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'MiSans';
  src: url('../fonts/misans-regular.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'MiSans';
  src: url('../fonts/misans-medium.woff2') format('woff2');
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'MiSans';
  src: url('../fonts/misans-semibold.woff2') format('woff2');
  font-weight: 600 700;
  font-style: normal;
  font-display: swap;
}

/* ---------- Tokens ---------- */
:root {
  --bg: #000000;
  --bg-soft: #0a0a0a;
  --bg-elev: #0f0f0f;

  --line: rgba(255, 255, 255, 0.08);
  --line-2: rgba(255, 255, 255, 0.15);
  --line-3: rgba(255, 255, 255, 0.3);

  --fg: #f5f5f7;
  --fg-muted: #b0b0b5;
  --fg-dim: #737373;
  --ink: #333333;

  --accent: #4123f5;
  --accent-2: #827cff;
  --accent-3: #9fa8ff;

  --glass: linear-gradient(180deg, rgba(34, 34, 34, 0.42), rgba(18, 18, 18, 0.28));
  --glow: radial-gradient(
    113.42% 113.42% at 50.71% 108.27%,
    rgba(141, 140, 139, 0.6) 0%,
    rgba(10, 10, 10, 0) 100%
  );

  --font-stack: 'Plus Jakarta Sans', 'MiSans', -apple-system, BlinkMacSystemFont,
    'PingFang SC', 'HarmonyOS Sans SC', 'Microsoft YaHei', 'Source Han Sans SC',
    'Noto Sans SC', sans-serif;
  --font-display: var(--font-stack);
  --font-body: var(--font-stack);
  /* labels were monospaced; a mono is neither round nor Apple, so they now
     ride the same rounded family and lean on letter-spacing instead */
  --font-mono: var(--font-stack);

  /* One weight for every small label — eyebrow, nav, footer, language switcher.
     Plus Jakarta resolves a real 300 for Latin but MiSans has no light face, so
     a label left to inherit body's weight renders its Latin part lighter than
     its Chinese part. Naming the weight once is what keeps the two scripts
     looking like one typeface. */
  --weight-label: 500;

  --maxw: 1280px;
  --gutter: 24px;
  --radius: 16px;
  --radius-lg: 24px;

  --ease: cubic-bezier(0.16, 1, 0.3, 1);
}

/* ---------- Base ---------- */
*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  scroll-behavior: smooth;
  /* The nav is fixed, so without this every in-page jump buries the target
     section's eyebrow and heading underneath it. */
  scroll-padding-top: 104px;
  -webkit-text-size-adjust: 100%;
}

/* Deliberately no -webkit-font-smoothing: antialiased and no
   text-rendering: optimizeLegibility. Both are macOS-era hints; on Windows
   the first opts out of ClearType subpixel rendering, which is what keeps
   small text crisp on a 1x display. The CJK face ships unhinted, so it has
   nothing else to fall back on. */
body {
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font-family: var(--font-body);
  font-size: 16px;
  line-height: 1.6;
  font-weight: 300;
  overflow-x: hidden;
}

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

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

button {
  font: inherit;
  color: inherit;
  background: none;
  border: none;
  cursor: pointer;
}

::selection {
  background: var(--accent);
  color: #fff;
}

/* ---------- Language toggle ---------- */
html[data-lang='zh'] .en {
  display: none !important;
}
html[data-lang='en'] .zh {
  display: none !important;
}

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

.section {
  position: relative;
  padding-block: 72px;
}

/* A section whose whole content is one statement — the database placeholder.
   The full section padding is sized for a heading plus a body of content;
   around two lines it just reads as a hole. */
.section--tight {
  padding-block: 44px;
}

/* Hairline between top-level chapters. The marquee already rules both of its
   own edges, so the section beneath it does not need one. */
.section--rule {
  border-top: 1px solid var(--line);
}

.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-family: var(--font-mono);
  font-size: 24px;
  font-weight: var(--weight-label);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--fg-dim);
  margin: 0 0 16px;
}

.eyebrow::before {
  content: '';
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 12px var(--accent);
}

/* ---------- Typography ----------
   Type scale: keep every size a whole number of pixels, and keep the
   viewport-relative middle of each clamp() wrapped in round(…, 1px). On a 1x
   display a fractional size (12.8px, 13.5px) leaves stems straddling two
   pixel columns, so a 1px stem rasterises as a 2px grey smear. At display
   sizes that error is proportionally invisible, which is why the page looks
   blurry at 100% and sharp as soon as you zoom in. */
h1,
h2,
h3,
h4 {
  font-family: var(--font-display);
  font-weight: 600;
  letter-spacing: -0.02em;
  line-height: 1.18;
  margin: 0;
}

.h-display {
  font-size: clamp(34px, round(5.4vw, 1px), 68px);
  line-height: 1.12;
  letter-spacing: -0.03em;
  font-weight: 600;
}

.h-section {
  font-size: clamp(28px, round(3.6vw, 1px), 46px);
  line-height: 1.2;
}

.lead {
  font-size: clamp(15px, round(1.3vw, 1px), 19px);
  color: var(--fg-muted);
  font-weight: 300;
  line-height: 1.65;
  margin: 16px 0 0;
}

/* ---------- Buttons ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 16px 28px;
  border-radius: var(--radius);
  font-family: var(--font-body);
  font-size: 15px;
  font-weight: 600;
  letter-spacing: -0.01em;
  white-space: nowrap;
  transition: background 0.4s var(--ease), color 0.4s var(--ease),
    border-color 0.4s var(--ease), transform 0.4s var(--ease);
}

.btn svg {
  transition: transform 0.4s var(--ease);
}

.btn:hover svg {
  transform: translateX(4px);
}

.btn-primary {
  background: #fff;
  color: var(--ink);
  border: 1px solid #fff;
}

.btn-primary:hover {
  background: #e9e9ee;
  border-color: #e9e9ee;
  transform: translateY(-2px);
}

.btn-ghost {
  background: transparent;
  color: #fff;
  border: 1px solid rgba(255, 255, 255, 0.5);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}

.btn-ghost:hover {
  background: rgba(255, 255, 255, 0.06);
  border-color: #fff;
  transform: translateY(-2px);
}

.btn-sm {
  padding: 11px 20px;
  font-size: 13px;
  border-radius: 12px;
}

/* ==========================================================================
   NAV
   ========================================================================== */
.nav {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 100;
  transition: background 0.5s var(--ease), border-color 0.5s var(--ease),
    backdrop-filter 0.5s var(--ease);
  border-bottom: 1px solid transparent;
}

.nav.is-stuck {
  background: rgba(0, 0, 0, 0.72);
  border-bottom-color: var(--line);
  backdrop-filter: blur(18px) saturate(150%);
  -webkit-backdrop-filter: blur(18px) saturate(150%);
}

.nav__inner {
  display: flex;
  align-items: center;
  gap: 32px;
  height: 76px;
}

.brand {
  display: flex;
  align-items: baseline;
  gap: 10px;
  flex-shrink: 0;
}

.brand__mark {
  font-family: var(--font-display);
  font-weight: 650;
  font-size: 19px;
  letter-spacing: -0.015em;
}

.brand__mark em {
  font-style: normal;
  color: var(--accent-2);
}

.brand__cn {
  font-size: 13px;
  font-weight: var(--weight-label);
  color: var(--fg-dim);
  letter-spacing: 0.12em;
}

.nav__links {
  display: flex;
  align-items: center;
  gap: 30px;
  margin-left: auto;
}

.nav__links a {
  font-size: 15px;
  color: var(--fg-muted);
  font-weight: var(--weight-label);
  transition: color 0.3s var(--ease);
  position: relative;
}

.nav__links a:hover {
  color: #fff;
}

.nav__right {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-shrink: 0;
}

.lang {
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 4px;
  border: 1px solid var(--line-2);
  border-radius: 10px;
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: var(--weight-label);
  letter-spacing: 0.06em;
}

.lang button {
  padding: 5px 9px;
  border-radius: 7px;
  color: var(--fg-dim);
  transition: background 0.3s var(--ease), color 0.3s var(--ease);
}

.lang button.is-on {
  background: rgba(255, 255, 255, 0.1);
  color: #fff;
}

.nav__burger {
  display: none;
  width: 40px;
  height: 40px;
  border: 1px solid var(--line-2);
  border-radius: 10px;
  align-items: center;
  justify-content: center;
}

.nav__burger span {
  display: block;
  width: 16px;
  height: 1.5px;
  background: #fff;
  position: relative;
}

.nav__burger span::before,
.nav__burger span::after {
  content: '';
  position: absolute;
  left: 0;
  width: 16px;
  height: 1.5px;
  background: #fff;
  transition: transform 0.3s var(--ease);
}

.nav__burger span::before {
  top: -5px;
}
.nav__burger span::after {
  top: 5px;
}

/* ==========================================================================
   HERO
   ========================================================================== */
.hero {
  position: relative;
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  isolation: isolate;
}

/* accent wash above the video, below the content */
.hero__bg {
  position: absolute;
  inset: 0;
  z-index: -2;
  pointer-events: none;
  background: radial-gradient(
    118% 74% at 50% 120%,
    rgba(65, 35, 245, 0.42) 0%,
    rgba(65, 35, 245, 0.13) 32%,
    rgba(0, 0, 0, 0) 64%
  );
  mix-blend-mode: screen;
  opacity: 0.8;
}

.hero__glow {
  position: absolute;
  left: 50%;
  bottom: -30%;
  width: min(1400px, 160vw);
  aspect-ratio: 1;
  transform: translateX(-50%);
  z-index: -1;
  background: radial-gradient(
    circle at 50% 50%,
    rgba(65, 35, 245, 0.16) 0%,
    rgba(65, 35, 245, 0.05) 34%,
    rgba(0, 0, 0, 0) 66%
  );
  filter: blur(20px);
  pointer-events: none;
}

.hero__grid {
  position: absolute;
  inset: 0;
  z-index: -1;
  background-image: linear-gradient(rgba(255, 255, 255, 0.035) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, 0.035) 1px, transparent 1px);
  background-size: 72px 72px;
  mask-image: radial-gradient(ellipse 80% 60% at 50% 40%, #000 0%, transparent 78%);
  -webkit-mask-image: radial-gradient(ellipse 80% 60% at 50% 40%, #000 0%, transparent 78%);
  pointer-events: none;
}

/* The capture footage is a 1280x1400 four-panel composite (third-person view,
   egocentric view, 3D trajectory, IMU readout). It is dense and it is the
   product, so it is shown whole in its own frame — never behind the copy. */
.hero__inner {
  position: relative;
  z-index: 2;
  width: 100%;
  max-width: var(--maxw);
  margin-inline: auto;
  padding: 128px var(--gutter) 0;
  display: grid;
  grid-template-columns: minmax(0, 1.16fr) minmax(0, 0.84fr);
  align-items: center;
  gap: 60px;
  text-align: left;
}

.hero__copy {
  min-width: 0;
}

.hero__media {
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
}

/* A drawn diagram rather than a player: no footage is public yet, so this
   frames the same portrait plate the clips used to fill. */
.hero__viz {
  position: relative;
  width: 100%;
  aspect-ratio: 560 / 612;
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: #060608;
  border: 1px solid var(--line-2);
  box-shadow: 0 50px 130px -55px rgba(65, 35, 245, 0.75),
    0 0 0 1px rgba(255, 255, 255, 0.04);
}

.hero__viz svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

.hero__badge {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 7px 16px 7px 12px;
  border: 1px solid var(--line-2);
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.03);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  font-size: 13px;
  color: var(--fg-muted);
  margin-bottom: 30px;
}

.hero__badge b {
  color: #fff;
  font-weight: 600;
}

.pulse {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--accent-2);
  box-shadow: 0 0 0 0 rgba(130, 124, 255, 0.7);
  animation: pulse 2.4s infinite;
}

@keyframes pulse {
  0% {
    box-shadow: 0 0 0 0 rgba(130, 124, 255, 0.6);
  }
  70% {
    box-shadow: 0 0 0 9px rgba(130, 124, 255, 0);
  }
  100% {
    box-shadow: 0 0 0 0 rgba(130, 124, 255, 0);
  }
}

/* the hero headline shares the fold with the capture footage, so it runs
   smaller than a full-width display heading and balances rather than
   dropping a single orphan glyph onto the last line */
.hero h1 {
  margin: 0;
  font-size: clamp(30px, round(3.55vw, 1px), 52px);
  line-height: 1.16;
  letter-spacing: -0.025em;
  text-wrap: balance;
}

.hero h1 .line-2 {
  display: block;
  background: linear-gradient(96deg, #fff 12%, var(--accent-3) 58%, #fff 96%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
}

.hero__sub {
  margin: 26px 0 0;
  max-width: 560px;
  font-size: clamp(15px, round(1.15vw, 1px), 18px);
  color: var(--fg-muted);
  font-weight: 400;
}

.hero__cta {
  display: flex;
  gap: 14px;
  justify-content: flex-start;
  flex-wrap: wrap;
  margin-top: 38px;
}

/* ==========================================================================
   DATA INFRASTRUCTURE
   ========================================================================== */

/* three principles — hairline triad, monochrome */
.infra__principles {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  margin-top: 34px;
  border-top: 1px solid var(--line-2);
}

.principle {
  padding: 26px 34px 0;
  border-left: 1px solid var(--line);
}

.principle:first-child {
  padding-left: 0;
  border-left: 0;
}

.principle__k {
  font-size: 17px;
  font-weight: 600;
  letter-spacing: -0.01em;
  line-height: 1.3;
}

.principle__d {
  margin: 12px 0 0;
  font-size: 14px;
  font-weight: 300;
  line-height: 1.72;
  color: var(--fg-muted);
}

/* four across — the marketplace and hiring rows carry one more item than the
   three-part story, so the rail tightens rather than wrapping. */
.infra__principles--4 {
  grid-template-columns: repeat(4, minmax(0, 1fr));
}

.infra__principles--4 .principle {
  padding-right: 26px;
}

/* The unreleased slot. A product card ends here instead of in a spec table:
   a hairline box that reads as a placeholder on purpose, so the absence of
   numbers looks like a decision rather than an omission. */
.soon {
  margin-top: 28px;
  padding: 15px 18px 16px;
  border: 1px dashed var(--line-2);
  border-radius: 14px;
  font-size: 13px;
  line-height: 1.5;
  color: var(--fg-dim);
}

.soon--wide {
  margin-top: 30px;
  padding: 20px 22px;
}

/* contact strip at the foot of the hiring section */
.join__contact {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 32px;
  margin-top: 40px;
  padding: 30px 34px;
  border: 1px solid var(--line-2);
  border-radius: var(--radius-lg);
  background: var(--glass);
}

.join__contact-k {
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--fg-dim);
}

.join__contact-d {
  margin: 12px 0 0;
  max-width: 62ch;
  font-size: 14px;
  font-weight: 300;
  line-height: 1.72;
  color: var(--fg-muted);
}

.join__contact-d a {
  color: var(--fg);
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-color: var(--line-3);
}

.join__contact-d a:hover {
  text-decoration-color: var(--fg);
}

/* ==========================================================================
   PRODUCT CYCLE
   ========================================================================== */
/* The three lines are not three rows. Each one feeds the next, so they are
   laid out on a triangle and a bowing arrow runs along every edge, back to
   the start. Each area here is one vertex of the ring in the markup:

     ego    apex          (380, 94)
     data   bottom right  (633.3, 533)
     model  bottom left   (126.7, 533)

   The areas land on those points because the box carries the same aspect
   ratio as the SVG viewBox, the columns are equal thirds, and the outer rows
   centre on 15% and 85%. Change any of the three and the arrows stop meeting
   the cards. */
.cycle {
  position: relative;
  max-width: 660px;
  margin: 36px auto 0;
  aspect-ratio: 760 / 627;
}

.cycle__ring {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

.cycle__nodes {
  position: relative;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  grid-template-rows: 30% 40% 30%;
  grid-template-areas:
    ".      ego    ."
    ".      .      ."
    "model  .      data";
  /* no gap: equal thirds put the column centres on 16.7/50/83.3%, which is
     where the ring's vertices are */
  height: 100%;
  margin: 0;
  padding: 0;
  list-style: none;
}

/* opaque, so the ring passes behind a card rather than through its text */
.cycle__node {
  align-self: center;
  justify-self: center;
  max-width: 220px;
  padding: 20px 18px;
  border: 1px solid var(--line);
  border-radius: 18px;
  background: var(--glass), #060607;
  text-align: center;
}

.cycle__node--ego { grid-area: ego; }
.cycle__node--data { grid-area: data; }
.cycle__node--model { grid-area: model; }

.cycle__n {
  display: block;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.16em;
  color: var(--accent-2);
}

.cycle__k {
  margin-top: 10px;
  font-family: var(--font-display);
  font-size: 20px;
  font-weight: 600;
  letter-spacing: -0.02em;
}

.cycle__d {
  margin: 8px 0 0;
  font-size: 13px;
  font-weight: 300;
  line-height: 1.65;
  color: var(--fg-muted);
}

/* ---------- the ring, in motion ----------
   The dashed arcs are the track. A bright segment runs along each edge so the
   figure reads as something circulating rather than as three arrows that
   happen to point at each other. Two pieces of arithmetic keep it seamless:

   `pathLength="100"` on the comets normalises the three edges, which are
   different lengths, so one lap takes the same time on all of them and the
   segments never bunch up or drift apart.

   The delays are 0 / -2.4s / -1.2s. That is not the obvious 0 / -1.2 / -2.4
   sweep: this ordering is what makes the comets arrive at the arrow heads, and
   the heads flash, in the arrows' own direction — ego, data, model, ego. Swap
   any two delays and the ring animates backwards through its own story. */
.cycle__comet {
  stroke: var(--accent-3);
  stroke-width: 2.4;
  stroke-linecap: round;
  /* dash + gap must total 100 to fill the normalised lap exactly. A short dash
     with a hot shadow reads as a scratch travelling along the line; a third of
     the edge, softly lit, reads as flow. */
  stroke-dasharray: 30 70;
  filter: drop-shadow(0 0 5px rgba(159, 168, 255, 0.55));
  animation: cycle-comet 3.6s linear infinite;
}

.cycle__comet:nth-child(2) { animation-delay: -2.4s; }
.cycle__comet:nth-child(3) { animation-delay: -1.2s; }

/* on a path of length 100 an offset of 100 and an offset of 0 are the same
   place, so the lap closes on itself with no seam */
@keyframes cycle-comet {
  from { stroke-dashoffset: 100; }
  to { stroke-dashoffset: 0; }
}

.cycle__head {
  filter: drop-shadow(0 0 5px rgba(130, 124, 255, 0.55));
  animation: cycle-head 3.6s linear infinite;
}

.cycle__head:nth-child(2) { animation-delay: -2.4s; }
.cycle__head:nth-child(3) { animation-delay: -1.2s; }

/* peaks at the top of its own cycle — the moment the comet on that edge
   reaches the head */
@keyframes cycle-head {
  0%, 100% { opacity: 1; }
  55% { opacity: 0.4; }
}

/* The comet is the whole effect. Held still it is a stray blob parked on the
   track, so it goes; the heads keep their full value. */
@media (prefers-reduced-motion: reduce) {
  .cycle__comet { display: none; }
  .cycle__head { animation: none; opacity: 1; }
}

/* ==========================================================================
   FOOTER
   ========================================================================== */
.footer {
  border-top: 1px solid var(--line);
  padding-block: 52px 34px;
  background: #000;
}

.footer__top {
  display: grid;
  grid-template-columns: 1.6fr repeat(2, 1fr);
  gap: 48px;
}

.footer__col h4 {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--fg-dim);
  font-weight: var(--weight-label);
  margin-bottom: 18px;
}

.footer__col ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 11px;
}

.footer__col a {
  font-size: 15px;
  font-weight: var(--weight-label);
  color: var(--fg-muted);
  transition: color 0.3s var(--ease);
}

.footer__col a:hover {
  color: #fff;
}

.footer__desc {
  margin-top: 18px;
  font-size: 14px;
  color: var(--fg-dim);
  max-width: 300px;
  line-height: 1.6;
}

.footer__bottom {
  margin-top: 40px;
  padding-top: 26px;
  border-top: 1px solid var(--line);
  display: flex;
  justify-content: space-between;
  gap: 20px;
  flex-wrap: wrap;
  font-size: 13px;
  color: var(--fg-dim);
}

.footer__bottom a {
  color: var(--fg-dim);
  text-decoration: none;
  transition: color 0.3s var(--ease);
}

.footer__bottom a:hover {
  color: #fff;
}

/* ==========================================================================
   REVEAL
   ========================================================================== */
[data-reveal] {
  opacity: 0;
  transform: translateY(30px);
  transition: opacity 0.9s var(--ease), transform 0.7s var(--ease);
}

[data-reveal].is-in {
  opacity: 1;
  transform: none;
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
  [data-reveal] {
    opacity: 1;
    transform: none;
    transition: none;
  }
}

/* ==========================================================================
   RESPONSIVE
   ========================================================================== */
/* The diagrams label themselves with SVG text, which lives in viewBox units
   and therefore shrinks with the panel. On a phone those labels land at 7-8px
   — noise rather than annotation — so they go away rather than shrink. */
@media (max-width: 900px) {
  .hero__viz svg text,
  .hero__viz svg .viz-legend {
    display: none;
  }
}

@media (max-width: 1024px) {
  .nav__links {
    display: none;
  }
  .nav__links.is-open {
    display: flex;
    position: absolute;
    top: 76px;
    left: 0;
    right: 0;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    margin: 0;
    padding: 6px var(--gutter) 18px;
    background: rgba(0, 0, 0, 0.94);
    backdrop-filter: blur(18px);
    -webkit-backdrop-filter: blur(18px);
    border-bottom: 1px solid var(--line);
  }
  .nav__links.is-open a {
    padding: 15px 0;
    font-size: 16px;
    border-bottom: 1px solid var(--line);
  }
  .nav__burger {
    display: flex;
  }
  .nav__inner {
    gap: 16px;
  }
  .hero__inner {
    grid-template-columns: 1fr;
    gap: 44px;
    padding-top: 112px;
    text-align: center;
  }
  .hero__sub {
    margin-inline: auto;
  }
  .hero__cta {
    justify-content: center;
  }
  .hero__media {
    max-width: 400px;
    margin-inline: auto;
    width: 100%;
  }
  .footer__top {
    grid-template-columns: 1fr 1fr;
    gap: 36px;
  }
  /* infra: principles stack on a hairline rail */
  .infra__principles {
    grid-template-columns: 1fr;
    border-top: 0;
  }
  .principle {
    padding: 22px 0 0;
    border-left: 0;
    border-top: 1px solid var(--line);
  }
  .principle:first-child {
    border-top: 1px solid var(--line-2);
  }
  .infra__principles--4 .principle {
    padding-right: 0;
  }
}

@media (max-width: 720px) {
  :root {
    --gutter: 20px;
  }
  html {
    /* shorter nav on a phone */
    scroll-padding-top: 88px;
  }
  .section {
    padding-block: 52px;
  }
  .section--tight {
    padding-block: 36px;
  }
  .footer__top {
    grid-template-columns: 1fr;
  }
  .hero__inner {
    padding-top: 104px;
  }
  .hero__badge {
    margin-bottom: 20px;
    font-size: 12px;
  }
  .hero__sub {
    margin-top: 18px;
  }
  .hero__cta {
    margin-top: 28px;
  }
  /* nav no longer fits: brand + lang + CTA + burger overflows 390px */
  .brand__cn,
  .nav__right .btn {
    display: none;
  }
  .join__contact {
    flex-direction: column;
    align-items: flex-start;
    gap: 24px;
    padding: 28px 24px;
  }
}

/* Below this the three columns are too narrow to hold a line of Chinese, and
   the cards grow taller than the gaps between the arrows — the ring stops
   reading. The triangle keeps its shape as a compact mark and the three lines
   go back to being a list, which is the one thing the cycle was meant to
   replace but the only honest fallback at this width. */
@media (max-width: 640px) {
  .cycle {
    aspect-ratio: auto;
    margin-top: 34px;
  }
  .cycle__ring {
    position: static;
    width: 240px;
    height: auto;
    margin: 0 auto 28px;
  }
  .cycle__nodes {
    display: block;
    height: auto;
  }
  .cycle__node {
    width: 100%;
    max-width: none;
    text-align: left;
    padding: 18px 20px;
  }
  .cycle__node + .cycle__node {
    margin-top: 14px;
  }
}

/* ==========================================================================
   DATABASE / DATASET
   ========================================================================== */
/* One featured open dataset, presented as a product card rather than a table.
   The smiley watermark is the Hugging Face mark at a whisper, so the card
   reads as "hosted on HF" without shouting it. */
.dataset {
  position: relative;
  margin-top: 40px;
  padding: 46px 48px;
  border: 1px solid var(--line-2);
  border-radius: var(--radius-lg);
  background: var(--glass), #060608;
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
  gap: 48px;
  align-items: center;
  overflow: hidden;
  box-shadow: 0 60px 140px -60px rgba(65, 35, 245, 0.6);
}

.dataset::before {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(120% 140% at 100% 0%, rgba(65, 35, 245, 0.16) 0%, rgba(0, 0, 0, 0) 55%);
  pointer-events: none;
}

.dataset__watermark {
  position: absolute;
  top: -44px;
  right: -44px;
  width: 320px;
  height: 320px;
  color: #fff;
  opacity: 0.05;
  pointer-events: none;
}

.dataset__main,
.dataset__stats {
  position: relative;
}

.dataset__brand {
  display: flex;
  align-items: center;
  gap: 10px;
}

.dataset__logo {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  border: 1px solid var(--line-2);
  border-radius: 11px;
  background: rgba(255, 255, 255, 0.04);
  color: #fff;
  flex-shrink: 0;
}

.dataset__logo svg {
  width: 22px;
  height: 22px;
}

.dataset__brandname {
  font-size: 14px;
  font-weight: 600;
  letter-spacing: -0.01em;
}

.dataset__badge {
  margin-left: 2px;
  padding: 4px 11px;
  border: 1px solid rgba(130, 124, 255, 0.42);
  border-radius: 999px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.08em;
  color: var(--accent-3);
  background: rgba(130, 124, 255, 0.08);
}

.dataset__name {
  margin-top: 24px;
  font-size: clamp(26px, round(2.6vw, 1px), 38px);
  letter-spacing: -0.02em;
  line-height: 1.12;
}

.dataset__id {
  margin-top: 8px;
  font-family: var(--font-mono);
  font-size: 13px;
  letter-spacing: 0.06em;
  color: var(--fg-dim);
}

.dataset__desc {
  margin-top: 18px;
  max-width: 46ch;
  font-size: 15px;
  font-weight: 300;
  line-height: 1.72;
  color: var(--fg-muted);
}

.dataset__cta {
  margin-top: 30px;
  display: flex;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
}

.dataset__cta .btn {
  font-size: 14px;
  padding: 14px 24px;
}

.dataset__note {
  font-size: 12px;
  color: var(--fg-dim);
}

/* the four facts of the dataset — monochrome rail, accent key */
.dataset__stats {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 14px;
}

.stat {
  padding: 22px 20px;
  border: 1px solid var(--line);
  border-radius: 16px;
  background: rgba(255, 255, 255, 0.02);
}

.stat__k {
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent-3);
}

.stat__v {
  margin-top: 10px;
  font-size: 14px;
  font-weight: 400;
  line-height: 1.5;
  color: var(--fg);
}

/* the slot after the card — a promise, not a spec table */
.dataset__more {
  margin-top: 20px;
  padding: 18px 22px;
  border: 1px dashed var(--line-2);
  border-radius: 14px;
  font-size: 13px;
  color: var(--fg-dim);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
}

.dataset__more-badge {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 13px;
  border: 1px solid var(--line-2);
  border-radius: 999px;
  font-size: 12px;
  color: var(--fg-muted);
}

.dataset__more-badge .pulse {
  width: 6px;
  height: 6px;
}

/* ==========================================================================
   CJK TRACKING RESET  (see _ref/study-apple.md)
   Apple ships `:lang(zh) { letter-spacing: 0em }` because CJK glyphs already
   carry their own sidebearings. Latin negative tracking is tuned for narrower
   Latin forms, so applied to Chinese it closes the gaps until strokes collide.
   Reset it on every heading-sized element that can hold CJK. Small tracked
   labels (eyebrows, tags) are deliberately excluded — the ceremony belongs
   there, not on display type.
   ========================================================================== */

.h-display .zh,
.h-section .zh,
.principle__k .zh,
.dataset__name .zh,
.stat__v .zh {
  letter-spacing: 0;
}

/* ==========================================================================
   DATABASE — RESPONSIVE
   ========================================================================== */
@media (max-width: 900px) {
  .dataset {
    grid-template-columns: 1fr;
    gap: 36px;
    padding: 34px 30px;
  }
  .dataset__watermark {
    width: 240px;
    height: 240px;
    top: -30px;
    right: -30px;
  }
}

@media (max-width: 640px) {
  .dataset {
    padding: 26px 20px;
    gap: 28px;
    margin-top: 32px;
  }
  .dataset__stats {
    gap: 10px;
  }
  .stat {
    padding: 16px 14px;
  }
  .dataset__brand {
    flex-wrap: wrap;
  }
  .dataset__more {
    flex-direction: column;
    align-items: flex-start;
  }
}
