/*
 * Lemon AI STUDIO homepage, v3 layer.
 *
 * Loaded after public.css and home-v2.css. It overrides no palette, radius,
 * shadow or font token: the hero stage (.hp-demo / .hp-stage / .hp-chat /
 * .hp-flow), the number strip and every section component come from the shared
 * layers, so the homepage reads as the same product as pricing and the inner
 * pages. All that is left here is the homepage display scale, pulled back
 * towards the shared one, and the two small hero-copy pieces v3 adds.
 */

/* Homepage headings stay a step above the inner pages, not a different scale:
   h1 ~1.2x the shared display size, h2 just over the shared section size.
   home-v2 ran them to 58px / 38px against the inner pages' 35px / 25px. */
body.v3.home-page {
  --v2-h1: clamp(38px, 3.4vw, 54px);
  --v2-h2: clamp(24px, 2.05vw, 29px);
}

/* ---------- Hero copy ---------- */
/* The copy is now short next to a tall stage, so it sits centred against it
   rather than hanging from the top with empty space below. */
body.v3 .hp-hero .container { align-items: center; }

/* home-v2 stretches the hero to a full screen (up to 920px). Any min-height
   taller than the content just leaves a blank band under the demo panel, so the
   hero is content-sized: fixed padding top and bottom, and the number strip
   follows straight after. That also keeps the strip on the first screen. */
@media (min-width: 1081px) {
  body.v3 .hp-hero { min-height: 0; padding-block: clamp(22px, 2.1vw, 40px) clamp(18px, 1.6vw, 30px); }
}

/* Compacted number strip: it shares the first screen now, so it gets the room
   it needs and no more. home-v2 runs 40px block padding and a 44px numeral. */
body.v3 .hp-numbers__list > div { padding-block: clamp(22px, 1.9vw, 34px); }
body.v3 .hp-numbers dt b { font-size: clamp(32px, 2.4vw, 38px); }
body.v3 .hp-numbers dd { margin-top: .7em; }

/* Short laptops (1366x768 and friends): the first screen has ~690px to hold a
   557px demo panel plus the strip, so the hero's padding, the chat's internal
   spacing and the strip all give up a little rather than the strip dropping
   below the fold. The chat body's 32em reserve goes content-sized here; nothing
   jumps, because unrevealed messages hold their space either way. */
@media (min-width: 1081px) and (max-height: 840px) {
  body.v3 .hp-hero { padding-block: 20px 24px; }
  body.v3.home-page .hp-stage .hp-chat__body { gap: .55em; padding: 1em 1.3em .9em; min-height: 0; }
  body.v3.home-page .hp-stage .hp-chat__input { margin: 0 1.3em 1.1em; }
  body.v3 .hp-numbers__list > div { padding-block: 18px; }
}


/* Tighter leading than home-v2's 1.22 so the two lines read as one statement.
   Tracking is not adjustable here: site.css has a global
   `h1, h2 { letter-spacing: 0 !important }` that no page stylesheet can reach. */
body.v3 .hp-hero h1 { line-height: 1.16; }




/* ---------- Hero stage: back to one light panel ----------
 * home-v2.css re-themes .home-page .hp-stage into a green tray holding a white
 * chat card and a dark (#1c2622) flow card. The rest of the site has no dark
 * surface except the docs code block, and the split cards read as two separate
 * widgets. These rules put the stage back to the treatment the shared layer and
 * studio-home use: a single white panel, the two columns divided by one
 * hairline, the flow on #fafbf9. Values match home.css; selectors carry
 * body.v3 only to outspecify the home-v2 block.
 */
body.v3.home-page .hp-stage {
  /* The chat bar is 4.4em of the stage's own font size. The flow head's em is
     its 11px label size, so home.css's calc(var(--hp-bar) / .76) lands 6.5px
     low and the two hairlines miss each other. Resolve the bar height in px
     once, off the same clamp home-v2 sets on .hp-stage, and share it. */
  --hp-bar-h: calc(4.4 * clamp(13px, min(.82vw, 1.62vh), 16px));
  grid-template-columns: minmax(0, 1.12fr) minmax(0, 1fr);
  grid-template-rows: auto;
  column-gap: 0;
  overflow: hidden;
  padding: 0;
  border: 1px solid var(--hp-line);
  border-radius: var(--hp-radius);
  background: #fff;
  box-shadow: var(--hp-shadow-float);
}
body.v3.home-page .hp-stage .hp-chat { grid-column: auto; grid-row: auto; border: 0; border-radius: 0; background: #fff; box-shadow: none; }
body.v3.home-page .hp-stage .hp-flow {
  grid-column: auto; grid-row: auto; align-self: stretch;
  min-height: 0; margin-top: 0; padding: 0 1.6em 1.6em;
  border: 0; border-left: 1px solid var(--hp-line-soft); border-radius: 0;
  color: var(--hp-text); background: #fafbf9; box-shadow: none;
}
body.v3.home-page .hp-stage .hp-flow__head { box-sizing: border-box; height: var(--hp-bar-h); margin: 0 0 1.5em; padding: 0; border-bottom: 1px solid var(--hp-line-soft); color: var(--hp-label); letter-spacing: .12em; }
/* Under 1440 the flow column is too narrow for the label plus the status pill
   on one line, and the label would wrap inside a bar whose height is fixed.
   home-v2 drops the tracking at 1081-1180 for the same reason. Must stay after
   the rule above: same specificity, so source order decides. */
@media (max-width: 1439px) {
  body.v3.home-page .hp-stage .hp-flow__head { letter-spacing: .02em; }
}
/* At the narrowest two-column widths even tight tracking can't fit the brand
   prefix beside the status pill; "后台处理" alone still says what the column is. */
@media (min-width: 1081px) and (max-width: 1240px) {
  body.v3.home-page .v3-flow-brand { display: none; }
}
body.v3.home-page .hp-stage .hp-flow__head > span:first-child { white-space: nowrap; }
/* Flow internals: the light palette from public.css. */
body.v3.home-page .hp-stage .hp-flow__status { color: var(--hp-muted); background: #f1f3f0; }
body.v3.home-page .hp-stage .hp-flow__status::before { background: #b3bdb6; }
body.v3.home-page .hp-stage .hp-flow__status[data-state="run"],
body.v3.home-page .hp-stage .hp-flow__status[data-state="done"] { color: var(--hp-jade-deep); background: var(--hp-tint); }
body.v3.home-page .hp-stage .hp-flow__status[data-state="run"]::before { background: var(--hp-jade); }
body.v3.home-page .hp-stage .hp-flow__status[data-state="done"]::before { border-color: var(--hp-jade); background: none; }
body.v3.home-page .hp-stage .hp-flow__idle { color: var(--hp-faint); }
body.v3.home-page .hp-stage .hp-flow__idle i { background: #9cc5b5; }
body.v3.home-page .hp-stage .hp-flow__list::before { background: var(--hp-line); }
body.v3.home-page .hp-stage.is-animated .hp-flow__step:not(:last-child)::before { background: #cfe3da; }
body.v3.home-page .hp-stage .hp-flow__icon { border-color: var(--hp-line); color: var(--hp-icon); background: #fff; }
body.v3.home-page .hp-stage .hp-flow__step.is-run .hp-flow__icon { border-color: #9fcab9; color: var(--hp-jade); }
body.v3.home-page .hp-stage .hp-flow__step.is-on .hp-flow__icon { border-color: #bfdccf; color: var(--hp-jade-deep); background: #eef6f1; }
body.v3.home-page .hp-stage .hp-flow__step strong { color: var(--hp-ink); }
body.v3.home-page .hp-stage .hp-flow__step small { color: var(--hp-muted); }
body.v3.home-page .hp-stage .hp-flow__step.is-run strong::after { color: var(--hp-faint); }
body.v3.home-page .hp-stage .hp-flow__chips i { color: #4a5a50; background: #f0f4f1; }
body.v3.home-page .hp-stage .hp-hits span { color: var(--hp-text); }
body.v3.home-page .hp-stage .hp-hits b { color: var(--hp-ink); }
body.v3.home-page .hp-stage .hp-hits i { background: var(--hp-line-soft); }
body.v3.home-page .hp-stage .hp-hits i::before { background: #5fa58c; }

@media (max-width: 640px) {
  body.v3.home-page .hp-stage { grid-template-columns: minmax(0, 1fr); border-radius: 16px; font-size: 13px; }
  body.v3.home-page .hp-stage .hp-flow { border-top: 1px solid var(--hp-line-soft); border-left: 0; }
}


/* ---------- Hero stage: colour ----------
 * Jade only. Greys that carried no meaning become light jade tints; the user
 * turn and finished results are solid or full-strength jade. The only other
 * colour on the panel is the assistant glow on the phone screen (below), which
 * shows only while Studio is working.
 * #27806a is the deepest jade that keeps 13px white text above 4.5:1.
 * Kept last so it wins over the light-panel block by source order.
 */
body.v3.home-page {
  --v3-jade: #27806a;
  --v3-jade-tint: #e6f3ec;
  --v3-jade-line: #d3e7db;
}

/* Chat: user turn solid jade, assistant turn a light jade tint instead of grey. */
body.v3.home-page .hp-stage .hp-msg--user { background: var(--v3-jade); box-shadow: none; }
body.v3.home-page .hp-stage .hp-msg--ai,
body.v3.home-page .hp-stage .hp-dots { color: #2f4a3f; background: var(--v3-jade-tint); }
body.v3.home-page .hp-stage .hp-dots i { background: #8fbfa9; }
body.v3.home-page .hp-stage .hp-product { border-color: var(--v3-jade-line); }
body.v3.home-page .hp-stage .hp-product__meta b { color: var(--v3-jade); }
body.v3.home-page .hp-stage .hp-chat__input.has-text { border-color: #9fcdb9; }
body.v3.home-page .hp-stage .hp-chat__input.has-text .hp-chat__send,
body.v3.home-page .hp-stage.is-static .hp-chat__send { background: var(--v3-jade); }

/* Flow */
body.v3.home-page .hp-stage .hp-flow__head { border-bottom-color: var(--v3-jade-line); }
body.v3.home-page .hp-stage .hp-flow__chips i { color: #2f6b58; background: var(--v3-jade-tint); }
body.v3.home-page .hp-stage .hp-flow__status[data-state="run"],
body.v3.home-page .hp-stage .hp-flow__status[data-state="done"] { color: var(--v3-jade); background: var(--v3-jade-tint); }
body.v3.home-page .hp-stage .hp-flow__status[data-state="run"]::before { background: var(--v3-jade); }
body.v3.home-page .hp-stage .hp-flow__status[data-state="done"]::before { border-color: var(--v3-jade); }
/* Step icons: running = white disc, jade ring and icon, pulsing (public.css
   hp-ring); done = jade tint disc. public.css transitions border and colour but
   not background, which flashed a dark disc for .4s; transition all three. */
body.v3.home-page .hp-stage .hp-flow__icon { transition: border-color .4s ease, color .4s ease, background-color .4s ease; }
body.v3.home-page .hp-stage .hp-flow__step.is-run .hp-flow__icon { border-color: var(--v3-jade); color: var(--v3-jade); background: #fff; }
body.v3.home-page .hp-stage .hp-flow__step.is-on .hp-flow__icon { border-color: #a9d2bf; color: var(--v3-jade); background: var(--v3-jade-tint); }
body.v3.home-page .hp-stage.is-animated .hp-flow__step:not(:last-child)::before { background: #a9d2bf; }
body.v3.home-page .hp-stage .hp-flow__step.is-on strong::after { border-color: var(--v3-jade); }
/* Retrieval scores: one hue, strength by depth. */
body.v3.home-page .hp-stage .hp-hits i { background: #e1ece5; }
body.v3.home-page .hp-stage .hp-hits li:nth-child(1) i::before { background: var(--v3-jade); }
body.v3.home-page .hp-stage .hp-hits li:nth-child(2) i::before { background: #7fbea3; }
body.v3.home-page .hp-stage .hp-hits li:nth-child(3) i::before { background: #c4cec7; }
body.v3.home-page .hp-stage .hp-hits li:nth-child(1) b { color: var(--v3-jade); }

/* ---------- Hero stage: the chat as an iPhone ----------
 * The stage becomes one mint surface: the phone on the left, the flow column on
 * the right with no dividing rule. The phone has iPhone 15 proportions
 * (71.6 x 146.6 mm); its height comes from the stage and the width from the
 * ratio, and the conversation scrolls inside it instead of stretching it.
 */
body.v3.home-page .hp-stage {
  grid-template-columns: auto minmax(0, 1fr);
  column-gap: clamp(22px, 2.4vw, 44px);
  padding: clamp(12px, 1vw, 18px) clamp(18px, 1.8vw, 30px);
  border-color: var(--v3-jade-line);
  background: #f2f8f4;
  --v3-phone-h: 44em;
  --v3-bezel: 7px;
}
body.v3.home-page .hp-stage .hp-chat.v3-phone {
  position: relative;
  display: flex; flex-direction: column;
  overflow: hidden;
  height: var(--v3-phone-h);
  aspect-ratio: 71.6 / 146.6;
  align-self: center;
  border: var(--v3-bezel) solid #1e2321;
  /* Screen corner is 47pt of 390pt; the phone itself is not inside its own
     container, so derive it from the phone height instead of --pt. */
  border-radius: calc(var(--v3-bezel) + var(--v3-phone-h) * .4884 * .1205);
  background: #ededed;
  box-shadow: 0 0 0 1px #3a403d, 0 28px 50px -30px rgba(20, 40, 30, .45), 0 2px 6px rgba(20, 40, 30, .08);
  /* Everything inside is measured in iPhone points: the screen is 390pt wide,
     so 1pt = 1/390 of it. Type, avatars, bars and spacing then keep WeChat's
     real proportions at any phone size. */
  container-type: inline-size;
  --pt: calc(100cqw / 390);
}
/* Points resolve against the screen (the container), so children re-declare. */
body.v3.home-page .hp-stage .v3-phone * { --pt: calc(100cqw / 390); }
/* The flow column floats on the same surface; no rule, no fill of its own. */
body.v3.home-page .hp-stage .hp-flow { padding: 0 .4em .4em; border-left: 0; background: transparent; }
body.v3.home-page .hp-stage .hp-flow__head { height: 3.4em; }

/* ---------- Assistant glow ----------
 * While Studio is working (status pill data-state="run", i.e. 理解需求 until
 * 生成推荐回答 is done) the screen edge glows the way Apple Intelligence does:
 * Apple's palette on a rotating angular gradient, blurred, fading inward from
 * the screen edge — no stroke, no hard line, no blur filter. Semi-transparent, so the chat
 * stays readable under it. Fades out when the answer arrives.
 * Requested for this demo; the only gradient on the site, scoped here.
 */
.v3-glow {
  position: absolute; inset: 0; z-index: 4; overflow: hidden;
  border-radius: calc(47 * var(--pt));
  pointer-events: none;
  opacity: 0;
  transition: opacity .7s ease;
  /* Built the way Apple layers the Siri edge glow: concentric strokes on the
     screen edge, each wider, softer and fainter than the last — a bright 10pt
     line, a 26pt glow, a 64pt halo, and a 170pt wash at 7% that reaches toward
     the centre without tinting the conversation. Drawn on the screen's 390pt
     grid with its 47pt corners, so the glow follows the rounded corners. */
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 390 820' preserveAspectRatio='none'%3E%3Cfilter id='b0' x='-50%25' y='-50%25' width='200%25' height='200%25'%3E%3CfeGaussianBlur stdDeviation='2'/%3E%3C/filter%3E%3Cfilter id='b1' x='-50%25' y='-50%25' width='200%25' height='200%25'%3E%3CfeGaussianBlur stdDeviation='8'/%3E%3C/filter%3E%3Cfilter id='b2' x='-50%25' y='-50%25' width='200%25' height='200%25'%3E%3CfeGaussianBlur stdDeviation='18'/%3E%3C/filter%3E%3Cfilter id='b3' x='-50%25' y='-50%25' width='200%25' height='200%25'%3E%3CfeGaussianBlur stdDeviation='44'/%3E%3C/filter%3E%3Crect x='0' y='0' width='390' height='820' rx='47' fill='none' stroke='%23000' stroke-width='10' stroke-opacity='1' filter='url(%23b0)'/%3E%3Crect x='0' y='0' width='390' height='820' rx='47' fill='none' stroke='%23000' stroke-width='26' stroke-opacity='0.6' filter='url(%23b1)'/%3E%3Crect x='0' y='0' width='390' height='820' rx='47' fill='none' stroke='%23000' stroke-width='64' stroke-opacity='0.24' filter='url(%23b2)'/%3E%3Crect x='0' y='0' width='390' height='820' rx='47' fill='none' stroke='%23000' stroke-width='170' stroke-opacity='0.07' filter='url(%23b3)'/%3E%3C/svg%3E") 0 0 / 100% 100% no-repeat;
          mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 390 820' preserveAspectRatio='none'%3E%3Cfilter id='b0' x='-50%25' y='-50%25' width='200%25' height='200%25'%3E%3CfeGaussianBlur stdDeviation='2'/%3E%3C/filter%3E%3Cfilter id='b1' x='-50%25' y='-50%25' width='200%25' height='200%25'%3E%3CfeGaussianBlur stdDeviation='8'/%3E%3C/filter%3E%3Cfilter id='b2' x='-50%25' y='-50%25' width='200%25' height='200%25'%3E%3CfeGaussianBlur stdDeviation='18'/%3E%3C/filter%3E%3Cfilter id='b3' x='-50%25' y='-50%25' width='200%25' height='200%25'%3E%3CfeGaussianBlur stdDeviation='44'/%3E%3C/filter%3E%3Crect x='0' y='0' width='390' height='820' rx='47' fill='none' stroke='%23000' stroke-width='10' stroke-opacity='1' filter='url(%23b0)'/%3E%3Crect x='0' y='0' width='390' height='820' rx='47' fill='none' stroke='%23000' stroke-width='26' stroke-opacity='0.6' filter='url(%23b1)'/%3E%3Crect x='0' y='0' width='390' height='820' rx='47' fill='none' stroke='%23000' stroke-width='64' stroke-opacity='0.24' filter='url(%23b2)'/%3E%3Crect x='0' y='0' width='390' height='820' rx='47' fill='none' stroke='%23000' stroke-width='170' stroke-opacity='0.07' filter='url(%23b3)'/%3E%3C/svg%3E") 0 0 / 100% 100% no-repeat;
}
/* A square larger than the screen's diagonal, rotating, so the colours travel
   round the edge. One layer, no filter: a blurred layer that rotates has to be
   re-blurred every frame, which shows as flicker (Safari especially), and two
   layers at different speeds beat against each other. Softness comes from the
   feathered mask on .v3-glow instead; rotating an unfiltered layer is a pure
   compositor transform. */
.v3-glow::before, .v3-glow::after {
  content: ""; position: absolute; top: 50%; left: 50%;
  width: 260%; aspect-ratio: 1;
  transform: translate(-50%, -50%) rotate(0deg);
  will-change: transform, opacity;
  backface-visibility: hidden;
}
.v3-glow::before {
  background: conic-gradient(#bc82f3, #f5b9ea, #8d9fff, #aa6eee, #ff6778, #ffba71, #c686ff, #bc82f3);
  animation: v3-glow-spin 4s linear infinite;
}
/* Second layer: the same palette a third of a turn on, spinning the other way
   and pulsing, so the edge shimmers — colours swell and fade as they pass
   instead of one band just rotating. Still no filter, so it stays on the
   compositor. */
.v3-glow::after {
  background: conic-gradient(from 120deg, #ff6778, #ffba71, #f5b9ea, #8d9fff, #bc82f3, #c686ff, #ff6778);
  animation: v3-glow-spin 5.5s linear infinite reverse, v3-glow-pulse 1.1s ease-in-out infinite alternate;
}
body.v3.home-page .hp-stage:has(.hp-flow__status[data-state="run"]) .v3-glow { opacity: .85; }
@keyframes v3-glow-pulse { from { opacity: .1; } to { opacity: .85; } }
@keyframes v3-glow-spin { to { transform: translate(-50%, -50%) rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .v3-glow::before, .v3-glow::after { animation: none; } }


@media (max-width: 640px) {
  body.v3.home-page .hp-stage { grid-template-columns: minmax(0, 1fr); row-gap: 14px; padding: 12px; }
  /* Phone fits in one screen with the copy above it, not a full screen on its own. */
  body.v3.home-page .hp-stage .hp-chat.v3-phone { justify-self: center; --v3-phone-h: min(42em, 66svh); }
  body.v3.home-page .hp-stage .hp-flow { border-top: 0; }
  /* The phone below is centred; left-aligned copy above it reads as tilted.
     Centre the copy on the same axis, full width so nothing is indented. */
  body.v3.home-page .hp-hero__copy { justify-self: stretch; justify-items: center; max-width: none; text-align: center; }
  body.v3.home-page .hp-hero__actions { justify-content: center; }
}

/* ---------- Phone screen: WeChat ----------
 * Measured from a WeChat iOS chat screenshot (390pt screen): 54pt status bar,
 * 44pt nav bar with a 17pt semibold centred title, 40pt avatars with 4pt
 * corners 12pt from the edge, 12pt to the bubble, bubbles 17pt / 24pt type with
 * 8pt x 12pt padding and 4pt corners, no tail, never wider than the space
 * between the two avatar columns; 16pt between messages; grey 13pt time stamp;
 * input bar with 30pt voice / emoji / plus icons and a white 4pt field.
 * System font, black text, WeChat's own colours — inside the phone only.
 */
body.v3.home-page .hp-stage .v3-phone {
  --wx-bg: #ededed; --wx-bar: #f7f7f7; --wx-green: #95ec69; --wx-ink: #191919;
  color: var(--wx-ink);
  font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Helvetica Neue", "Microsoft YaHei", sans-serif;
  letter-spacing: 0;
}
/* Point-based type starts one level down: the phone is not inside its own
   container, so a cqw font-size on it would resolve against the viewport and
   take the em-based phone height with it. */
body.v3.home-page .hp-stage .v3-phone > * { font-size: calc(17 * var(--pt)); }

/* Status bar */
.v3-phone__status { position: relative; display: flex; flex: none; align-items: center; justify-content: space-between; height: calc(54 * var(--pt)); padding: calc(4 * var(--pt)) calc(30 * var(--pt)) 0 calc(34 * var(--pt)); background: var(--wx-bg); color: #000; font-size: calc(17 * var(--pt)); font-weight: 600; font-variant-numeric: tabular-nums; }
.v3-phone__island { position: absolute; top: calc(11 * var(--pt)); left: 50%; width: calc(125 * var(--pt)); height: calc(37 * var(--pt)); border-radius: 999px; background: #000; transform: translateX(-50%); }
.v3-phone__sys { display: inline-flex; align-items: center; gap: calc(6 * var(--pt)); }
.v3-phone__sys svg { height: calc(11 * var(--pt)); fill: currentColor; }
.v3-phone__sys svg + svg { height: calc(12.5 * var(--pt)); }

/* Nav bar */
body.v3.home-page .hp-stage .v3-phone .hp-chat__bar { display: grid; flex: none; grid-template-columns: calc(44 * var(--pt)) minmax(0, 1fr) calc(44 * var(--pt)); align-items: center; height: calc(44 * var(--pt)); padding: 0 calc(12 * var(--pt)); border-bottom: .5px solid rgba(0, 0, 0, .1); background: var(--wx-bg); }
.v3-wx-back { display: inline-flex; padding-left: calc(4 * var(--pt)); color: #000; }
.v3-wx-back svg { width: calc(11 * var(--pt)); height: calc(20 * var(--pt)); }
body.v3.home-page .hp-stage .v3-phone .hp-chat__title { display: block; min-width: 0; text-align: center; }
body.v3.home-page .hp-stage .v3-phone .hp-chat__title strong { display: block; overflow: hidden; color: #000; font-size: calc(17 * var(--pt)); font-weight: 600; text-overflow: ellipsis; white-space: nowrap; }
body.v3.home-page .hp-stage .v3-phone .hp-chat__more { justify-self: end; gap: calc(3.5 * var(--pt)); padding: 0 calc(4 * var(--pt)) 0 0; }
body.v3.home-page .hp-stage .v3-phone .hp-chat__more i { width: calc(4.5 * var(--pt)); height: calc(4.5 * var(--pt)); background: #000; }

/* Thread */
body.v3.home-page .hp-stage .v3-phone .hp-chat__body { display: flex; flex: 1 1 0; flex-direction: column; gap: calc(16 * var(--pt)); min-height: 0; overflow: hidden; padding: calc(14 * var(--pt)) calc(12 * var(--pt)) calc(16 * var(--pt)); background: var(--wx-bg); scroll-behavior: smooth; }
.v3-wx-time { margin: 0 0 calc(-2 * var(--pt)); align-self: center; color: #999; font-size: calc(13 * var(--pt)); line-height: 1.4; }
/* Unplayed messages take no room, so the thread grows from the top like a real
   chat; studio-home.js keeps the newest message in view. Scoped to is-animated:
   without the script the shared fallback still reveals everything. */
body.v3.home-page .hp-stage.is-animated .v3-phone .hp-chat__body [data-at]:not(.is-on) { display: none; }
body.v3.home-page .hp-stage.is-animated .v3-phone .hp-chat__body [data-at].is-on { animation: v3-msg-in .3s ease both; }
@keyframes v3-msg-in { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
body.v3.home-page .hp-stage .v3-phone .hp-reply { display: block; }

/* Bubbles. 104pt = the two avatar columns (12 + 40 + 12 each side... the edge
   margin is the body padding, so 40 + 12 per side). */
body.v3.home-page .hp-stage .v3-phone :is(.hp-msg, .hp-dots, .hp-product) {
  position: relative; box-sizing: border-box;
  max-width: calc(100% - 104 * var(--pt));
  margin: 0; border-radius: calc(4 * var(--pt)); box-shadow: none;
}
body.v3.home-page .hp-stage .v3-phone .hp-msg {
  min-height: calc(40 * var(--pt));
  padding: calc(8 * var(--pt)) calc(12 * var(--pt));
  color: var(--wx-ink); font-size: calc(17 * var(--pt)); line-height: calc(24 * var(--pt)); letter-spacing: 0;
  word-break: normal; line-break: strict; overflow-wrap: anywhere; text-wrap: wrap;
}
/* WeChat has no rich text: emphasis in the script reads as plain text. */
body.v3.home-page .hp-stage .v3-phone .hp-msg b { color: inherit; font-weight: inherit; }
body.v3.home-page .hp-stage .v3-phone :is(.hp-msg--ai, .hp-dots, .hp-product) { align-self: flex-start; margin-left: calc(52 * var(--pt)); background: #fff; }
body.v3.home-page .hp-stage .v3-phone .hp-msg--user { align-self: flex-end; margin-right: calc(52 * var(--pt)); background: var(--wx-green); }
/* Typing bubble: dots and reply text are never shown together, so it sits in flow. */
body.v3.home-page .hp-stage .v3-phone .hp-dots { position: relative; top: auto; left: auto; display: inline-flex; align-items: center; gap: calc(5 * var(--pt)); width: fit-content; height: calc(40 * var(--pt)); padding: 0 calc(14 * var(--pt)); }
body.v3.home-page .hp-stage .v3-phone .hp-dots i { width: calc(6 * var(--pt)); height: calc(6 * var(--pt)); background: #b2b2b2; }
/* Avatars: 40pt, 4pt corners, top-aligned with the bubble. */
body.v3.home-page .hp-stage .v3-phone :is(.hp-msg, .hp-dots, .hp-product)::before { content: ""; position: absolute; top: 0; width: calc(40 * var(--pt)); height: calc(40 * var(--pt)); border-radius: calc(4 * var(--pt)); }
body.v3.home-page .hp-stage .v3-phone :is(.hp-msg--ai, .hp-dots, .hp-product)::before { left: calc(-52 * var(--pt)); background: #fff url("/login/assets/company-logo.png") center / 76% no-repeat; }
/* Customer avatar: drop a square image at /login/assets/avatar-customer.jpg.
   Until that file exists the generic silhouette underneath shows instead. */
body.v3.home-page .hp-stage .v3-phone .hp-msg--user::before { right: calc(-52 * var(--pt)); background: url("/login/assets/avatar-customer.jpg") center / cover no-repeat, url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 40'%3E%3Ccircle cx='20' cy='15' r='7' fill='%23fff'/%3E%3Cpath d='M6 38c1.5-8 7-12 14-12s12.5 4 14 12' fill='%23fff'/%3E%3C/svg%3E") center / 100% no-repeat, #b7c3cf; }

/* Product card: a WeChat link card, full bubble width.
 *   name (2 lines)              [img]
 *   ¥239  库存128               [img]
 *   420g · IPX4防泼水 · P-10086
 *   ──────────
 *   查看商品
 */
body.v3.home-page .hp-stage .v3-phone .hp-product {
  display: grid; align-items: start;
  width: calc(100% - 104 * var(--pt));
  grid-template-columns: minmax(0, 1fr) calc(52 * var(--pt));
  grid-template-areas: "name img" "price img" "spec spec" "cta cta";
  gap: calc(4 * var(--pt)) calc(10 * var(--pt));
  padding: calc(12 * var(--pt)) calc(12 * var(--pt)) calc(10 * var(--pt));
  border: 0;
  word-break: normal; overflow-wrap: anywhere;
}
body.v3.home-page .hp-stage .v3-phone :is(.hp-product__info, .hp-product__meta) { display: contents; }
body.v3.home-page .hp-stage .v3-phone .hp-product__img { grid-area: img; width: calc(52 * var(--pt)); height: calc(52 * var(--pt)); border-radius: calc(2 * var(--pt)); background: #f5f5f5; }
body.v3.home-page .hp-stage .v3-phone .hp-product__info strong { grid-area: name; display: -webkit-box; overflow: hidden; color: var(--wx-ink); font-size: calc(16 * var(--pt)); font-weight: 400; line-height: calc(22 * var(--pt)); white-space: normal; text-overflow: clip; -webkit-box-orient: vertical; -webkit-line-clamp: 2; }
body.v3.home-page .hp-stage .v3-phone .hp-product__meta b { grid-area: price; align-self: end; color: #fa5151; font-family: inherit; font-size: calc(16 * var(--pt)); font-weight: 500; }
body.v3.home-page .hp-stage .v3-phone .hp-product__meta small { grid-area: price; align-self: end; justify-self: end; color: #999; font-size: calc(13 * var(--pt)); white-space: nowrap; }
body.v3.home-page .hp-stage .v3-phone .hp-product__spec { grid-area: spec; margin-top: calc(4 * var(--pt)); overflow: hidden; color: #999; font-size: calc(13 * var(--pt)); text-overflow: ellipsis; white-space: nowrap; }
body.v3.home-page .hp-stage .v3-phone .hp-product__cta { grid-area: cta; margin-top: calc(6 * var(--pt)); padding: calc(8 * var(--pt)) 0 0; border-top: .5px solid rgba(0, 0, 0, .1); border-radius: 0; color: #576b95; background: none; font-size: calc(13 * var(--pt)); font-weight: 400; text-align: left; }

/* Input bar */
body.v3.home-page .hp-stage .v3-phone .hp-chat__input { display: flex; flex: none; align-items: flex-end; gap: calc(10 * var(--pt)); margin: 0; padding: calc(8 * var(--pt)) calc(10 * var(--pt)); border: 0; border-top: .5px solid rgba(0, 0, 0, .08); border-radius: 0; color: var(--wx-ink); background: var(--wx-bar); box-shadow: none; font-size: calc(17 * var(--pt)); }
body.v3.home-page .hp-stage .v3-phone .hp-chat__input.has-text { border-color: rgba(0, 0, 0, .08); background: var(--wx-bar); box-shadow: none; }
body.v3.home-page .hp-stage .v3-phone [data-hp-typing] { flex: 1; min-width: 0; min-height: calc(40 * var(--pt)); padding: calc(8 * var(--pt)) calc(10 * var(--pt)); overflow: visible; border-radius: calc(4 * var(--pt)); color: var(--wx-ink); background: #fff; font-size: calc(17 * var(--pt)); line-height: calc(24 * var(--pt)); text-overflow: clip; white-space: normal; word-break: normal; overflow-wrap: anywhere; }
body.v3.home-page .hp-stage .v3-phone [data-hp-typing].is-typing::after { width: 1.5px; height: calc(20 * var(--pt)); background: #07c160; }
.v3-wx-ico { flex: none; width: calc(30 * var(--pt)); height: calc(30 * var(--pt)); margin-bottom: calc(5 * var(--pt)); border: calc(1.6 * var(--pt)) solid #191919; border-radius: 50%; background-position: center; background-repeat: no-repeat; background-size: 62%; }
.v3-wx-ico--voice { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none' stroke='%23191919' stroke-width='1.8' stroke-linecap='round'%3E%3Cpath d='M7 6.5a5 5 0 0 1 0 7M11 4a8.5 8.5 0 0 1 0 12'/%3E%3C/svg%3E"); }
.v3-wx-ico--emoji { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none' stroke='%23191919' stroke-width='1.8' stroke-linecap='round'%3E%3Cpath d='M6.5 12.2a4.5 4.5 0 0 0 7 0'/%3E%3Ccircle cx='7' cy='8' r='.6' fill='%23191919'/%3E%3Ccircle cx='13' cy='8' r='.6' fill='%23191919'/%3E%3C/svg%3E"); }
/* "+" until there is text, then WeChat's green 发送 */
body.v3.home-page .hp-stage .v3-phone .hp-chat__send { display: grid; flex: none; place-items: center; width: calc(30 * var(--pt)); height: calc(30 * var(--pt)); margin-bottom: calc(5 * var(--pt)); padding: 0; border: calc(1.6 * var(--pt)) solid #191919; border-radius: 50%; color: #191919; background: transparent; }
body.v3.home-page .hp-stage .v3-phone .hp-chat__send svg { display: none; }
body.v3.home-page .hp-stage .v3-phone .hp-chat__send::after { content: "+"; font-size: calc(24 * var(--pt)); font-weight: 300; line-height: 1; transform: translateY(calc(-1 * var(--pt))); }
body.v3.home-page .hp-stage .v3-phone .hp-chat__input.has-text .hp-chat__send { width: auto; height: calc(32 * var(--pt)); margin-bottom: calc(4 * var(--pt)); padding: 0 calc(12 * var(--pt)); border: 0; border-radius: calc(4 * var(--pt)); color: #fff; background: #07c160; }
body.v3.home-page .hp-stage .v3-phone .hp-chat__input.has-text .hp-chat__send::after { content: "发送"; font-size: calc(15 * var(--pt)); font-weight: 500; transform: none; }
body.v3.home-page .hp-stage .v3-phone .hp-chat__send.is-press { transform: scale(.94); }
/* Home indicator on the input bar's grey: 134 x 5pt, 8pt off the bottom. */
body.v3.home-page .hp-stage .v3-phone .v3-phone__home { display: block; flex: none; width: 100%; height: calc(28 * var(--pt)); margin: 0; border-radius: 0; background: var(--wx-bar) linear-gradient(#000, #000) center calc(100% - 8 * var(--pt)) / calc(134 * var(--pt)) calc(5 * var(--pt)) no-repeat; }

/* Phone size per viewport height, so phone + number strip fit the first screen.
   Inside, everything scales with the phone (points), so only the size changes. */
@media (min-width: 1081px) and (max-height: 920px) {
  body.v3.home-page .hp-stage { padding-block: 10px; }
  /* The phone needs the height; the hero's own padding and the caption give it. */
  body.v3 .hp-hero { padding-block: 18px 14px; }
  body.v3 .hp-demo figcaption { margin-top: .55em; }
}
@media (min-width: 1081px) and (max-height: 840px) {
  body.v3.home-page .hp-stage { padding-block: 6px; }
  body.v3 .hp-hero { padding-block: 12px 8px; }
  body.v3 .hp-demo figcaption { margin-top: .4em; line-height: 1.5; }
  body.v3.home-page .hp-stage .hp-flow__head { height: 3em; margin-bottom: 1em; }
}

/* ---------- Flow column: a console card ----------
 * The flow list used only the top half of the stage. It becomes a white card
 * the height of the phone: steps at the top, each with its elapsed time once
 * done, and at the bottom what Studio hands back to the tenant's system — the
 * part a buyer actually integrates against. The payload appears with the
 * product card in the chat (data-at 6) and holds its space meanwhile, so
 * nothing above it moves.
 */
body.v3.home-page .hp-stage .hp-flow {
  display: flex; flex-direction: column; align-self: stretch;
  margin-block: clamp(6px, .8vw, 14px);
  padding: 0 1.4em 1.3em;
  border: 1px solid var(--v3-jade-line); border-radius: 16px;
  background: #fff;
  box-shadow: 0 1px 2px rgba(30, 60, 45, .04), 0 18px 36px -28px rgba(30, 60, 45, .28);
}
body.v3.home-page .hp-stage .hp-flow__head { flex: none; height: 3.6em; margin: 0 0 1.3em; }
body.v3.home-page .hp-stage .hp-flow__list { --hp-flow-gap: 1.25em; }
/* Elapsed time: mono, right-aligned before the check, only once the step is done. */
.v3-ms { margin-left: auto; color: var(--hp-faint); font-family: var(--hp-mono); font-size: .86em; font-style: normal; font-weight: 400; font-variant-numeric: tabular-nums; }
body.v3.home-page .hp-stage .hp-flow__step:not(.is-on) .v3-ms { visibility: hidden; }
body.v3.home-page .hp-stage .hp-flow__step strong { gap: .6em; }

/* Returned payload */
.v3-out { margin-top: auto; padding-top: 1.2em; }
.v3-out__head { display: flex; justify-content: space-between; gap: 1em; margin: 0 0 .6em; color: var(--hp-label); font-size: max(11px, .8em); letter-spacing: .1em; }
.v3-out__head span + span { color: var(--hp-faint); font-family: var(--hp-mono); letter-spacing: 0; white-space: nowrap; }
.v3-out__code { margin: 0; padding: .85em 1em; overflow: hidden; border-radius: 10px; color: #4e5850; background: #f4f8f5; font-family: var(--hp-mono); font-size: max(11.5px, .86em); line-height: 1.65; white-space: pre; }
.v3-out__code b { color: var(--v3-jade); font-weight: 400; }
.v3-out__code i { color: #8a5a1f; font-style: normal; }
.v3-out__code u { color: #2c302d; text-decoration: none; }
@media (max-width: 640px) {
  body.v3.home-page .hp-stage .hp-flow { margin-block: 0; }
}
/* Short laptops: the console card must not outgrow the phone. */
@media (min-width: 1081px) and (max-height: 840px) {
  body.v3.home-page .hp-stage .hp-flow { margin-block: 4px; padding: 0 1.2em .9em; }
  body.v3.home-page .hp-stage .hp-flow__head { height: 3em; margin-bottom: .9em; }
  body.v3.home-page .hp-stage .hp-flow__list { --hp-flow-gap: .85em; }
  body.v3.home-page .hp-stage .hp-hits { gap: .3em; }
  .v3-out { padding-top: .7em; }
  .v3-out__code { padding: .6em .85em; line-height: 1.5; }
}

/* ---------- Phone height follows the viewport ----------
 * Fixed sizes per breakpoint left short browser windows (toolbars, docked
 * windows) with the number strip cut off and the phone oddly small or large.
 * The phone takes what the first screen has left after the header (76px), hero
 * padding, stage padding, caption and number strip (~270px together), between a
 * readable minimum and the design size. Everything inside scales in points.
 */
@media (min-width: 1081px) {
  /* Below ~790px of viewport the strip gives way rather than the phone: under
     510px the chat text drops below ~10px. */
  body.v3.home-page .hp-stage { --v3-phone-h: clamp(510px, calc(100svh - 270px), 45em); }
}

/* ---------- Flow column: a macOS window ----------
 * Next to the iPhone the console has to belong to the same family, so it is
 * drawn as a Mac app window: traffic lights and a centred title in the title
 * bar, #f5f5f7 window background, the steps as an inset grouped list (white
 * group, 10px corners, inset hairlines) with SF-Symbols-style coloured icon
 * tiles, Apple system colours, system font, SF Mono for numbers and the
 * payload. Same height as the phone, top and bottom aligned.
 */
body.v3.home-page .hp-stage .hp-flow {
  --mac-ink: #1d1d1f; --mac-sub: #6e6e73; --mac-line: rgba(60, 60, 67, .14); --mac-bg: #f5f5f7;
  --mac-blue: #007aff; --mac-green: #34c759; --mac-purple: #af52de; --mac-orange: #ff9500;
  display: flex; flex-direction: column; align-self: stretch;
  margin-block: 0; padding: 0 1.15em 1.15em;
  overflow: hidden;
  border: 0; border-radius: 12px;
  color: var(--mac-ink); background: var(--mac-bg);
  box-shadow: 0 0 0 .5px rgba(0, 0, 0, .16), 0 1px 1px rgba(0, 0, 0, .04), 0 22px 44px -18px rgba(20, 30, 25, .32);
  font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text", "PingFang SC", "Helvetica Neue", sans-serif;
  letter-spacing: 0;
}
/* Title bar */
.v3-mac-bar { position: relative; display: flex; flex: none; align-items: center; gap: 8px; height: 2.9em; margin: 0 -1.15em; padding: 0 1em; border-bottom: .5px solid var(--mac-line); background: #ececee; }
.v3-mac-bar i { width: 12px; height: 12px; border-radius: 50%; background: #ff5f57; box-shadow: inset 0 0 0 .5px rgba(0, 0, 0, .12); }
.v3-mac-bar i:nth-child(2) { background: #febc2e; }
.v3-mac-bar i:nth-child(3) { background: #28c840; }
.v3-mac-bar span { position: absolute; left: 50%; color: #4d4d4f; font-size: .92em; font-weight: 600; transform: translateX(-50%); white-space: nowrap; }
/* Section header + status */
body.v3.home-page .hp-stage .hp-flow__head { flex: none; height: auto; margin: 1em .2em .55em; padding: 0; border: 0; color: var(--mac-sub); font-size: .82em; font-weight: 500; letter-spacing: 0; }
body.v3.home-page .hp-stage .hp-flow__status { padding: .2em .65em; color: var(--mac-blue); background: rgba(0, 122, 255, .1); font-size: 1em; font-weight: 500; }
body.v3.home-page .hp-stage .hp-flow__status::before { background: var(--mac-blue); }
body.v3.home-page .hp-stage .hp-flow__status[data-state="run"] { color: var(--mac-blue); background: rgba(0, 122, 255, .1); }
body.v3.home-page .hp-stage .hp-flow__status[data-state="run"]::before { background: var(--mac-blue); }
body.v3.home-page .hp-stage .hp-flow__status[data-state="done"] { color: #248a3d; background: rgba(52, 199, 89, .14); }
body.v3.home-page .hp-stage .hp-flow__status[data-state="done"]::before { border-color: #248a3d; }
body.v3.home-page .hp-stage .hp-flow__status[data-state="idle"] { color: var(--mac-sub); background: rgba(118, 118, 128, .12); }
body.v3.home-page .hp-stage .hp-flow__idle { margin: 0 .2em; color: var(--mac-sub); font-size: .86em; }
body.v3.home-page .hp-stage .hp-flow__idle i { background: var(--mac-blue); }

/* Inset grouped list */
body.v3.home-page .hp-stage .hp-flow__list { gap: 0; overflow: hidden; border-radius: 10px; background: #fff; box-shadow: 0 0 0 .5px rgba(0, 0, 0, .06); }
body.v3.home-page .hp-stage .hp-flow__list:not(:has(.is-on, .is-run)) { box-shadow: none; }
body.v3.home-page .hp-stage .hp-flow__list::before,
body.v3.home-page .hp-stage.is-animated .hp-flow__step::before { display: none; }
body.v3.home-page .hp-stage .hp-flow__step { grid-template-columns: 2em minmax(0, 1fr); gap: .8em; padding: .8em .9em .85em; }
/* Inset separator: starts at the text, like iOS/macOS grouped lists. */
body.v3.home-page .hp-stage .hp-flow__step + .hp-flow__step::after { content: ""; position: absolute; top: 0; right: 0; left: 3.7em; height: .5px; background: var(--mac-line); }
/* Icon tiles: rounded squares in system colours, white glyph. */
body.v3.home-page .hp-stage .hp-flow__icon,
body.v3.home-page .hp-stage .hp-flow__step.is-on .hp-flow__icon,
body.v3.home-page .hp-stage .hp-flow__step.is-run .hp-flow__icon { width: 2em; height: 2em; border: 0; border-radius: .55em; color: #fff; background: var(--tile, var(--mac-blue)); }
body.v3.home-page .hp-stage .hp-flow__icon .hp-ico { font-size: 1.05em; stroke-width: 1.9; }
body.v3.home-page .hp-stage .hp-flow__step:nth-child(1) { --tile: var(--mac-purple); }
body.v3.home-page .hp-stage .hp-flow__step:nth-child(2) { --tile: var(--mac-blue); }
body.v3.home-page .hp-stage .hp-flow__step:nth-child(3) { --tile: var(--mac-orange); }
body.v3.home-page .hp-stage .hp-flow__step:nth-child(4) { --tile: var(--mac-green); }
body.v3.home-page .hp-stage .hp-flow__step.is-run .hp-flow__icon { animation: v3-tile-pulse 1.2s ease-in-out infinite; }
@keyframes v3-tile-pulse { 50% { opacity: .55; } }
/* Text */
body.v3.home-page .hp-stage .hp-flow__step strong { padding-top: .2em; color: var(--mac-ink); font-size: .95em; font-weight: 600; }
body.v3.home-page .hp-stage .hp-flow__step.is-run strong::after { color: var(--mac-sub); font-weight: 400; }
body.v3.home-page .hp-stage .hp-flow__step.is-on strong::after { border-color: var(--mac-green); }
body.v3.home-page .hp-stage .hp-flow__step small { color: var(--mac-sub); font-size: .82em; }
.v3-ms { color: var(--mac-sub); font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: .8em; }
body.v3.home-page .hp-stage .hp-flow__chips i { color: #3c3c43; background: rgba(118, 118, 128, .12); font-size: .8em; }
/* Retrieval scores: iOS progress bars in system blue */
body.v3.home-page .hp-stage .hp-hits { gap: .45em; }
body.v3.home-page .hp-stage .hp-hits li { font-size: .82em; }
body.v3.home-page .hp-stage .hp-hits span { color: #3c3c43; }
body.v3.home-page .hp-stage .hp-hits b,
body.v3.home-page .hp-stage .hp-hits li:nth-child(1) b { color: var(--mac-ink); font-family: ui-monospace, "SF Mono", Menlo, monospace; font-weight: 500; }
body.v3.home-page .hp-stage .hp-hits li:nth-child(1) b { color: var(--mac-blue); }
body.v3.home-page .hp-stage .hp-hits i { height: 4px; border-radius: 2px; background: rgba(118, 118, 128, .14); }
body.v3.home-page .hp-stage .hp-hits li:nth-child(1) i::before { background: var(--mac-blue); }
body.v3.home-page .hp-stage .hp-hits li:nth-child(2) i::before { background: #7ab8ff; }
body.v3.home-page .hp-stage .hp-hits li:nth-child(3) i::before { background: #c7c7cc; }

/* Payload: section header, then an Xcode-light code block */
.v3-out { padding-top: 1em; }
.v3-out__head { margin: 0 .2em .55em; color: var(--mac-sub); font-size: .82em; font-weight: 500; letter-spacing: 0; }
.v3-out__head span + span { color: var(--mac-sub); font-family: ui-monospace, "SF Mono", Menlo, monospace; font-weight: 400; }
.v3-out__code { padding: .8em .95em; border-radius: 10px; color: var(--mac-ink); background: #fff; box-shadow: 0 0 0 .5px rgba(0, 0, 0, .06); font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: .82em; line-height: 1.6; }
.v3-out__code b { color: #0b4f79; }
.v3-out__code i { color: #c41a16; }
.v3-out__code u { color: #1c00cf; }

/* Short windows: the Mac window must not outgrow the phone. */
@media (min-width: 1081px) and (max-height: 840px) {
  body.v3.home-page .hp-stage .hp-flow { padding-bottom: .8em; }
  .v3-mac-bar { height: 2.5em; }
  body.v3.home-page .hp-stage .hp-flow__head { margin: .6em .2em .45em; }
  body.v3.home-page .hp-stage .hp-flow__step { padding-block: .5em .55em; }
  body.v3.home-page .hp-stage .hp-hits { gap: .25em; margin-top: .3em; }
  body.v3.home-page .hp-stage .hp-flow__chips { margin-top: .3em; }
  .v3-out { padding-top: .55em; }
  .v3-out__head { margin-bottom: .4em; }
  .v3-out__code { padding: .5em .85em; line-height: 1.45; }
}

/* ---------- Hero copy: four things and room around them ----------
 * Premium here means fewer elements, not more decoration: a quiet eyebrow with
 * a live dot, the headline, one line of lead, two buttons. No boxes, no colour
 * tiles, no extra links — the demo on the right carries the detail. The
 * sales route stays in the closing section ("没有开发团队？联系销售对接").
 * Spacing grows from small to large going down, so each step has air.
 */
body.v3 .hp-hero .v3-live { gap: .7em; color: var(--hp-label); font-size: 12px; letter-spacing: .2em; }
.v3-live i { position: relative; width: 6px; height: 6px; border-radius: 50%; background: var(--v3-jade); }
.v3-live i::after { content: ""; position: absolute; inset: -4px; border-radius: 50%; background: var(--v3-jade); opacity: 0; }
body.v3.home-page:has(.hp-flow__status[data-state="run"]) .v3-live i::after { animation: v3-live-ping 1.4s ease-out infinite; }
@keyframes v3-live-ping { 0% { opacity: .35; transform: scale(.5); } 100% { opacity: 0; transform: scale(1.7); } }
@media (prefers-reduced-motion: reduce) { body.v3.home-page:has(.hp-flow__status[data-state="run"]) .v3-live i::after { animation: none; } }

body.v3 .hp-hero h1 { margin: clamp(22px, 2vw, 34px) 0 clamp(22px, 2vw, 32px); line-height: 1.16; }
body.v3 .hp-hero__lead { max-width: 22em; color: #59635c; line-height: 1.95; }
body.v3 .hp-hero__actions { gap: 14px; margin-top: clamp(36px, 3.4vw, 56px); }
@media (min-width: 1081px) and (max-height: 840px) {
  body.v3 .hp-hero h1 { margin-block: 18px 18px; }
  body.v3 .hp-hero__actions { margin-top: 30px; }
}

/* ---------- Hero copy: set like an Apple product page ----------
 * The devices on the right are Apple; the copy beside them was set in the
 * site's editorial serif and read as a different brand. The copy now uses the
 * same system typography Apple uses for product pages: large semibold display
 * type, a grey lead, a pill button and a text link with a chevron.
 * The second line takes the Apple Intelligence gradient — the same palette as
 * the glow on the phone — so the headline and the demo say one thing. This and
 * the glow are the only gradients on the site (an explicit exception).
 */
body.v3 .hp-hero__copy { --apple: -apple-system, BlinkMacSystemFont, "SF Pro Display", "PingFang SC", "Helvetica Neue", "Microsoft YaHei", sans-serif; }
body.v3 .hp-hero .v3-live { color: #1d1d1f; font-family: var(--hp-sans); font-size: clamp(13px, .95vw, 15px); font-weight: 600; letter-spacing: .02em; }
body.v3 .hp-hero h1 {
  margin: clamp(14px, 1.3vw, 22px) 0 clamp(18px, 1.6vw, 28px);
  color: var(--hp-ink);
  font-family: var(--hp-serif); font-size: clamp(44px, 4.3vw, 70px); font-weight: 500; letter-spacing: 0; line-height: 1.08;
}
body.v3 .hp-hero h1 .hp-accent {
  width: fit-content;
  padding-bottom: .04em;
  color: transparent;
  background: linear-gradient(90deg, #2f7bff 0%, #8e5cf7 40%, #e2559c 72%, #ff8a3d 100%);
  -webkit-background-clip: text; background-clip: text;
}
body.v3 .hp-hero__lead { max-width: 21em; color: #6e6e73; font-family: var(--hp-sans); font-size: clamp(17px, 1.3vw, 21px); font-weight: 400; line-height: 1.55; }
body.v3 .hp-hero__actions { align-items: center; gap: clamp(22px, 2vw, 32px); margin-top: clamp(30px, 2.8vw, 46px); }
body.v3 .hp-hero .hp-btn { font-family: var(--hp-sans); }
body.v3 .hp-hero .hp-btn--primary { min-height: 48px; padding: 0 clamp(22px, 1.7vw, 28px); border-radius: 999px; font-size: clamp(15px, 1vw, 17px); font-weight: 500; }
@media (min-width: 1081px) and (max-height: 840px) {
  body.v3 .hp-hero h1 { margin-block: 12px 16px; }
  body.v3 .hp-hero__actions { margin-top: 26px; }
}
@media (max-width: 640px) {
  body.v3 .hp-hero__actions { flex-direction: row; justify-content: flex-start; }
  body.v3 .hp-hero__actions .hp-btn--primary { flex: none; }
  body.v3 .hp-hero__actions .hp-btn--secondary { flex: none; }
}

/* ---------- Lead and actions, Apple product-page rhythm ----------
 * Two wrapped grey lines under a two-line headline read as a paragraph and
 * flattened the hierarchy. The lead is now one short line, set as a subhead
 * (dark grey, medium, a size that clearly sits below the headline); "接回你的
 * 系统" is what the Mac window on the right already shows. The actions follow
 * Apple's pattern: one solid pill for the main action (no arrow icon, which
 * read as generic), one text link with a chevron for the secondary one.
 */
body.v3 .hp-hero__lead { max-width: none; color: #424245; font-size: clamp(17px, 1.25vw, 20px); font-weight: 400; line-height: 1.5; white-space: nowrap; }
body.v3 .hp-hero__actions { gap: clamp(26px, 2.2vw, 36px); margin-top: clamp(28px, 2.5vw, 40px); }
body.v3 .hp-hero .hp-btn--primary { min-height: 46px; padding: 0 clamp(24px, 1.8vw, 30px); font-size: clamp(15px, 1.05vw, 17px); font-weight: 500; letter-spacing: .01em; }
@media (max-width: 640px) {
  body.v3 .hp-hero__lead { white-space: normal; font-size: 18px; }
}

/* ---------- Hero actions ----------
 * Two buttons, not a button plus a caption: the link gets the same pill shape,
 * height and corner as the primary one, and the text arrow becomes the same
 * chevron the rest of the site uses, so the green is no longer the only shape
 * in the pair. Hover only changes colour (AGENTS.md).
 */
body.v3 .hp-hero .hp-btn--secondary {
  min-height: 46px; padding: 0 clamp(24px, 1.8vw, 30px); border-radius: 999px;
  border-color: #cfdcd5; color: #3f5a4f; background: #fff;
  font-size: clamp(15px, 1.05vw, 17px); font-weight: 500; line-height: 1; letter-spacing: .01em;
}
body.v3 .hp-hero .hp-btn--secondary .hp-ico { width: 1em; height: 1em; }
@media (hover: hover) and (pointer: fine) {
  body.v3 .hp-hero .hp-btn--secondary:hover { color: var(--hp-jade-deep); border-color: #bcd5c9; background: #f8fbf9; }
  body.v3 .hp-hero .hp-btn--secondary:hover .hp-ico { transform: translateX(2px); }
}

/* ---------- First screen ----------
 * The site header is left exactly as on every other public page (width,
 * type, button shape). Strip type is system type; the mint box behind the
 * devices is dropped so the devices sit on the page like the copy does.
 */
body.v3.home-page { --v3-apple: -apple-system, BlinkMacSystemFont, "SF Pro Text", "PingFang SC", "Helvetica Neue", "Microsoft YaHei", sans-serif; }

/* Devices on the page, no panel */
body.v3.home-page .hp-stage { overflow: visible; padding: 0; border: 0; border-radius: 0; background: none; box-shadow: none; }

/* Number strip in the same type */
body.v3.home-page .hp-numbers :is(dt, dd) { font-family: var(--hp-serif); }
body.v3.home-page .hp-numbers dt { color: #1d1d1f; font-size: 15px; font-weight: 600; }
/* Numbers match the pricing page: Lemon Latin 400, tight tracking. The ¥ is not
   in Lemon Latin, so it falls back to a serif; set it in the sans instead. */
body.v3.home-page .hp-numbers dt b { color: var(--hp-ink); font-family: var(--hp-num); font-weight: 400; letter-spacing: -.035em; font-variant-numeric: tabular-nums; }
body.v3.home-page .hp-numbers dt b { font-size: clamp(34px, 2.6vw, 44px); }
body.v3.home-page .hp-numbers .hp-num-cur { font-family: var(--hp-sans); }
body.v3.home-page .hp-numbers dd { color: #6e6e73; font-size: 14px; }

/* ---------- Scenes: the example chat on an iPad ----------
 * The hero shows the shopper's phone; the scenes show the same chat as an app
 * on an iPad. Landscape 4:3 beside the tabs, portrait when stacked on phones.
 * The three scene panels swap inside one screen, so tabs never move the frame.
 */
body.v3.home-page .v3-pad {
  --pad-bezel: clamp(10px, 1.6vw, 16px);
  position: relative;
  padding: var(--pad-bezel);
  border-radius: calc(var(--pad-bezel) + clamp(12px, 1.6vw, 18px));
  background: #1e2321;
  box-shadow: 0 0 0 1px #3a403d, 0 36px 64px -36px rgba(20, 40, 30, .45), 0 2px 6px rgba(20, 40, 30, .08);
}
/* Front camera, centred on the long top bezel. */
body.v3.home-page .v3-pad::before { content: ""; position: absolute; top: calc(var(--pad-bezel) / 2 - 3px); left: 50%; width: 6px; height: 6px; border-radius: 50%; background: #0c0f0e; box-shadow: inset 0 0 0 1.5px #2b322f; transform: translateX(-50%); }
/* No overflow clipping here: with it, aspect-ratio becomes a fixed height and
   a long reply is cut off. Corners are rounded on the status bar and the app. */
body.v3.home-page .v3-pad__screen { --pad-r: clamp(12px, 1.6vw, 18px); display: flex; flex-direction: column; aspect-ratio: 4 / 3; border-radius: var(--pad-r); }
body.v3.home-page .v3-pad__status { border-radius: var(--pad-r) var(--pad-r) 0 0; display: flex; flex: none; align-items: center; justify-content: space-between; height: 26px; padding: 0 18px; color: #1d1d1f; font-size: 11px; font-weight: 600; font-variant-numeric: tabular-nums; }
body.v3.home-page .v3-pad__sys { display: inline-flex; align-items: center; gap: 5px; }
body.v3.home-page .v3-pad__sys svg { height: 10px; fill: currentColor; }
body.v3.home-page .v3-pad__sys svg + svg { height: 11px; }
/* The scene is the app filling the screen: no card border, radius or shadow. */
body.v3.home-page .v3-pad .v2-scene:not([hidden]) { display: flex; flex: 1 1 0; flex-direction: column; min-height: 0; border: 0; border-radius: 0 0 var(--pad-r) var(--pad-r); box-shadow: none; }
body.v3.home-page .v3-pad .v2-scene:focus-visible { outline-offset: -3px; }
body.v3.home-page .v3-pad .v2-scene .hp-chat__bar { flex: none; }
/* 对话区占用剩余空间，内容滚动，不把输入栏挤出屏幕。 */
body.v3.home-page .v3-pad .v2-scene .hp-chat__body { flex: 1 1 0; height: auto; }
body.v3.home-page .v3-pad .v2-scene .hp-chat__input { flex: none; }
body.v3.home-page .v3-pad + .v2-scenes__note { margin-top: 18px; }
@media (max-width: 640px) {
  body.v3.home-page .v3-pad { --pad-bezel: 10px; width: min(100%, 360px); margin-inline: auto; }
  body.v3.home-page .v3-pad__screen { aspect-ratio: 3 / 4; }
  body.v3.home-page .v3-pad__status { padding: 0 14px; }
}

/* ---------- iPad screen: WeChat ----------
 * Same WeChat look as the hero phone (grey thread, 4pt-corner bubbles with
 * square avatars, centred nav title, voice / emoji / plus input bar), in iPad
 * points. Landscape: the 760pt-wide conversation column of iPad WeChat;
 * stacked portrait on phones: 390pt like the phone.
 */
body.v3.home-page .v3-pad__screen {
  --wx-bg: #ededed; --wx-bar: #f7f7f7; --wx-green: #95ec69; --wx-ink: #191919;
  container-type: inline-size;
  color: var(--wx-ink);
  background: var(--wx-bg);
  font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Helvetica Neue", "Microsoft YaHei", sans-serif;
  letter-spacing: 0;
}
body.v3.home-page .v3-pad__screen > * { --pt: calc(100cqw / 760); }
@media (max-width: 640px) { body.v3.home-page .v3-pad__screen > * { --pt: calc(100cqw / 390); } }
body.v3.home-page .v3-pad__status { height: calc(28 * var(--pt)); padding: 0 calc(20 * var(--pt)); color: #000; background: var(--wx-bg); font-size: calc(13 * var(--pt)); }
body.v3.home-page .v3-pad__sys { gap: calc(6 * var(--pt)); }
body.v3.home-page .v3-pad__sys svg { height: calc(11 * var(--pt)); }
body.v3.home-page .v3-pad__sys svg + svg { height: calc(12.5 * var(--pt)); }
body.v3.home-page .v3-pad .v2-scene:not([hidden]) { color: var(--wx-ink); background: var(--wx-bg); font-size: calc(17 * var(--pt)); }

/* Nav bar */
body.v3.home-page .v3-pad .v2-scene .hp-chat__bar { display: grid; grid-template-columns: calc(44 * var(--pt)) minmax(0, 1fr) calc(44 * var(--pt)); align-items: center; height: calc(44 * var(--pt)); padding: 0 calc(12 * var(--pt)); border-bottom: .5px solid rgba(0, 0, 0, .1); background: var(--wx-bg); }
body.v3.home-page .v3-pad .v3-wx-back svg { width: calc(11 * var(--pt)); height: calc(20 * var(--pt)); }
body.v3.home-page .v3-pad .hp-chat__title { display: block; min-width: 0; text-align: center; }
body.v3.home-page .v3-pad .hp-chat__title strong { display: block; overflow: hidden; color: #000; font-size: calc(17 * var(--pt)); font-weight: 600; text-overflow: ellipsis; white-space: nowrap; }
body.v3.home-page .v3-pad .hp-chat__more { justify-self: end; gap: calc(3.5 * var(--pt)); padding: 0 calc(4 * var(--pt)) 0 0; }
body.v3.home-page .v3-pad .hp-chat__more i { width: calc(4.5 * var(--pt)); height: calc(4.5 * var(--pt)); background: #000; }

/* Thread: everything in the avatar columns, 52pt in from each side. */
body.v3.home-page .v3-pad .v2-scene .hp-chat__body { display: flex; flex-direction: column; gap: calc(14 * var(--pt)); min-height: 0; overflow-y: auto; padding: calc(12 * var(--pt)) calc(12 * var(--pt)) calc(14 * var(--pt)); background: var(--wx-bg); }
body.v3.home-page .v3-pad .hp-chat__body > * { flex-shrink: 0; }
body.v3.home-page .v3-pad .v3-wx-time { margin: 0; align-self: center; color: #999; font-size: calc(13 * var(--pt)); line-height: 1.4; }
body.v3.home-page .v3-pad .hp-reply { position: relative; display: block; }
body.v3.home-page .v3-pad :is(.hp-msg, .v2-status) {
  position: relative; box-sizing: border-box; width: fit-content;
  max-width: calc(100% - 104 * var(--pt));
  min-height: calc(40 * var(--pt));
  margin: 0; padding: calc(8 * var(--pt)) calc(12 * var(--pt));
  border-radius: calc(4 * var(--pt)); box-shadow: none;
  color: var(--wx-ink); font-size: calc(17 * var(--pt)); line-height: calc(24 * var(--pt)); letter-spacing: 0;
  word-break: normal; line-break: strict; overflow-wrap: anywhere;
}
body.v3.home-page .v3-pad .hp-msg b { color: inherit; font-weight: inherit; }
body.v3.home-page .v3-pad :is(.hp-msg--ai, .v2-status) { align-self: flex-start; margin-left: calc(52 * var(--pt)); background: #fff; }
body.v3.home-page .v3-pad .hp-msg--user { align-self: flex-end; margin-right: calc(52 * var(--pt)); background: var(--wx-green); }
/* Thinking status: a white bubble with the dots, shown in place of the reply. */
body.v3.home-page .v3-pad .v2-status { position: absolute; top: 0; left: 0; display: inline-flex; align-items: center; gap: calc(8 * var(--pt)); color: #999; font-size: calc(15 * var(--pt)); white-space: nowrap; }
body.v3.home-page .v3-pad .v2-status__dots i { width: calc(6 * var(--pt)); height: calc(6 * var(--pt)); background: #b2b2b2; }
/* Avatars: 40pt, 4pt corners, top-aligned with the bubble. */
body.v3.home-page .v3-pad :is(.hp-msg, .v2-status)::before { content: ""; position: absolute; top: 0; width: calc(40 * var(--pt)); height: calc(40 * var(--pt)); border-radius: calc(4 * var(--pt)); }
body.v3.home-page .v3-pad :is(.hp-msg--ai, .v2-status)::before { left: calc(-52 * var(--pt)); background: #fff url("/login/assets/company-logo.png") center / 76% no-repeat; }
body.v3.home-page .v3-pad .hp-msg--user::before { right: calc(-52 * var(--pt)); background: url("/login/assets/avatar-customer.jpg") center / cover no-repeat, url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 40'%3E%3Ccircle cx='20' cy='15' r='7' fill='%23fff'/%3E%3Cpath d='M6 38c1.5-8 7-12 14-12s12.5 4 14 12' fill='%23fff'/%3E%3C/svg%3E") center / 100% no-repeat, #b7c3cf; }

/* Cards under the reply: white, 4pt corners, in the AI bubble column. */
body.v3.home-page .v3-pad :is(.hp-use__picks, .hp-use__track, .v2-doc) { box-sizing: border-box; align-self: flex-start; width: calc(100% - 104 * var(--pt)); max-width: none; margin: 0 0 0 calc(52 * var(--pt)); }
body.v3.home-page .v3-pad .hp-use__picks { gap: calc(8 * var(--pt)); font-size: calc(15 * var(--pt)); }
body.v3.home-page .v3-pad .hp-use__picks li { column-gap: calc(10 * var(--pt)); padding: calc(10 * var(--pt)); border: 0; border-radius: calc(4 * var(--pt)); background: #fff; font-size: inherit; grid-template-columns: calc(44 * var(--pt)) minmax(0, 1fr); }
body.v3.home-page .v3-pad .hp-use__picks img { width: calc(44 * var(--pt)); height: calc(44 * var(--pt)); border-radius: calc(2 * var(--pt)); background: #f5f5f5; }
body.v3.home-page .v3-pad .hp-use__picks span { color: var(--wx-ink); }
body.v3.home-page .v3-pad .hp-use__picks b { color: #fa5151; font-family: inherit; }
body.v3.home-page .v3-pad .hp-use__track { padding: calc(12 * var(--pt)); border: 0; border-radius: calc(4 * var(--pt)); background: #fff; font-size: calc(14 * var(--pt)); }
body.v3.home-page .v3-pad .hp-use__track li { padding-top: calc(18 * var(--pt)); }
body.v3.home-page .v3-pad .hp-use__track li::before { top: calc(4 * var(--pt)); background: #c8e6c9; }
body.v3.home-page .v3-pad .hp-use__track li::after { top: 0; width: calc(9 * var(--pt)); height: calc(9 * var(--pt)); border-color: #07c160; }
body.v3.home-page .v3-pad .hp-use__track li.is-done::after { background: #07c160; }
body.v3.home-page .v3-pad .hp-use__track strong { color: var(--wx-ink); font-weight: 500; }
body.v3.home-page .v3-pad .hp-use__track small { color: #999; }
/* Document: a WeChat file card. */
body.v3.home-page .v3-pad .v2-doc { gap: calc(12 * var(--pt)); padding: calc(12 * var(--pt)); border: 0; border-radius: calc(4 * var(--pt)); background: #fff; }
body.v3.home-page .v3-pad .v2-doc__icon { width: calc(40 * var(--pt)); height: calc(40 * var(--pt)); border-radius: calc(4 * var(--pt)); color: #fff; background: #3e7bf6; }
body.v3.home-page .v3-pad .v2-doc__body strong { color: var(--wx-ink); font-size: calc(16 * var(--pt)); font-weight: 400; }
body.v3.home-page .v3-pad .v2-doc__body small { color: #999; font-size: calc(13 * var(--pt)); }
/* Source line: grey system-note type, centred like WeChat's notices. */
body.v3.home-page .v3-pad .v2-src { align-self: center; gap: calc(4 * var(--pt)); color: #999; font-size: calc(13 * var(--pt)); }
body.v3.home-page .v3-pad .v2-src .hp-ico { width: calc(13 * var(--pt)); height: calc(13 * var(--pt)); color: #b2b2b2; }

/* Input bar */
body.v3.home-page .v3-pad .v2-scene .hp-chat__input { display: flex; align-items: flex-end; gap: calc(10 * var(--pt)); margin: 0; padding: calc(8 * var(--pt)) calc(10 * var(--pt)) calc(10 * var(--pt)); border: 0; border-top: .5px solid rgba(0, 0, 0, .08); border-radius: 0 0 var(--pad-r) var(--pad-r); color: var(--wx-ink); background: var(--wx-bar); box-shadow: none; font-size: calc(17 * var(--pt)); }
body.v3.home-page .v3-pad .v2-scene .hp-chat__input.has-text { border-color: rgba(0, 0, 0, .08); background: var(--wx-bar); box-shadow: none; }
body.v3.home-page .v3-pad [data-hp-typing] { flex: 1; min-width: 0; min-height: calc(40 * var(--pt)); padding: calc(8 * var(--pt)) calc(10 * var(--pt)); overflow: hidden; border-radius: calc(4 * var(--pt)); color: var(--wx-ink); background: #fff; font-size: calc(17 * var(--pt)); line-height: calc(24 * var(--pt)); text-overflow: ellipsis; white-space: nowrap; }
body.v3.home-page .v3-pad [data-hp-typing].is-typing::after { width: 1.5px; height: calc(20 * var(--pt)); background: #07c160; }
body.v3.home-page .v3-pad .v3-wx-ico { width: calc(30 * var(--pt)); height: calc(30 * var(--pt)); margin-bottom: calc(5 * var(--pt)); border-width: calc(1.6 * var(--pt)); }
body.v3.home-page .v3-pad .hp-chat__send { display: grid; flex: none; place-items: center; width: calc(30 * var(--pt)); height: calc(30 * var(--pt)); margin-bottom: calc(5 * var(--pt)); padding: 0; border: calc(1.6 * var(--pt)) solid #191919; border-radius: 50%; color: #191919; background: transparent; }
body.v3.home-page .v3-pad .hp-chat__send svg { display: none; }
body.v3.home-page .v3-pad .hp-chat__send::after { content: "+"; font-size: calc(24 * var(--pt)); font-weight: 300; line-height: 1; transform: translateY(calc(-1 * var(--pt))); }
body.v3.home-page .v3-pad .hp-chat__input.has-text .hp-chat__send { width: auto; height: calc(32 * var(--pt)); margin-bottom: calc(4 * var(--pt)); padding: 0 calc(12 * var(--pt)); border: 0; border-radius: calc(4 * var(--pt)); color: #fff; background: #07c160; }
body.v3.home-page .v3-pad .hp-chat__input.has-text .hp-chat__send::after { content: "发送"; font-size: calc(15 * var(--pt)); font-weight: 500; transform: none; }
body.v3.home-page .v3-pad .hp-chat__send.is-press { transform: scale(.94); }
body.v3.home-page .v2-scenes.is-static .v3-pad .hp-chat__send { background: transparent; }
/* Portrait: two product cards side by side leave a few characters per line. */
@media (max-width: 640px) { body.v3.home-page .v3-pad .hp-use__picks { grid-template-columns: minmax(0, 1fr); } }
/* Side by side: centred, the iPad reads high next to the tabs. Sit it on the
   section's bottom line so the note lines up with "看更多应用场景". */
@media (min-width: 1081px) { body.v3.home-page .v2-scenes__stage { align-self: end; } }



/* ---------- Header logo ----------
 * The teal SVG replaces the old lemon PNG plus its wordmark text.
 */

body.v3.home-page .site-header .brand--img img { display: block; width: auto; height: 42px; mix-blend-mode: normal; }
@media (max-width: 700px) {
  body.v3.home-page .site-header .brand--img img { height: 34px; }
}

/* Footer logo, same SVG as the header. */
body.v3.home-page .site-footer__brand--img img { display: block; width: auto; height: 30px; object-fit: contain; }


/* ---------- One vertical line ----------
 * The logo, the hero copy, the number strip and the footer logo must share the
 * same left edge. site.css caps .container at 1260px while the page body uses
 * the wider gutter-based width, so the header and footer sat 69px right of the
 * hero. On this page every container uses the page width.
 */
body.v3.home-page .site-header .container,
body.v3.home-page .site-footer .container,
body.v3.home-page main .container { width: min(var(--hp-max), calc(100% - var(--hp-gutter) * 2)); }

/* ---------- 04 用户评价 ----------
 * Three quotes with an initial avatar, in the same card language as the rest
 * of the page (hairline border, no shadow).
 */
/* Marquee: one continuous row that drifts right-to-left. The track holds two
   copies of the quotes, so translating it by exactly half its width loops with
   no seam. Hover pauses it; reduced motion stops it and leaves it scrollable. */
.v3-quotes__marquee { margin: 0 calc(50% - 50vw); overflow: hidden; -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 6%, #000 94%, transparent 100%); mask-image: linear-gradient(90deg, transparent 0, #000 6%, #000 94%, transparent 100%); }
.v3-quotes__list { display: flex; gap: 16px; width: max-content; margin: 0; padding: 4px max(var(--hp-gutter), calc(50vw - var(--hp-max) / 2)); list-style: none; animation: v3-marquee 64s linear infinite; will-change: transform; }
.v3-quotes__list > .v3-quote[aria-hidden="true"] { pointer-events: none; }
@keyframes v3-marquee { from { transform: translateX(0); } to { transform: translateX(-50%); } }
@media (hover: hover) and (pointer: fine) { .v3-quotes__marquee:hover .v3-quotes__list { animation-play-state: paused; } }
@media (prefers-reduced-motion: reduce) {
  .v3-quotes__list { animation: none; width: auto; overflow-x: auto; scroll-snap-type: x mandatory; scrollbar-width: none; }
  .v3-quotes__list > .v3-quote[aria-hidden="true"] { display: none; }
}
.v3-quote { display: grid; flex: 0 0 380px; gap: 22px; padding: 28px; border: 1px solid var(--hp-line); border-radius: var(--hp-radius); background: #fff; }
/* One continuous quote. The paragraphs are sentence groups — same colour and
   weight throughout — so it reads as one person speaking, not a headline. */
.v3-quote blockquote { display: grid; gap: 8px; margin: 0; color: var(--hp-text); font-size: var(--hp-fs-body); line-height: 1.8; }
/* Fill each line before breaking: no pretty-wrapping (it breaks early to avoid
   an orphan) and no breaking at punctuation, which cut lines in half. */
.v3-quote blockquote p { margin: 0; text-wrap: wrap; word-break: break-all; line-break: auto; overflow-wrap: normal; }
.v3-quote footer { display: flex; align-items: center; gap: 12px; padding-top: 20px; border-top: 1px solid var(--hp-line-soft); }
/* Illustrated avatar, 34px round. */
.v3-quote__avatar { flex: none; width: 34px; height: 34px; overflow: hidden; border-radius: 50%; }
.v3-quote__avatar img { display: block; width: 100%; height: 100%; }
.v3-quote__who { display: grid; gap: 2px; min-width: 0; }
.v3-quote__who strong { color: var(--hp-ink); font-size: var(--hp-fs-small); font-weight: 600; }
.v3-quote__who small { color: var(--hp-faint); font-size: var(--hp-fs-label); }
@media (max-width: 640px) { .v3-quote { flex-basis: calc(100vw - 100px); } }


/* ---------- 04 用户评价: give the section its own presence ----------
 * The page is a run of near-white sections, so a row of white cards read as
 * one more block of content. This section is the darkest surface on the page
 * — the same ink as the Mac window in the demo — with the quotes inverted, so
 * it breaks the page and the social proof is the thing you notice.
 */
.v3-quotes { border-block: 1px solid var(--hp-line-soft); background: #f3f6f1; }
.v3-quote { border-color: var(--hp-line); background: #fff; }
.v3-quote__avatar { border: 1px solid var(--hp-line); }
@media (min-width: 1081px) {
  /* A wider, more open card once the section is the anchor of the page. */
  .v3-quote { flex-basis: 420px; padding: 32px; }
}


/* ---------- Quote cards: fixed height, rest behind 更多 ----------
 * The quotes are long, and sizing each card to its text made every card 438px
 * tall. The card is a fixed 240px now; anything past that fades out and a
 * "更多" toggle reveals the rest in place. Without JS the full text shows.
 */
/* Three fixed rows in every card: quote, the 更多 line, the author. 更多 is
   the same line whether it is empty or not, so the author never shifts. */
.v3-quote { grid-template-rows: auto auto 1fr; }
.v3-quote > blockquote { display: block; }
.v3-quote footer { align-self: end; }
/* Body is a fixed number of lines, so the 更多 line and the author row sit at
   the same height in every card. 7 lines at this size is about 240px. */
/* Fixed 7-line well in every card (not just a max), so the 更多 line and the
   author row land at the same height whatever the quote length. */
.v3-quote__body { position: relative; height: calc(7 * 1.8em); min-height: calc(7 * 1.8em); flex: none; overflow: hidden; }
.v3-quote.is-open .v3-quote__body { height: auto; min-height: 0; }
.v3-quote.is-clamped:not(.is-open) .v3-quote__body::after { content: ""; position: absolute; right: 0; bottom: 0; left: 0; height: 72px; background: linear-gradient(transparent, #fff); pointer-events: none; }
/* While any card is open the row grows to fit it, and shifts every card alike. */
.v3-quotes__list { --v3-quote-rows: auto; }
.v3-quotes__list:has(.v3-quote.is-open) { --v3-quote-rows: 1fr; }

/* The row is always there — hidden with visibility, not display, or the author
   row below it would ride up in cards that have no button. */
.v3-quote__more { visibility: hidden; margin: 0; padding: 0; border: 0; color: var(--hp-jade); background: none; font: inherit; font-size: var(--hp-fs-small); font-weight: 500; line-height: 1.6; cursor: pointer; }
.v3-quote__more.is-shown { visibility: visible; }
.v3-quote__more:hover { text-decoration: underline; text-underline-offset: 3px; }
/* No JS: no clamp to hide behind, no button that would do nothing. */
html:not(.hp-js) .v3-quote__body { max-height: none; }
html:not(.hp-js) .v3-quote__body::after,
html:not(.hp-js) .v3-quote__more { display: none; }
