/* ==========================================================================
   龙居能量规划中心 — stylesheet

   Rebuilt to match the original Webador site's look: a white ground, a narrow
   centred column, indigo type, and a soft green accent on buttons and the
   footer. The original achieved this with 276 KB of Webador framework CSS; this
   is the same look in one file with no framework behind it.

   Sections:
     1.  Tokens
     2.  Reset and base
     3.  Typography
     4.  Layout primitives
     5.  Header and navigation
     6.  Hero
     7.  Buttons and links
     8.  Section furniture
     9.  Services                (home — 服务项目)
     10. Case study              (个人能量重塑, 企业能量优化)
     11. Content blocks          (callout, block, facts, lists)
     12. People                  (关于我们)
     13. Contact                 (联系我们)
     14. Footer
     15. Utilities
     16. Focus, motion, print
   ========================================================================== */

/* ==========================================================================
   1. Tokens
   ========================================================================== */

:root {
  /* The original's accent, unchanged: 龙居's indigo, straight from its theme. */
  --indigo: #2a1f68;
  --indigo-2: #32257c;

  /* The template's other accent — the 更多信息 buttons and the footer band.
     It is almost certainly a Webador default the site never customised, but it
     is half the original's colour identity, so it is reproduced. */
  --green: #b8e19a;
  --green-ink: #2d4c17;

  --ink: #202020;
  --ink-2: #4f4f4f;
  --ink-3: #7d7d7d;

  --rule: #e3e3e3;
  --rule-strong: #cccccc;

  --paper: #ffffff;
  --surface-tint: #f7f5fb;

  /* No webfonts: Chinese ones run 5–15 MB, more than the whole page budget. */
  --font: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei",
    "Source Han Sans SC", "Noto Sans CJK SC", "Noto Sans SC",
    -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
    "Helvetica Neue", Arial, sans-serif;
  --font-latin: ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI",
    Roboto, "Helvetica Neue", Arial, sans-serif;
  /* The original sets every heading in a serif, not just the Latin ones:
     `.jw-section h1..h6 { font-family: "Times New Roman", …, serif }`. Latin
     glyphs take Times New Roman exactly as they do there; Chinese glyphs fall
     through to a Songti face — SimSun on Windows, Songti SC on macOS — which
     is what the original's Chinese headings actually render in. */
  --font-serif: "Times New Roman", "Songti SC", SimSun, "Source Han Serif SC",
    "Noto Serif CJK SC", Cambria, "Hoefler Text", Utopia, "Liberation Serif",
    Times, serif;

  --step--1: 0.8125rem;
  --step-0: 1rem;
  --step-1: 1.0625rem;

  --sp-1: 0.5rem;
  --sp-2: 0.875rem;
  --sp-3: 1.5rem;
  --sp-4: 2.25rem;
  --sp-5: 3.5rem;
  --sp-6: 5rem;

  --section: clamp(3rem, 6vw, 4.5rem);

  /* The original runs two widths: a ~825px content column, and a ~605px
     measure for the centred statements inside it. Both measured off the page. */
  --container: 56rem;
  --measure: 38rem;
  --gutter: clamp(1.25rem, 5vw, 2.5rem);

  --radius: 4px;
  --header-h: 0;        /* the header is in flow, not overlaid; nothing offsets it */
}

/* ==========================================================================
   2. Reset and base
   ========================================================================== */

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: var(--sp-4);
}

body {
  margin: 0;
  min-height: 100vh;
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font);
  font-size: var(--step-0);
  line-height: 1.6;   /* the original's --jw-line-height-paragraph: 1.5 */
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

main { flex: 1 0 auto; }

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

:focus-visible {
  outline: 2px solid var(--indigo);
  outline-offset: 3px;
  border-radius: 2px;
}

/* ==========================================================================
   3. Typography
   ========================================================================== */

/* The original's heading scale is deliberately compressed — measured on the
   live page, its h2 sits at ~19px against 16px body text, and its h1 at ~20px.
   Reproduced here rather than widened: the quiet, near-flat hierarchy is a
   large part of why the original reads the way it does. */
h1, h2, h3, h4 {
  margin: 0;
  font-family: var(--font-serif);
  font-weight: 700;
  line-height: 1.25;
  color: var(--indigo);
  text-wrap: balance;
}

h1 { font-size: clamp(1.25rem, 1.9vw, 1.4rem); }
h2 { font-size: clamp(1.15rem, 1.6vw, 1.25rem); }
h3 { font-size: clamp(1.05rem, 1.3vw, 1.125rem); }
h4 { font-size: var(--step-0); }

p { margin: 0 0 var(--sp-3); }
p:last-child { margin-bottom: 0; }

ul, ol { margin: 0 0 var(--sp-3); padding-left: 1.4em; }
ul:last-child, ol:last-child { margin-bottom: 0; }
li { margin-bottom: 0.45em; }
li:last-child { margin-bottom: 0; }

a { color: var(--indigo); text-underline-offset: 0.2em; }
a:hover { color: var(--indigo-2); }

strong, b { font-weight: 700; }

/* The original's English sub-titles: serif, small, widely tracked. */
.subtitle {
  font-family: var(--font-serif);
  font-size: clamp(0.9rem, 1.5vw, 1.1rem);
  letter-spacing: 0.1em;
  line-height: 1.5;
}

.latin { font-family: var(--font-latin); }

.lede {
  font-size: var(--step-1);
  color: var(--indigo);
}

/* ==========================================================================
   4. Layout primitives
   ========================================================================== */

.container {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.measure { max-width: var(--measure); }

.mx-auto { margin-inline: auto; }

.text-center { text-align: center; }

.section { padding-block: var(--section); }

/* Corporate case pages need a little more breathing room than the general
   56rem content column. The wider shell keeps the image, labels and evidence
   readable without making the prose line length excessive. */
.case-shell { max-width: 68rem; }

.case-nav {
  position: sticky;
  top: 0.75rem;
  z-index: 4;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.4rem;
  width: fit-content;
  max-width: 100%;
  margin: -1.5rem auto var(--sp-5);
  padding: 0.55rem;
  background: rgba(255, 255, 255, 0.94);
  border: 1px solid var(--rule);
  border-radius: 999px;
  box-shadow: 0 0.5rem 1.5rem rgba(42, 31, 104, 0.08);
  backdrop-filter: blur(10px);
}

.case-nav a {
  display: inline-block;
  padding: 0.45rem 0.8rem;
  border-radius: 999px;
  color: var(--indigo);
  font-size: var(--step--1);
  text-decoration: none;
  white-space: nowrap;
}

.case-nav a:hover,
.case-nav a:focus-visible {
  background: var(--surface-tint);
  text-decoration: none;
}

.case-intro {
  max-width: var(--measure);
  margin: 0 auto var(--sp-5);
  text-align: center;
}

.case-intro h2 { margin-bottom: var(--sp-2); }

.case-intro > p:last-child { margin-bottom: 0; }

.process-grid {
  display: grid;
  gap: 1px;
  margin-top: var(--sp-4);
  background: var(--rule);
  border: 1px solid var(--rule);
  text-align: left;
}

.process-step {
  padding: var(--sp-3);
  background: var(--paper);
}

.process-step__num {
  display: block;
  margin-bottom: var(--sp-1);
  color: var(--ink-3);
  font-size: var(--step--1);
  font-weight: 700;
  letter-spacing: 0.12em;
}

.process-step h3 { margin-bottom: var(--sp-1); }
.process-step p { margin-bottom: 0; color: var(--ink-2); }

@media (min-width: 640px) {
  .process-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* ==========================================================================
   5. Header and navigation

   The original centres the logo and wordmark, with the navigation on its own
   line beneath them, on white — the header sits above the hero rather than over
   it, so there is no scroll state to manage.
   ========================================================================== */

.site-header {
  background: var(--paper);
  border-bottom: 1px solid var(--rule);
}

.site-header__inner {
  position: relative;
  display: grid;
  justify-items: center;
  gap: clamp(0.75rem, 2vw, 1.25rem);
  padding-block: clamp(1.25rem, 3vw, 2rem) clamp(0.875rem, 2vw, 1.375rem);
}

.brand {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  text-decoration: none;
}

/* Sized by height, not width: the mark is a landscape emblem, and height is
   what reads against .brand__name beside it. Driving the width instead would
   make the mark's footprint depend on its aspect ratio, so the two variants in
   _work/brand-alternates/ (emblem and full lockup) would need different rules.
   Both are drawn on the same canvas, so `height` + `auto` fits either. The file
   is 240px wide, so it stays sharp to 3x on the largest box here. */
.brand__mark {
  height: clamp(2.5rem, 5vw, 3.5rem);
  width: auto;
  flex: none;
}

.brand__name {
  font-size: clamp(1.45rem, 3.4vw, 2.25rem);
  font-weight: 700;
  letter-spacing: 0.02em;
  color: var(--indigo);
  line-height: 1.2;
}

.site-nav { width: 100%; }

.nav__list {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: clamp(0.875rem, 3vw, 2.25rem);
  margin: 0;
  padding: 0;
  list-style: none;
}

.nav__list li { margin: 0; }

.nav__link {
  display: inline-block;
  padding-block: 0.15rem;
  color: var(--ink);
  font-size: 0.95rem;
  text-decoration: none;
}

.nav__link:hover { text-decoration: underline; }

.nav__link[aria-current="page"] {
  position: relative;
  color: var(--indigo);
  font-weight: 700;
}

.nav__link[aria-current="page"]::after {
  content: "";
  position: absolute;
  right: 0;
  bottom: -0.35rem;
  left: 0;
  height: 2px;
  background: var(--indigo);
}

/* The language link is a utility rather than a destination, so a hairline rule
   sets it apart from the page links beside it. The padding matches the flex
   gap, which puts the rule on the centre line between the two runs. Only on
   wide screens: once the list stacks, a rule at the left edge reads as a stray
   line rather than a divider. */
@media (min-width: 861px) {
  .nav__item--lang {
    padding-left: clamp(0.875rem, 3vw, 2.25rem);
    border-left: 1px solid var(--rule);
  }
}

/* Hamburger: narrow screens only. */
.nav-toggle {
  display: none;
  width: 2.75rem;
  height: 2.75rem;
  padding: 0;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: transparent;
  color: var(--indigo);
  cursor: pointer;
}

.nav-toggle__bars,
.nav-toggle__bars::before,
.nav-toggle__bars::after {
  display: block;
  width: 1.125rem;
  height: 2px;
  margin-inline: auto;
  background: currentColor;
}

.nav-toggle__bars { position: relative; }
.nav-toggle__bars::before,
.nav-toggle__bars::after { content: ""; position: absolute; left: 0; }
.nav-toggle__bars::before { top: -6px; }
.nav-toggle__bars::after { top: 6px; }

/* Narrow screens collapse the navigation behind the toggle — but only when
   scripting is on. Scoped to .js so that with scripting off the whole list
   stays visible rather than being collapsed with no way to open it. */
@media (max-width: 860px) {
  .js .nav-toggle {
    display: block;
    position: absolute;
    top: 50%;
    right: var(--gutter);
    transform: translateY(-50%);
    margin-top: -0.5rem;
  }

  /* The toggle is positioned over the centred brand rather than beside it, so
     the brand has to stop short of it — "LongJu Energy Planning Center" is long
     enough to reach the right edge and slide under the button. Reserving the
     toggle's own width plus a gutter lets the name wrap to a second line
     instead. Scoped to .js for the same reason the toggle is: with scripting
     off there is no button to avoid. */
  .js .brand {
    max-width: calc(100% - 4.5rem);
  }

  /* Keep the language switcher visible beside the hamburger even while the
     destination links are collapsed. It remains in the same list when the
     menu opens, so there is one source of truth for both states. */
  .js .site-nav:not(.is-open) {
    display: block;
    height: 0;
  }

  .js .site-nav:not(.is-open) .nav__list { display: block; }
  .js .site-nav:not(.is-open) .nav__list > li:not(.nav__item--lang) { display: none; }
  .js .site-nav:not(.is-open) .nav__item--lang {
    position: absolute;
    top: 50%;
    right: calc(var(--gutter) + 3.5rem);
    transform: translateY(-50%);
  }

  .js .site-nav:not(.is-open) .nav__item--lang .nav__link { padding: 0.45rem; }

  .js .site-nav.is-open {
    border-top: 1px solid var(--rule);
    padding-top: var(--sp-3);
  }

  .js .nav__list { flex-direction: column; align-items: center; gap: var(--sp-2); }
}

/* ==========================================================================
   6. Hero

   The original's hero is a full-width media band, 33% of the viewport wide in
   height, with the caption centred directly on it and no scrim. The video that
   filled it is replaced here by a still, and the still carries drifting motes
   — the motion the video would have given the band, rendered rather than
   encoded. See *The motes* at the end of this section.

   Stacking, back to front: artwork (0), veil (1), motes (2), caption (3).
   ========================================================================== */

.hero {
  position: relative;
  isolation: isolate;
  display: grid;
  align-content: center;
  justify-items: center;
  text-align: center;
  overflow: hidden;
  min-height: clamp(15rem, 33vw, 26rem);
  padding: var(--sp-5) var(--gutter);
  color: var(--indigo);
  background: linear-gradient(160deg, #1c1546 0%, #2a1f68 60%, #3b2d84 100%);
}

.hero__bg { position: absolute; inset: 0; z-index: 0; }

.hero__bg img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 45%;
}

/* Much lighter than a scrim that has to carry the caption on its own — the
   artwork and the motes both need to read through it. The caption takes its own
   pool of light below instead. */
.hero::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  background: linear-gradient(180deg,
    rgba(25, 18, 68, 0.18) 0%,
    rgba(25, 18, 68, 0.08) 45%,
    rgba(25, 18, 68, 0.22) 100%);
}

/* The caption's own scrim — what holds the original's near-black #070600 at
   contrast now that the veil is light. Sized to the caption rather than to the
   column, so on a sub-page it does not stretch the width of the container. */
.hero__inner {
  position: relative;
  z-index: 3;
  width: fit-content;
  max-width: 40rem;
  padding: clamp(1.25rem, 3vw, 2rem) clamp(1.5rem, 6vw, 3.5rem);
}

/* A pool of light rather than a panel: a blurred rounded rectangle drawn behind
   the text, so there is no edge to see — only a lighter patch of the artwork.
   A radial gradient was tried first and showed its corners: the text nearly
   fills its own box, so the gradient had nowhere left to fade out before the
   box ran out. Blur has no such constraint, because it can spill past the box.
   It sits above the motes, so they dim behind the caption rather than drifting
   across the words. */
.hero__inner::before {
  content: "";
  position: absolute;
  inset: -0.75rem -1rem;
  z-index: -1;
  border-radius: 2.5rem;
  background: rgba(255, 255, 255, 0.76);
  filter: blur(22px);
}

.hero__tagline {
  margin: 0 0 var(--sp-2);
  font-size: clamp(0.95rem, 1.7vw, 1.15rem);
  letter-spacing: 0.14em;
  color: var(--indigo);
}

.hero--page .hero__tagline {
  max-width: 34rem;
  letter-spacing: 0.06em;
}

/* Sizes are the original's, measured on the live page: caption 26.8px,
   sub-title 21.2px. The two greys are its own inline values. */
.hero__title {
  margin: 0;
  font-size: clamp(1.4rem, 2.4vw, 1.675rem);
  font-weight: 700;
  color: #070600;
}

.hero__subtitle {
  margin: var(--sp-1) 0 0;
  letter-spacing: 0.02em;
  font-size: clamp(1.05rem, 1.7vw, 1.326rem);
  color: #0a0a0a;
}

.hero__lede {
  margin: var(--sp-3) 0 0;
  font-size: var(--step-0);
  color: var(--ink);
}

.hero .btn-row { margin-top: var(--sp-4); }

.hero--page .btn--primary {
  background: var(--indigo);
  border-color: var(--indigo);
  color: #fff;
}

.hero--page .btn--primary:hover {
  background: var(--indigo-2);
  border-color: var(--indigo-2);
  color: #fff;
}

/* Sub-pages carry the band too — in the original every page opens with one,
   the home page's caption just has more in it. */
.hero--page { padding-block: var(--sp-4); }

/* ---- The motes ----------------------------------------------------------

   The artwork already has glowing orbs scattered through it. These are more of
   the same, drifting — the motion the original's background video would have
   given the band, rendered rather than encoded.

   A baked animation was built first and abandoned. libvips' animated-WebP
   writer does no inter-frame prediction, so every frame is a full keyframe:
   an 8-second 1280px loop came to 4.6 MB, against a page of about 100 KB, and
   no setting in sharp improved it (effort 0 → 6 moved 86 → 64 KB a frame).
   This costs roughly a kilobyte and runs at the display's own refresh rate.

   Every mote is an empty <span>; all of its variation comes from the
   :nth-child table below, so the markup is the same 24 spans on every page and
   no page carries a style attribute. The keyframes are written once and read
   their numbers from custom properties.

   Two nested transforms, because one element cannot carry both: the mote rises,
   and the dot inside it sways. The rise starts below the bottom edge and ends
   past the top, so the band's existing `overflow: hidden` hides both ends and
   no mote is ever seen to appear or vanish.

   `screen` lets a mote bloom where it crosses a bright ribbon instead of
   stacking flat on it, which is how the orbs in the artwork already behave. */

.hero__motes {
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  mix-blend-mode: screen;
}

.hero__mote {
  position: absolute;
  top: 100%;
  left: var(--x);
  width: var(--size);
  height: var(--size);
  margin-left: calc(var(--size) / -2);
  animation: hero-rise var(--dur) linear var(--delay) infinite;
}

.hero__mote::before {
  content: "";
  display: block;
  width: 100%;
  height: 100%;
  border-radius: 50%;
  background: radial-gradient(circle, var(--tint) 0%, transparent 68%);
  opacity: var(--op);
  animation: hero-sway var(--sway-dur) ease-in-out var(--delay) infinite alternate;
}

@keyframes hero-rise {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(0, calc(-1 * var(--travel)), 0); }
}

@keyframes hero-sway {
  from { transform: translate3d(calc(-1 * var(--sway)), 0, 0); }
  to   { transform: translate3d(var(--sway), 0, 0); }
}

/* The field — position, size, speed, phase and tint, spread by hand so that no
   two motes travel together. Slower and smaller reads as further away. The four
   tints are the artwork's own, warm gold-white dominating: the ground is
   blue-violet, so a warm mote reads as light rather than as another colour in
   the picture. Negative delays start each one mid-flight, so the band is alive
   on the first frame rather than filling up from empty. */
.hero__mote:nth-child(1)  { --x:  6%; --size: 14px; --dur: 26s; --delay:  -3s; --travel: 34rem; --op: .55; --tint: #fff4d6; --sway: 14px; --sway-dur:  9s; }
.hero__mote:nth-child(2)  { --x: 14%; --size:  7px; --dur: 31s; --delay: -17s; --travel: 30rem; --op: .40; --tint: #ffffff; --sway:  8px; --sway-dur: 11s; }
.hero__mote:nth-child(3)  { --x: 21%; --size: 22px; --dur: 22s; --delay:  -9s; --travel: 38rem; --op: .62; --tint: #7ae8ff; --sway: 18px; --sway-dur:  8s; }
.hero__mote:nth-child(4)  { --x: 28%; --size:  9px; --dur: 29s; --delay: -24s; --travel: 32rem; --op: .35; --tint: #b98cff; --sway: 10px; --sway-dur: 12s; }
.hero__mote:nth-child(5)  { --x: 35%; --size: 16px; --dur: 24s; --delay:  -1s; --travel: 36rem; --op: .70; --tint: #fff4d6; --sway: 15px; --sway-dur:  7s; }
.hero__mote:nth-child(6)  { --x: 41%; --size:  6px; --dur: 33s; --delay: -12s; --travel: 28rem; --op: .45; --tint: #ffffff; --sway:  6px; --sway-dur: 10s; }
.hero__mote:nth-child(7)  { --x: 47%; --size: 26px; --dur: 20s; --delay:  -6s; --travel: 40rem; --op: .50; --tint: #ff7ad9; --sway: 20px; --sway-dur:  9s; }
.hero__mote:nth-child(8)  { --x: 53%; --size: 11px; --dur: 27s; --delay: -21s; --travel: 33rem; --op: .58; --tint: #fff4d6; --sway: 12px; --sway-dur: 13s; }
.hero__mote:nth-child(9)  { --x: 59%; --size:  8px; --dur: 30s; --delay: -14s; --travel: 31rem; --op: .38; --tint: #7ae8ff; --sway:  9px; --sway-dur:  8s; }
.hero__mote:nth-child(10) { --x: 65%; --size: 18px; --dur: 23s; --delay:  -4s; --travel: 37rem; --op: .66; --tint: #ffffff; --sway: 16px; --sway-dur: 11s; }
.hero__mote:nth-child(11) { --x: 71%; --size:  6px; --dur: 34s; --delay: -28s; --travel: 28rem; --op: .42; --tint: #b98cff; --sway:  7px; --sway-dur:  9s; }
.hero__mote:nth-child(12) { --x: 77%; --size: 20px; --dur: 21s; --delay: -11s; --travel: 39rem; --op: .54; --tint: #fff4d6; --sway: 19px; --sway-dur:  7s; }
.hero__mote:nth-child(13) { --x: 83%; --size: 10px; --dur: 28s; --delay: -19s; --travel: 32rem; --op: .48; --tint: #ff7ad9; --sway: 11px; --sway-dur: 12s; }
.hero__mote:nth-child(14) { --x: 89%; --size: 13px; --dur: 25s; --delay:  -7s; --travel: 35rem; --op: .60; --tint: #7ae8ff; --sway: 13px; --sway-dur: 10s; }
.hero__mote:nth-child(15) { --x: 94%; --size:  7px; --dur: 32s; --delay: -26s; --travel: 29rem; --op: .36; --tint: #ffffff; --sway:  8px; --sway-dur: 13s; }
.hero__mote:nth-child(16) { --x: 10%; --size: 24px; --dur: 19s; --delay: -15s; --travel: 42rem; --op: .44; --tint: #b98cff; --sway: 21px; --sway-dur:  8s; }
.hero__mote:nth-child(17) { --x: 24%; --size:  5px; --dur: 35s; --delay:  -2s; --travel: 27rem; --op: .50; --tint: #fff4d6; --sway:  5px; --sway-dur: 11s; }
.hero__mote:nth-child(18) { --x: 38%; --size: 12px; --dur: 26s; --delay: -23s; --travel: 34rem; --op: .64; --tint: #ffffff; --sway: 14px; --sway-dur:  9s; }
.hero__mote:nth-child(19) { --x: 50%; --size:  9px; --dur: 29s; --delay: -10s; --travel: 30rem; --op: .40; --tint: #7ae8ff; --sway: 10px; --sway-dur: 12s; }
.hero__mote:nth-child(20) { --x: 62%; --size: 17px; --dur: 22s; --delay: -30s; --travel: 38rem; --op: .52; --tint: #fff4d6; --sway: 17px; --sway-dur:  7s; }
.hero__mote:nth-child(21) { --x: 74%; --size:  6px; --dur: 33s; --delay:  -5s; --travel: 28rem; --op: .46; --tint: #ff7ad9; --sway:  6px; --sway-dur: 10s; }
.hero__mote:nth-child(22) { --x: 86%; --size: 15px; --dur: 24s; --delay: -18s; --travel: 36rem; --op: .68; --tint: #b98cff; --sway: 15px; --sway-dur:  9s; }
.hero__mote:nth-child(23) { --x: 44%; --size: 11px; --dur: 27s; --delay: -33s; --travel: 33rem; --op: .35; --tint: #ffffff; --sway: 12px; --sway-dur: 13s; }
.hero__mote:nth-child(24) { --x: 68%; --size: 21px; --dur: 20s; --delay:  -8s; --travel: 41rem; --op: .58; --tint: #7ae8ff; --sway: 18px; --sway-dur:  8s; }

/* Half the field on a phone: two dozen composited layers is more than a small
   screen needs, and the band is only a fifth of the viewport there. */
@media (max-width: 639px) {
  .hero__mote:nth-child(n + 13) { display: none; }
}

/* The only thing here that depends on motion. Removing the field leaves the band
   exactly as it was before any of this existed — the still, the veil and the
   caption are all still there. */
@media (prefers-reduced-motion: reduce) {
  .hero__motes { display: none; }
}

/* ==========================================================================
   7. Buttons and links
   ========================================================================== */

.btn {
  display: inline-block;
  padding: 0.6rem 1.5rem;
  border: 1px solid transparent;
  border-radius: var(--radius);
  font-size: 0.9375rem;
  font-weight: 500;
  line-height: 1.5;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  transition: background-color 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}

/* The original's 更多信息 button: soft green ground, dark green ink. */
.btn--primary {
  background: var(--indigo);
  border-color: var(--indigo);
  color: #fff;
}
.btn--primary:hover { background: var(--indigo-2); border-color: var(--indigo-2); color: #fff; }

.btn--outline {
  background: transparent;
  border-color: var(--indigo);
  color: var(--indigo);
}
.btn--outline:hover { background: var(--indigo); color: #fff; }

.btn--link {
  padding-inline: 0;
  border: 0;
  background: none;
  color: var(--indigo);
  text-decoration: underline;
  text-underline-offset: 0.2em;
}

.btn-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
}

.btn-row--center { justify-content: center; }

/* ==========================================================================
   8. Section furniture
   ========================================================================== */

.section__head { margin-bottom: var(--sp-4); text-align: center; }

.section__head h2 { margin: 0; }

/* A section label that is also the heading — an <h2> styled as a label, so no
   new headline had to be invented for a section that had none. */
.eyebrow {
  font-weight: 700;
  letter-spacing: 0.02em;
  color: var(--indigo);
}

/* The opening statement: centred, indigo, in the original's narrow measure. */
.statement {
  max-width: var(--measure);
  margin-inline: auto;
  text-align: center;
  color: var(--indigo);
}

.statement h2 { margin-bottom: var(--sp-3); }

.statement__lead { font-size: var(--step-1); }

/* ==========================================================================
   9. Services — home, 服务项目

   The original sets the two services as a centred pair of columns, image on
   top and the copy beneath it, left-aligned inside each column.
   ========================================================================== */

/* Not a grid of equal columns: the original sizes each column to its own
   image, so the two are different widths at a shared height, centred as a
   pair. The copy below then wraps to that same width — which is why the
   original's left-hand paragraph breaks where it does. */
.services {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: clamp(1.5rem, 3vw, 2.25rem);
}

.service {
  flex: 0 1 auto;
  min-width: 0;
  max-width: 100%;
  display: flex;
  flex-direction: column;
  padding: 0.5rem 1rem 1rem;
  border: 1px solid var(--rule);
  background: var(--paper);
  text-align: center;
}

.service__media {
  display: block;
  height: clamp(13rem, 39vw, 31rem);
  width: auto;
  max-width: 100%;
  margin: 0 auto var(--sp-3);
  object-fit: cover;
}

/* Stacked, the shared height would leave the images narrow and short, so they
   go back to filling the column at their own ratio. */
@media (max-width: 799px) {
  .services { display: grid; gap: var(--sp-5); }
  .service__media { width: 100%; height: auto; }
}

.service__title { margin-bottom: var(--sp-3); }

.service__body { flex: 1; text-align: left; }

.service__body > p:first-child { margin-top: 0; }

/* The original's numbered 1/2/3/4 run, drawn by a counter so the number stays
   out of the text; the lettered A/B/C run carries its letter in the text
   already, so that list takes no marker at all. */
.service__body ol,
.service__body ul {
  margin: 0 0 var(--sp-3);
  padding: 0;
  list-style: none;
}

.service__body ol { counter-reset: serviceitem; }

.service__body ol > li {
  position: relative;
  padding-left: 1.9em;
  margin-bottom: 0.6em;
  counter-increment: serviceitem;
}

.service__body ol > li::before {
  content: counter(serviceitem) "、";
  position: absolute;
  left: 0;
  top: 0;
  color: var(--ink);
}

.service__actions { margin-top: var(--sp-4); text-align: center; }

.service__summary {
  margin: calc(var(--sp-1) * -1) 0 var(--sp-3);
  color: var(--ink-2);
  text-align: left;
}

.trust-grid {
  display: grid;
  gap: 1px;
  background: var(--rule);
  border: 1px solid var(--rule);
}

.trust-point {
  padding: var(--sp-3);
  background: var(--paper);
}

.trust-point__num {
  display: block;
  margin-bottom: var(--sp-1);
  color: var(--ink-3);
  font-size: var(--step--1);
  font-weight: 700;
  letter-spacing: 0.12em;
}

.trust-point h3 { margin-bottom: var(--sp-1); }
.trust-point p { margin-bottom: 0; color: var(--ink-2); }

@media (min-width: 640px) {
  .trust-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* ==========================================================================
   10. Case study — 个人能量重塑, 企业能量优化
   ========================================================================== */

.case {
  display: grid;
  gap: clamp(1.5rem, 4vw, 2.5rem);
  padding-block: clamp(2rem, 5vw, 3.5rem);
  border-top: 1px solid var(--rule);
}

.case:first-child { border-top: 0; padding-top: 0; }
.case:last-child { padding-bottom: 0; }

@media (min-width: 800px) {
  .case { grid-template-columns: 17rem minmax(0, 1fr); align-items: start; }
}

.case__media img {
  width: 100%;
  aspect-ratio: 3 / 4;
  object-fit: cover;
  object-position: center 40%;
}

.case__title {
  margin-bottom: var(--sp-3);
  font-size: clamp(1.25rem, 2.2vw, 1.55rem);
  line-height: 1.35;
}

/* The numeral that opens a numbered block, carried over from the original's
   1/2/3/4 in the heading text. */
.case__num {
  display: block;
  margin-bottom: var(--sp-1);
  font-size: var(--step-0);
  font-weight: 700;
  letter-spacing: 0.1em;
  color: var(--ink-3);
}

.hero--page .hero__actions { margin-top: var(--sp-3); }

/* ==========================================================================
   11. Content blocks
   ========================================================================== */

.callout {
  margin-block: var(--sp-3);
  padding: var(--sp-3);
  background: var(--surface-tint);
  border-left: 3px solid var(--indigo);
}

.callout__label {
  display: block;
  margin-bottom: var(--sp-2);
  font-size: var(--step--1);
  font-weight: 700;
  color: var(--indigo);
}

.block { margin-top: var(--sp-4); }

.block__label {
  margin: 0 0 var(--sp-2);
  font-size: var(--step-1);
  font-weight: 700;
  color: var(--indigo);
}

.case__body .block + .block {
  padding-top: var(--sp-3);
  border-top: 1px solid var(--rule);
}

.case-toggle {
  display: block;
  margin: calc(var(--sp-2) * -1) 0 var(--sp-3) auto;
  padding: 0.35rem 0.75rem;
  border: 1px solid var(--rule-strong);
  border-radius: var(--radius);
  background: var(--paper);
  color: var(--indigo);
  font: inherit;
  font-size: var(--step--1);
  cursor: pointer;
}

.case-toggle:hover { border-color: var(--indigo); }

.case.is-collapsed .case__body > :not(.case__title):not(.case-toggle) { display: none; }
.case.is-collapsed .case__title { margin-bottom: 0; }

/* --- Definition-list "facts" table --------------------------------------- */

.facts {
  margin: var(--sp-3) 0 0;
  border-top: 1px solid var(--rule);
}

.facts__row {
  display: grid;
  gap: 0.35rem var(--sp-3);
  padding-block: var(--sp-3);
  border-bottom: 1px solid var(--rule);
}

@media (min-width: 640px) {
  .facts__row { grid-template-columns: 7rem minmax(0, 1fr); }
}

@media (max-width: 799px) {
  .case-nav {
    position: static;
    margin-top: calc(var(--sp-3) * -1);
    margin-bottom: var(--sp-4);
    border-radius: var(--radius);
  }
}

.facts__label {
  font-size: var(--step--1);
  font-weight: 700;
  color: var(--indigo);
}

.facts__value > :last-child { margin-bottom: 0; }

/* --- Marked lists --------------------------------------------------------
   :where() keeps these at zero specificity so the marker rules below, which
   are more specific, always win on a list that carries one. */

:where(.facts__value, .case__body) ul { list-style: none; padding-left: 0; }
:where(.facts__value, .case__body) li { position: relative; padding-left: 1.1em; }
:where(.facts__value, .case__body) li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.85em;
  width: 0.5em;
  height: 1px;
  background: var(--rule-strong);
}

.results li::before,
.checklist li::before,
.arrowlist li::before {
  top: 0;
  width: auto;
  height: auto;
  background: none;
  color: var(--indigo);
}

.results li::before { content: "✓"; font-weight: 700; }
.checklist li::before { content: "☑"; }
.arrowlist li::before { content: "▸"; }

/* ==========================================================================
   12. People — 关于我们
   ========================================================================== */

.person {
  display: grid;
  gap: clamp(1.25rem, 3vw, 2rem);
  padding-block: clamp(1.75rem, 4vw, 2.75rem);
  border-top: 1px solid var(--rule);
}

.person:first-of-type { border-top: 0; }

@media (min-width: 620px) {
  .person { grid-template-columns: 12rem minmax(0, 1fr); align-items: start; }
}

/* A portrait tile, matching the original. It cropped these two on the CDN with a
   ratio per photo — 心莲 at 0.6826:1 pushed down to offset-y 65%, 姝宏 at 0.75:1
   centred — so both came out portrait and showed head and upper body rather than
   a square headshot. A square (which this was) keeps only 45% of 心莲's 720x1600,
   because that photo is nearly twice as tall as it is wide.
   姝宏's file is already 3:4, so cover has no overflow here and the whole photo
   shows; 心莲 needs the taller box and the downward offset. Re-check both if
   either photo is replaced. */
.person__photo img {
  width: 100%;
  aspect-ratio: 3 / 4;
  object-fit: cover;
  object-position: center 50%;
}

/* 心莲's tile in the original is the taller of the two. `object-position: 65%`
   is its `offset-y65`: it puts the 0.6826:1 window over the same band of her
   photo, from just above her head down to mid-torso. */
.person__photo--tall img {
  aspect-ratio: 0.6826;
  object-position: center 65%;
}

.person__name { margin-bottom: 0.25rem; }

.person__role {
  margin-bottom: var(--sp-2);
  font-size: var(--step--1);
  font-weight: 700;
  color: var(--indigo);
}

.credentials {
  margin: 0 0 var(--sp-2);
  padding-left: 1.2em;
  color: var(--ink-2);
}

/* ==========================================================================
   13. Contact — 联系我们

   No cards here: the original separates everything with a hairline and an
   indigo label, and nothing floats on a tinted panel.
   ========================================================================== */

.contact-primary {
  display: grid;
  gap: var(--sp-3) var(--sp-4);
  margin-bottom: var(--sp-5);
}

.contact-note {
  max-width: var(--measure);
  margin: 0 auto var(--sp-4);
  padding: var(--sp-3);
  background: var(--surface-tint);
  border-left: 3px solid var(--indigo);
  color: var(--ink-2);
  text-align: center;
}

.contact-note p { margin-bottom: 0; }

@media (min-width: 640px) {
  .contact-primary { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

.contact-method {
  display: block;
  padding-top: var(--sp-2);
  border-top: 1px solid var(--rule);
  color: inherit;
  text-decoration: none;
}

a.contact-method:hover .contact-method__value { color: var(--indigo); }

.contact-method__label {
  margin: 0;
  font-size: var(--step--1);
  font-weight: 700;
  color: var(--indigo);
}

/* The one place a long Latin string has to break rather than push the
   container wide: an email address has no space to wrap at. */
.contact-method__value {
  margin: var(--sp-1) 0 0;
  font-family: var(--font-latin);
  font-size: var(--step-1);
  color: var(--ink);
  overflow-wrap: anywhere;
}

.copy-btn {
  margin-top: var(--sp-2);
  padding: 0.35rem 0.85rem;
  background: none;
  border: 1px solid var(--rule-strong);
  border-radius: var(--radius);
  font-family: inherit;
  font-size: var(--step--1);
  color: var(--ink-2);
  cursor: pointer;
  transition: border-color 0.18s ease, color 0.18s ease;
}

.copy-btn:hover { border-color: var(--indigo); color: var(--indigo); }

.offices { display: grid; gap: var(--sp-4); }

@media (min-width: 720px) {
  .offices { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

.office {
  padding-top: var(--sp-3);
  border-top: 1px solid var(--rule);
}

.office__label {
  margin: 0 0 var(--sp-1);
  font-size: var(--step--1);
  font-weight: 700;
  color: var(--indigo);
}

.office__name { margin: 0 0 var(--sp-1); color: var(--ink); }

.office__lines,
.office address {
  margin: 0;
  font-style: normal;
  font-size: var(--step--1);
  line-height: 1.7;
  color: var(--ink-2);
}

/* ==========================================================================
   14. Footer — the original's green band
   ========================================================================== */

.site-footer {
  margin-top: var(--section);
  padding-block: var(--sp-4);
  background: var(--green);
  color: var(--green-ink);
}

.footer__grid {
  display: grid;
  gap: var(--sp-3);
}

@media (min-width: 760px) {
  .footer__grid {
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: var(--sp-3) var(--sp-4);
  }
  /* The brand takes a full row of its own, so the longer English name and the
     addresses below it stop wrapping into ragged two-word lines. */
  .footer__grid > :first-child { grid-column: 1 / -1; }
}

.site-footer a { color: var(--green-ink); }

.footer__brand {
  margin-bottom: 0.25rem;
  font-weight: 700;
  color: var(--green-ink);
}

.footer__heading {
  margin-bottom: 0.25rem;
  font-size: var(--step--1);
  font-weight: 700;
  color: var(--green-ink);
}

.footer__address,
.footer__list {
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: var(--step--1);
  font-style: normal;
  color: var(--green-ink);
}

.footer__bottom {
  margin-top: var(--sp-4);
  padding-top: var(--sp-3);
  border-top: 1px solid rgba(45, 76, 23, 0.25);
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2) var(--sp-3);
  justify-content: space-between;
  font-size: var(--step--1);
}

.footer__bottom:first-child { margin-top: 0; padding-top: 0; border-top: 0; }

/* ==========================================================================
   15. Utilities
   ========================================================================== */

.is-decorative { pointer-events: none; }

.mt-4 { margin-top: var(--sp-4); }

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 10;
  padding: 0.6rem 1rem;
  background: var(--indigo);
  color: #fff;
  text-decoration: none;
}

.skip-link:focus { left: 0; }

/* ==========================================================================
   16. Focus, motion, print
   ========================================================================== */

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

@media print {
  .site-header, .site-footer, .nav-toggle, .btn { display: none; }
  body { color: #000; background: #fff; }
  a { text-decoration: underline; }
}
