  :root {
    /* Background image — change here if you rename the file */
    --bg-image: url('bg3.webp');
    --bg-x: 62%;
    --bg-x-mobile: 69%;

    --overlay: rgba(218, 211, 198, 0.85);
    --ink: #121113;
    --ink-soft: #3f3e39;
    --ink-mute: #504c46;
    --line: rgba(24, 23, 26, 0.18);
    --card: rgba(255, 255, 255, 0.45);
    --card-border: rgba(255, 255, 255, 0.65);
  }

  * { margin: 0; padding: 0; box-sizing: border-box; }

  /* Visually hidden but readable by assistive tech and indexable by
     search engines — used for brand-variant keywords. */
  .sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
    border: 0;
  }

  html, body {
    min-height: 100vh;
    color: var(--ink);
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    font-family: 'Geist', sans-serif;
  }
  html[lang="zh"] body { font-family: 'Noto Sans SC', 'Geist', sans-serif; }

  /* Full-screen scroll snapping between the two sections — scrolling
     down past a threshold commits to the next screen instead of
     resting halfway, like Apple's product pages. */
  html {
    scroll-snap-type: y mandatory;
  }

  /* Boot lock — applied via class="booting" on <html> from the very first
     paint and removed by JS once load settles. While locked the document
     is unscrollable with snapping off, so iOS Safari has no saved scroll
     position to restore onto screen two (and nothing to flicker against). */
  html.booting,
  html.booting body {
    overflow: hidden !important;
    scroll-snap-type: none !important;
  }

  body {
    position: relative;
    overflow-x: hidden;
    background: #ece8e1; /* fallback while .bg loads */
    touch-action: pan-y;
    -webkit-overflow-scrolling: touch;
  }

  .snap {
    scroll-snap-align: start;
    scroll-snap-stop: always;
  }

  /* ------------------------------------------------------------------
     Fixed layers

     The real cutout is drawn on #cutoutCanvas:
     1. .bg is the only background image and stays fixed.
     2. #cutoutCanvas draws the translucent overlay.
     3. Canvas uses destination-out to erase the ShowShow text area,
        so that part becomes genuinely transparent and reveals .bg.
     4. The original h1.logo stays in the document flow as the layout
        anchor. Once the canvas is ready, h1.logo stops painting itself.

     This avoids the old background-position sync loop and avoids SVG
     mask coordinate bugs such as a half ShowShow appearing at top-left.
     ------------------------------------------------------------------ */
  .bg,
  .overlay,
  #cutoutCanvas,
  #globeBackdrop,
  #globeCanvas,
  .grain {
    position: fixed;
    inset: 0;
    width: 100vw;
    height: 100vh;
    height: 100lvh;
    pointer-events: none;
  }

  /* Section-2 dark backdrop — a black, semi-transparent vignette that
     fades in (scroll-linked) ABOVE the hero + light overlay, turning the
     second screen into a premium dark stage for the globe. z-index 4 sits
     above .page (3) so the first screen dims uniformly as you scroll. */
  #globeBackdrop {
    z-index: 4;
    opacity: 0;
    background:
      radial-gradient(120% 90% at 50% 42%,
        rgba(22,22,27,0.86) 0%,
        rgba(10,10,13,0.94) 55%,
        rgba(3,3,5,0.985) 100%);
    will-change: opacity;
  }

  /* Rotating globe layer — above the dark backdrop, revealed on scroll
     (opacity + scale are scroll-linked by JS). Starts hidden. */
  #globeCanvas {
    z-index: 5;
    opacity: 0;
    transform: scale(0.94);
    transform-origin: center 40%;
    will-change: opacity, transform;
  }

  .bg {
    background: var(--bg-image) var(--bg-x) center / cover no-repeat;
    z-index: 0;
    transform: translateZ(0);
    backface-visibility: hidden;
  }

  /* Fallback before Canvas is ready, and for no-JS. */
  .overlay {
    z-index: 1;
    background: var(--overlay);
  }

  #cutoutCanvas {
    /* Keep the canvas in layout from the first paint.
       Important for iPhone Safari: display:none makes getBoundingClientRect()
       return 0x0 on the first draw, so the cutout may not appear until the
       user scrolls/touches and triggers another resize/draw. */
    display: block;
    z-index: 1;
    opacity: 0;
    visibility: hidden;
    transform: translateZ(0);
    backface-visibility: hidden;
  }

  body.cutout-ready #cutoutCanvas {
    opacity: 1;
    visibility: visible;
  }
  body.cutout-ready .overlay { display: none; }

  .grain {
    z-index: 2;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='200' height='200'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0  0 0 0 0 0  0 0 0 0 0  0 0 0 0.06 0'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>");
    mix-blend-mode: multiply;
  }

  .page {
    position: relative;
    z-index: 3;
    min-height: 100vh;
    min-height: 100dvh;   /* match the visible viewport so snap points & footer line up on mobile */
    display: flex;
    flex-direction: column;
    padding: 28px clamp(20px, 5vw, 64px);
  }

  /* ---------- Top bar ---------- */
  .topbar {
    display: flex;
    justify-content: space-between;
    align-items: center;
    font-size: 12px;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--ink-soft);
    font-weight: 500;
  }
  html[lang="zh"] .topbar { letter-spacing: 0.04em; }

  .topbar .mark {
    display: flex;
    align-items: center;
    gap: 10px;
  }
  .topbar .dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: #2a8e5a;
    box-shadow: 0 0 0 4px rgba(42, 142, 90, 0.18);
    animation: pulse 2.4s ease-in-out infinite;
  }
  @keyframes pulse {
    0%, 100% { box-shadow: 0 0 0 4px rgba(42, 142, 90, 0.18); }
    50%      { box-shadow: 0 0 0 8px rgba(42, 142, 90, 0.05); }
  }

  /* Language toggle button (replaces the old date) */
  .lang-toggle {
    background: transparent;
    border: 1px solid var(--line);
    color: var(--ink-soft);
    font: inherit;
    font-size: 11.5px;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    padding: 7px 14px;
    border-radius: 999px;
    cursor: pointer;
    transition: background .25s ease, color .25s ease, border-color .25s ease;
    font-family: 'Geist', sans-serif;
  }
  html[lang="zh"] .lang-toggle { letter-spacing: 0.04em; }
  .lang-toggle:hover {
    background: var(--ink);
    color: #f8f5f0;
    border-color: var(--ink);
  }

  /* ---------- Hero ---------- */
  .hero {
    flex: 1;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    text-align: center;
    padding: 60px 0 40px;
  }

  .eyebrow {
    font-family: 'Instrument Serif', serif;
    font-style: italic;
    font-size: clamp(16px, 1.6vw, 20px);
    color: var(--ink-soft);
    margin-bottom: 14px;
    letter-spacing: 0.01em;
    opacity: 0;
    animation: rise 1.1s 0.1s cubic-bezier(.2,.7,.2,1) forwards;
  }
  html[lang="zh"] .eyebrow {
    font-family: 'Noto Serif SC', serif;
    font-style: normal;
  }

  /* The original logo remains the only document logo.

     Before Canvas is ready, this fallback shows the same visual style.
     After Canvas is ready, the h1 becomes invisible but still occupies
     the exact original layout position; Canvas reads its rect and cuts
     the real transparent hole there.
  */
  .logo {
    font-family: 'Archivo Black', sans-serif;
    font-weight: 900;
    font-size: clamp(56px, 14vw, 220px);
    line-height: 0.9;
    letter-spacing: -0.04em;
    max-width: 100%;

    background-image: var(--bg-image);
    background-repeat: no-repeat;
    background-size: cover;
    background-position: var(--bg-x) center;
    background-attachment: fixed;

    -webkit-background-clip: text;
            background-clip: text;
    -webkit-text-fill-color: transparent;
            color: transparent;

    margin: 0 0 22px;
    user-select: none;

    opacity: 0;
    transform: translateY(14px);
    animation: rise 1.2s 0.2s cubic-bezier(.2,.7,.2,1) forwards;
  }

  body.cutout-ready .logo {
    background-image: none;
    -webkit-text-fill-color: transparent;
            color: transparent;
  }

  .slogan {
    max-width: 640px;
    font-size: clamp(15px, 1.35vw, 18px);
    line-height: 1.65;
    color: var(--ink-soft);
    font-weight: 400;
    margin: 0 auto 8px;
    opacity: 0;
    animation: rise 1.1s 0.4s cubic-bezier(.2,.7,.2,1) forwards;
  }
  .slogan em {
    font-family: 'Instrument Serif', serif;
    font-style: italic;
    color: var(--ink);
    font-weight: 400;
  }
  /* "No-break" group — keeps the tail of the slogan together so it
     never orphans onto its own line as 1-2 characters. */
  .slogan .nb { white-space: nowrap; }
  html[lang="zh"] .slogan em {
    font-family: 'Noto Serif SC', serif;
    font-style: normal;
    font-weight: 600;
    border-bottom: 1px solid var(--ink);
    padding-bottom: 1px;
  }

  /* ---------- Feature row ---------- */
  .features {
    display: flex;
    gap: 14px;
    flex-wrap: wrap;
    justify-content: center;
    margin: 44px 0 40px;
    opacity: 0;
    animation: rise 1.1s 0.55s cubic-bezier(.2,.7,.2,1) forwards;
  }
  .feature {
    background: var(--card);
    border: 1px solid var(--card-border);
    backdrop-filter: blur(14px);
    -webkit-backdrop-filter: blur(14px);
    padding: 14px 22px;
    border-radius: 999px;
    display: flex;
    align-items: center;
    gap: 10px;
    font-size: 13.5px;
    color: var(--ink);
    font-weight: 500;
  }
  .feature .num {
    font-family: 'Instrument Serif', serif;
    font-style: italic;
    color: var(--ink-mute);
    font-size: 15px;
  }
  .feature code {
    font-family: ui-monospace, 'SF Mono', Menlo, monospace;
    font-size: 12.5px;
    background: rgba(24,23,26,0.07);
    padding: 2px 8px;
    border-radius: 6px;
    letter-spacing: 0.02em;
  }

  .protocol-inline {
    display: inline-flex;
    align-items: center;
    gap: 0;
  }

  .protocol-inline .protocol-label {
    margin-right: 8px;
  }

  /* ---------- CTA ---------- */
  .cta-wrap {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 12px;
    opacity: 0;
    animation: rise 1.1s 0.8s cubic-bezier(.2,.7,.2,1) forwards;
  }
  .cta {
    display: inline-flex;
    align-items: center;
    gap: 14px;
    padding: 16px 30px 16px 36px;
    background: var(--ink);
    color: #f8f5f0;
    text-decoration: none;
    border-radius: 999px;
    font-size: 15px;
    font-weight: 500;
    letter-spacing: 0.01em;
    /* No href on this <a> — explicit pointer + user-select so it still
       behaves visually like a clickable element. */
    cursor: pointer;
    user-select: none;
    -webkit-user-select: none;
    -webkit-touch-callout: none;
    transition: transform .35s cubic-bezier(.2,.7,.2,1),
                box-shadow .35s ease,
                background .35s ease;
    box-shadow: 0 12px 30px -12px rgba(24,23,26,0.45);
    border: 1px solid rgba(0,0,0,0.4);
  }
  .cta:hover,
  .cta:focus-visible {
    transform: translateY(-2px);
    box-shadow: 0 18px 40px -14px rgba(24,23,26,0.55);
    outline: none;
  }
  .cta.is-loading { pointer-events: none; opacity: 0.85; }
  .cta .arrow {
    display: inline-flex;
    width: 28px;
    height: 28px;
    border-radius: 50%;
    background: #f8f5f0;
    color: var(--ink);
    align-items: center;
    justify-content: center;
    font-size: 13px;
    transition: transform .35s cubic-bezier(.2,.7,.2,1);
  }
  .cta:hover .arrow { transform: translateX(4px); }
  .cta-host {
    font-size: 12px;
    color: var(--ink-mute);
    letter-spacing: 0.08em;
    text-transform: uppercase;
  }

  /* ---------- Restricted-region toast ---------- */
  .region-toast[hidden] { display: none !important; }
  .region-toast {
    position: fixed;
    left: 50%;
    bottom: 28px;
    transform: translate(-50%, 24px);
    z-index: 50;
    max-width: min(92vw, 460px);
    padding: 12px 22px;
    background: var(--card);
    border: 1px solid var(--card-border);
    backdrop-filter: blur(16px);
    -webkit-backdrop-filter: blur(16px);
    border-radius: 999px;
    font-size: 13.5px;
    line-height: 1.4;
    color: var(--ink);
    text-align: center;
    box-shadow: 0 16px 40px -20px rgba(24,23,26,0.35);
    opacity: 0;
    transition: opacity .25s ease, transform .25s cubic-bezier(.2,.7,.2,1);
    pointer-events: none;
  }
  .region-toast.show {
    opacity: 1;
    transform: translate(-50%, 0);
  }

  /* Pause the hero entrance animations while the loader is up, so
     the full staggered cascade plays from frame 0 once the loader
     dismisses — instead of finishing invisibly under it. */
  body.is-loading .eyebrow,
  body.is-loading .logo,
  body.is-loading .slogan,
  body.is-loading .features,
  body.is-loading .cta-wrap {
    animation-play-state: paused;
  }

  /* ---------- Initial loader ----------
     Purely visual: covers the page for ~0.8s then fades out. The geo
     lookup, font loading, canvas cutout etc. all run underneath in
     parallel — this just smooths over the first paint. The background
     color matches `body`'s fallback so the transition into the real
     bg image (once it streams in) is seamless. */
  .loader {
    position: fixed;
    inset: 0;
    z-index: 1000;
    display: flex;
    align-items: center;
    justify-content: center;
    background: #ece8e1;
    transition: opacity .4s ease;
  }
  .loader.is-done {
    opacity: 0;
    pointer-events: none;
  }
  .loader .spinner {
    position: relative;
    width: 44px;
    height: 44px;
    border-radius: 50%;
    border: 1.5px solid rgba(24, 23, 26, 0.10);
    border-top-color: rgba(24, 23, 26, 0.82);
    animation: loaderSpin .85s linear infinite;
    will-change: transform;
  }
  /* A small static counter-dot sits opposite the moving arc — gives
     the spinner a subtle weighted feel rather than a generic throbber. */
  .loader .spinner::after {
    content: '';
    position: absolute;
    top: -3px;
    left: 50%;
    width: 4px;
    height: 4px;
    margin-left: -2px;
    border-radius: 50%;
    background: rgba(24, 23, 26, 0.82);
  }
  @keyframes loaderSpin {
    to { transform: rotate(360deg); }
  }
  @media (prefers-reduced-motion: reduce) {
    .loader .spinner { animation-duration: 1.6s; }
  }

  /* ---------- Globe section (dark, scroll reveal) ----------
     The second screen. The globe is the fixed #globeCanvas behind it;
     this section holds the "立即体验" CTA and the page footer at the
     very bottom. The dark backdrop (#globeBackdrop) provides the
     premium black stage. */
  .globe-section {
    position: relative;
    z-index: 6;
    min-height: 100vh;
    min-height: 100dvh;   /* match visible viewport so the footer sits at the true bottom */
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: flex-end;
    text-align: center;
    padding: 60px clamp(20px, 5vw, 64px) clamp(28px, 4vh, 44px);
  }

  /* Two equal-size headline lines, pinned top-left of the dark screen.
     Revealed only once the globe has assembled (body/section .globe-ready),
     so on iOS they don't flash in mid-slide and jump to the top. */
  .globe-copy {
    position: absolute;
    top: clamp(74px, 12vh, 132px);
    left: clamp(20px, 5vw, 64px);
    text-align: left;
    pointer-events: none;
    opacity: 0;
    transform: translateY(18px);
    transition: opacity .8s ease, transform .8s cubic-bezier(.2,.7,.2,1);
  }
  .globe-section.globe-ready .globe-copy {
    opacity: 1;
    transform: translateY(0);
  }
  .globe-copy p {
    margin: 0;
    font-size: clamp(19px, 2.4vw, 31px);
    line-height: 1.34;
    font-weight: 500;
    letter-spacing: 0.005em;
    color: rgba(255, 255, 255, 0.92);
  }
  .globe-copy p + p { margin-top: 2px; }
  .globe-cta-wrap {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: flex-end;
    padding-bottom: clamp(40px, 9vh, 90px);
    opacity: 0;
    transform: translateY(26px);
    /* slight stagger after the copy */
    transition: opacity .8s ease .14s, transform .8s cubic-bezier(.2,.7,.2,1) .14s;
  }
  .globe-section.globe-ready .globe-cta-wrap {
    opacity: 1;
    transform: translateY(0);
  }

  /* Light (inverted) CTA for the dark stage — same interaction as the
     hero "Enter the Panel" button, restyled to stand out on black. */
  .cta-light {
    background: #f4f1ea;
    color: #15141a;
    border: 1px solid rgba(255, 255, 255, 0.55);
    box-shadow: 0 18px 50px -18px rgba(0, 0, 0, 0.7);
  }
  .cta-light:hover,
  .cta-light:focus-visible {
    box-shadow: 0 26px 60px -18px rgba(0, 0, 0, 0.8);
  }
  .cta-light .arrow {
    background: #15141a;
    color: #f4f1ea;
  }

  /* ---------- Footer ----------
     Lives at the very bottom of the dark globe section, so it's styled
     light. Fades in with the section. */
  .footer {
    width: 100%;
    display: flex;
    justify-content: center;
    align-items: center;
    font-size: 11px;
    letter-spacing: 0.2em;
    text-transform: uppercase;
    color: rgba(255, 255, 255, 0.42);
    padding-top: 18px;
    border-top: 1px solid rgba(255, 255, 255, 0.10);
    opacity: 0;
    transition: opacity .9s ease .28s;
  }
  .globe-section.globe-ready .footer { opacity: 1; }
  html[lang="zh"] .footer { letter-spacing: 0.08em; }

  @keyframes rise {
    to { opacity: 1; transform: translateY(0); }
  }

  @media (max-width: 640px) {
    :root { --bg-x: var(--bg-x-mobile); }
    .page { padding: 22px 22px; }
    .topbar { font-size: 10.5px; }
    .features { gap: 8px; }
    .feature { padding: 11px 16px; font-size: 12.5px; }
    .cta { padding: 14px 24px 14px 28px; font-size: 14px; }
    .footer { flex-direction: column; gap: 10px; align-items: start; }
    .logo { font-size: clamp(54px, 13.5vw, 96px); }
  }

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

  /* ---------- In-app browser block screen ---------- */
  .open-external[hidden] { display: none !important; }
  .open-external {
    position: fixed;
    inset: 0;
    z-index: 10;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 32px clamp(20px, 5vw, 48px);
  }
  .open-external-arrow {
    position: absolute;
    top: 18px;
    right: 22px;
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 6px;
    color: var(--ink);
    pointer-events: none;
  }
  .open-external-arrow svg {
    width: 56px;
    height: 56px;
    animation: oeBounce 1.6s ease-in-out infinite;
  }
  .open-external-arrow .oe-arrow-label {
    font-family: 'Instrument Serif', serif;
    font-style: italic;
    font-size: 14px;
    color: var(--ink-soft);
    margin-right: 4px;
  }
  html[lang="zh"] .open-external-arrow .oe-arrow-label {
    font-family: 'Noto Serif SC', serif;
    font-style: normal;
  }
  @keyframes oeBounce {
    0%, 100% { transform: translate(0, 0); }
    50%      { transform: translate(6px, -6px); }
  }
  .open-external-card {
    max-width: 460px;
    width: 100%;
    background: var(--card);
    border: 1px solid var(--card-border);
    backdrop-filter: blur(18px);
    -webkit-backdrop-filter: blur(18px);
    border-radius: 22px;
    padding: 36px 32px;
    text-align: center;
    box-shadow: 0 24px 60px -28px rgba(24,23,26,0.35);
  }
  .open-external-card .oe-eyebrow {
    font-family: 'Instrument Serif', serif;
    font-style: italic;
    font-size: 16px;
    color: var(--ink-soft);
    margin-bottom: 12px;
  }
  html[lang="zh"] .open-external-card .oe-eyebrow {
    font-family: 'Noto Serif SC', serif;
    font-style: normal;
  }
  .open-external-card .oe-title {
    font-family: 'Archivo Black', sans-serif;
    font-weight: 900;
    font-size: clamp(26px, 5vw, 36px);
    line-height: 1.1;
    letter-spacing: -0.02em;
    color: var(--ink);
    margin-bottom: 14px;
  }
  html[lang="zh"] .open-external-card .oe-title {
    font-family: 'Noto Sans SC', sans-serif;
    font-weight: 600;
    letter-spacing: 0;
  }
  .open-external-card .oe-desc {
    font-size: 15px;
    line-height: 1.7;
    color: var(--ink-soft);
    margin-bottom: 22px;
  }
  .open-external-card .oe-desc em {
    font-family: 'Instrument Serif', serif;
    font-style: italic;
    color: var(--ink);
    font-weight: 400;
  }
  html[lang="zh"] .open-external-card .oe-desc em {
    font-family: 'Noto Serif SC', serif;
    font-style: normal;
    font-weight: 600;
    border-bottom: 1px solid var(--ink);
    padding-bottom: 1px;
  }
  .open-external-card .oe-host {
    display: inline-block;
    font-family: ui-monospace, 'SF Mono', Menlo, monospace;
    font-size: 12.5px;
    background: rgba(24,23,26,0.07);
    color: var(--ink);
    padding: 6px 14px;
    border-radius: 999px;
    letter-spacing: 0.04em;
  }
