/* Jiangsu · Zhejiang · Shanghai KV integration
   This file only changes presentation. Route data and interactions remain in app.js. */

:root {
  --bb-space: #0d4728;
  --bb-space-deep: #03170d;
  --bb-panel: #0a3820;
  --bb-panel-soft: #12512f;
  --bb-cream: #f3f3ee;
  --bb-paper: #f3f2ec;
  --bb-gold: #f5cad7;
  --bb-gold-deep: #db789a;
  --bb-pink: #f04c83;
  --bb-cyan: #74f5ed;
  --bb-ink: #082719;
  --bb-muted: #b6cbbd;
  --bb-line: rgba(239, 246, 241, 0.24);
}

html { background: #03170d; }

body {
  color: var(--bb-paper);
  background:
    radial-gradient(circle at 50% -8%, rgba(74, 221, 126, 0.2), transparent 42%),
    #03170d;
}

.ambient { display: none !important; }

.app-shell {
  border-color: rgba(225, 238, 229, 0.18);
  background:
    linear-gradient(180deg, rgba(2, 35, 18, 0.05), rgba(2, 28, 15, 0.34)),
    url("assets/jzh-green-surface-v1.webp") center top / 100% auto repeat-y,
    #0d4728;
  box-shadow: 0 24px 90px rgba(0, 15, 8, 0.46);
}

.app-shell::before {
  background: radial-gradient(circle, rgba(116, 245, 237, 0.1), transparent 68%);
}

.topbar {
  border-bottom-color: rgba(239, 246, 241, 0.12);
  background: linear-gradient(180deg, rgba(3, 32, 17, 0.78), rgba(3, 32, 17, 0));
}

.brand { background: transparent; }
.brand-lockup { filter: drop-shadow(0 5px 12px rgba(0, 19, 10, 0.34)); }

/* Official full KV cover */
body.intro-active .app-shell {
  min-height: 100svh;
  border-top: 0;
  border-radius: 0;
  background: #0d4728;
}

body.intro-active .topbar {
  position: absolute;
  z-index: 4;
  width: 100%;
  height: 0;
  overflow: hidden;
  opacity: 0;
  pointer-events: none;
}

.intro-view {
  position: relative;
  min-height: 100svh;
  padding: 0;
  overflow: hidden;
  isolation: isolate;
}

.intro-view::before,
.intro-view::after { display: none !important; }

.intro-kv-art {
  position: absolute;
  z-index: -2;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center top;
  user-select: none;
  pointer-events: none;
}

/* The centre swirl already exists in the static KV. Two extra full-canvas
   copies (same crop/fit rules as .intro-kv-art, so they always land on the
   exact same pixels) sit on top: a ring layer that slowly spins + pulses,
   and the mascot cut-out that breathes, so the tap target visibly invites a
   tap instead of sitting there inert. */
.intro-kv-motion {
  position: absolute;
  z-index: 0;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: hidden;
  pointer-events: none;
  user-select: none;
}

.intro-kv-motion img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center top;
  pointer-events: none;
  user-select: none;
}

.intro-kv-motion__glow {
  transform-origin: 50% 61.4%;
  /* Feather out right where the mascot sits so the spin never drags the
     mascot silhouette baked into this layer along with it. */
  -webkit-mask-image: radial-gradient(circle at 50% 61.4%, transparent 0, transparent 8vw, black 15vw, black 100%);
  mask-image: radial-gradient(circle at 50% 61.4%, transparent 0, transparent 8vw, black 15vw, black 100%);
  animation: jzh-glow-spin 14s linear infinite, jzh-glow-pulse 3.2s ease-in-out infinite;
  will-change: transform, opacity, filter;
}

.intro-kv-motion__mascot {
  object-fit: cover;
  object-position: center top;
  transform-origin: 50% 61.4%;
  animation: jzh-mascot-bounce 2.1s ease-in-out infinite;
  will-change: transform, filter;
}

@keyframes jzh-glow-spin {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}

@keyframes jzh-glow-pulse {
  0%, 100% { opacity: 0.4; filter: brightness(1) saturate(1); }
  50% { opacity: 1; filter: brightness(1.35) saturate(1.25); }
}

@keyframes jzh-mascot-bounce {
  0%, 100% { transform: scale(1); filter: brightness(1); }
  50% { transform: scale(1.07); filter: brightness(1.16); }
}

.intro-meta,
.intro-copy {
  position: absolute !important;
  width: 1px !important;
  height: 1px !important;
  padding: 0 !important;
  margin: -1px !important;
  overflow: hidden !important;
  clip: rect(0 0 0 0) !important;
  white-space: nowrap !important;
  border: 0 !important;
}

.intro-action {
  position: absolute;
  z-index: 3;
  /* The official KV already has a small character in the centre of
     the pink subject. Turn that exact character into the tap target instead of
     adding a separate text CTA in the surrounding artwork. */
  top: 61.4%;
  bottom: auto;
  left: 50%;
  right: auto;
  width: 112px;
  height: 112px;
  margin: 0;
  padding: 0;
  transform: translate(-50%, -50%);
}

/* The base intro reveal animates transform on this wrapper. That would
   cancel the -50% centring once the reveal finishes, so keep the wrapper
   fixed and let the button itself carry the motion. */
.intro-view.is-active .intro-action,
.intro-view.skip-enter .intro-action {
  opacity: 1;
  transform: translate(-50%, -50%);
  animation: none;
}

.intro-enter,
#startBtn {
  position: relative;
  z-index: 1;
  display: block;
  width: 112px;
  height: 112px;
  min-height: 112px;
  padding: 0;
  color: transparent;
  border: 0;
  border-radius: 50%;
  background: transparent;
  box-shadow: none;
  cursor: pointer;
}

.intro-enter::before,
.intro-enter::after,
#startBtn::before,
#startBtn::after { display: none; }

.intro-enter:focus-visible,
#startBtn:focus-visible {
  outline: 3px solid #6df4eb;
  outline-offset: 6px;
}

/* 这个按钮是盖在 KV 中心小人上的透明热区,基础样式表里它本是一颗实心
   按钮:styles.css 的 .intro-enter:hover 会画出粉色硬阴影 + 柠檬绿光晕,
   鼠标一碰就糊在小人脸上。基础态已被上面清空,这里补上交互态。 */
.intro-enter:hover,
.intro-enter:active,
#startBtn:hover,
#startBtn:active {
  transform: none;
  background: transparent;
  box-shadow: none;
}

.intro-enter > span {
  position: absolute !important;
  width: 1px !important;
  height: 1px !important;
  padding: 0 !important;
  margin: -1px !important;
  overflow: hidden !important;
  clip: rect(0 0 0 0) !important;
  white-space: nowrap !important;
  border: 0 !important;
}

.intro-enter b { display: none; }

.intro-benefits,
.intro-action > p { display: none; }

/* Inner pages: calm green texture + silver/pink hierarchy */
.setup-view,
.result-view { color: var(--bb-paper); }

.setup-view .hero {
  margin: -8px -22px 0;
  padding: 42px 44px 34px;
  background:
    radial-gradient(circle at 92% 10%, rgba(240, 76, 131, 0.18), transparent 28%),
    linear-gradient(180deg, rgba(4, 57, 30, 0.18), rgba(4, 57, 30, 0));
}

.setup-view .hero::after { display: none; }
.hero-orbit { opacity: 0.56; }
.hero-orbit path { stroke: rgba(229, 238, 232, 0.34); }

.eyebrow,
.section-kicker,
.share-sheet-header p { color: var(--bb-cyan); }

.hero h1.brand-page-title,
.result-hero h1.brand-page-title {
  color: #f5f5ef;
  -webkit-text-stroke-color: rgba(255, 255, 255, 0.2);
  text-shadow: 0 10px 30px rgba(0, 20, 10, 0.38);
}

.hero h1.brand-page-title em,
.result-hero h1.brand-page-title em {
  color: #ff9cbd;
  text-shadow: 3px 3px 0 rgba(126, 18, 58, 0.66), 0 12px 30px rgba(0, 20, 10, 0.34);
}

.hero-copy,
.text-back { color: rgba(238, 245, 240, 0.76); }

.form-block {
  border-color: rgba(230, 241, 233, 0.24);
  background:
    radial-gradient(circle at 100% 0, rgba(116, 245, 237, 0.07), transparent 30%),
    rgba(3, 45, 23, 0.84);
  box-shadow: 0 20px 48px rgba(0, 24, 12, 0.24);
}

.form-block legend { color: #f4f4ee; }
.step-number {
  color: #082719;
  background: #ff9cbd;
  box-shadow: 3px 4px 0 rgba(116, 245, 237, 0.5);
}
.field-help { color: rgba(230, 241, 233, 0.62); }

.day-option {
  color: #f4f4ee;
  border-color: rgba(230, 241, 233, 0.24);
  background: rgba(2, 29, 15, 0.76);
  box-shadow: 7px 8px 0 rgba(1, 24, 12, 0.3);
}

.day-option[aria-pressed="true"] {
  color: #072518;
  border-color: rgba(255, 255, 255, 0.86);
  background: linear-gradient(145deg, #f4f4ef, #d9eee0 66%, #ffc1d5);
  box-shadow: 7px 8px 0 rgba(240, 76, 131, 0.34);
}

.day-option::after { border-color: rgba(240, 76, 131, 0.54); }
.day-option[aria-pressed="true"]::after { border-color: #0b5f36; background: #74f5ed; }

.selection-count {
  color: #082719;
  background: #ff9cbd;
  box-shadow: 3px 4px 0 rgba(116, 245, 237, 0.36);
}

.taste-chip {
  color: #f1f5f2;
  border-color: color-mix(in srgb, var(--chip-color) 48%, rgba(255,255,255,.16));
  background: rgba(2, 34, 17, 0.7);
}

.taste-chip[aria-pressed="true"] {
  color: #082719;
  border-color: rgba(255, 255, 255, 0.86);
  background: #f3f3ee;
  box-shadow: 4px 5px 0 color-mix(in srgb, var(--chip-color) 54%, transparent);
}

.taste-chip-icon { filter: drop-shadow(2px 3px 0 rgba(0, 29, 14, 0.38)); }

/* 选中后胶囊底色变成米白,基础样式表还会给图标加一道
   drop-shadow(3px 4px 0 rgba(7,22,44,.88)) 的近实心深色硬阴影,
   叠上近黑的图标色就糊成一团。这里改成:用该口味自己的颜色调深
   (保住色相身份、又保证在米白上够对比),并去掉那道重阴影。 */
.taste-chip[aria-pressed="true"] .taste-chip-icon {
  color: color-mix(in srgb, var(--chip-color) 40%, #082719);
  filter: none;
}

.primary-button,
.share-poster-button,
.sheet-primary {
  color: #082719;
  border-color: rgba(255, 255, 255, 0.88);
  background: linear-gradient(105deg, #f4f4ef 0 62%, #fac8d8 100%);
  box-shadow: 0 7px 0 rgba(240, 76, 131, 0.6), 0 18px 38px rgba(0, 25, 12, 0.24);
}

.button-arrow,
.share-poster-arrow,
.sheet-primary b { color: #fff; background: #082f1d; }

.surprise-button,
.secondary-button,
.friend-share-button,
.sheet-secondary {
  color: #eef4f0;
  border-color: rgba(230, 241, 233, 0.25);
  background: rgba(3, 45, 23, 0.84);
}

.micro-note,
.logic-note {
  color: rgba(234, 242, 237, 0.78);
  border-color: rgba(230, 241, 233, 0.2);
  background: rgba(3, 45, 23, 0.8);
}

/* Route result */
.result-hero {
  min-height: 276px;
  padding: 34px 22px 46px;
  /* Keep the route copy directly on the app shell's continuous official
     texture. A second image/gradient here produces a visible rectangular
     seam on mobile and risks placing key-visual artwork behind the copy. */
  background: none;
}

.result-hero > p:not(.eyebrow) { color: rgba(238, 245, 240, 0.76); }

.selected-tastes span {
  color: #f2f4f0;
  border-color: color-mix(in srgb, var(--tag-color) 48%, transparent);
  background: rgba(2, 29, 15, 0.68);
}

.day-tab {
  color: #eef4f0;
  border-color: rgba(230, 241, 233, 0.24);
  background: rgba(3, 45, 23, 0.92);
}
.day-tab[aria-selected="true"] {
  color: #082719;
  border-color: #f4f4ef;
  background: #f4f4ef;
}

.stat {
  border-color: rgba(230, 241, 233, 0.2);
  background: rgba(3, 45, 23, 0.9);
}
.stat strong { color: #ff9cbd; }
.stat span { color: rgba(230, 241, 233, 0.66); }

.content-card {
  color: #082719;
  border-color: rgba(255, 255, 255, 0.46);
  background: #f1f2ed;
  box-shadow: 0 24px 56px rgba(0, 25, 12, 0.24);
}
.section-heading h2 { color: #082719; }
.section-kicker { color: #0d6740; }
.live-mark { color: #174d32; background: #d4eadb; }
.live-mark i { background: #0b9655; }

.show-card {
  color: #082719;
  border-color: rgba(8, 39, 25, 0.14);
  background: rgba(255, 255, 252, 0.94);
  box-shadow: 0 12px 28px rgba(8, 39, 25, 0.08);
}
.show-card:hover,
.show-card.is-focused { border-color: rgba(8, 39, 25, 0.3); box-shadow: 0 14px 34px rgba(8, 39, 25, 0.12); }
.artist-artwork { box-shadow: 4px 5px 0 rgba(240, 76, 131, 0.32); }
.artist-name,
.show-time strong { color: #082719; }
.show-match { color: #0f6540; }
.show-match-dots i.on { background: #0b9655; }
.route-basis,
.artist-styles { border-color: rgba(8, 39, 25, 0.12); color: #4f695a; }
.route-basis > span,
.artist-styles > span { color: #7a9083; }
.route-basis > b,
.artist-styles > b { color: #173c29; }
.transfer { color: #698174; }
.transfer strong { color: #274d38; }
.stage-pill { color: #082719; }

.map-card { background: #e8ece7; }
.icon-button { color: #f2f4f0; border-color: rgba(230, 241, 233, 0.24); background: #07351f; }
.venue-map { border-color: rgba(8, 39, 25, 0.34); background: #07351f; }
.venue-map svg > rect:first-of-type { fill: #07351f; stroke: #4b8e68; }
.venue-map #mapBg stop:first-child { stop-color: #0b5b35; }
.venue-map #mapBg stop:last-child { stop-color: #031b0f; }
.venue-map .map-road,
.venue-map .map-path { stroke: rgba(226, 239, 230, 0.3); }
.venue-map .map-road-label,
.venue-map .entrance-node text,
.venue-map .twin-zone > text { fill: #eef4f0; }
.venue-map .audience-flow path { stroke: rgba(116, 245, 237, 0.54); }
.venue-map .map-zone ellipse,
.venue-map .map-zone rect { fill: rgba(238, 244, 240, 0.08); stroke: rgba(238, 244, 240, 0.28); }
.venue-map .map-zone text { fill: rgba(238, 244, 240, 0.72); }
.venue-map .twin-zone > rect { fill: rgba(240, 76, 131, 0.08); stroke: rgba(240, 76, 131, 0.44); }
.map-corner-label { color: rgba(238, 244, 240, 0.48); }
.map-note,
.map-legend { color: #557061; }
.logic-icon { color: #082719; background: #ff9cbd; }

/* Sharing */
.share-sheet-backdrop { background: rgba(1, 20, 10, 0.84); }
.share-sheet-panel {
  color: #eef4f0;
  border-color: rgba(230, 241, 233, 0.2);
  background:
    linear-gradient(180deg, rgba(4, 61, 32, 0.96), rgba(2, 28, 15, 0.99)),
    url("assets/jzh-green-surface-v1.webp") center / cover;
  box-shadow: 0 -24px 70px rgba(0, 20, 10, 0.52);
}
.share-sheet-header h2 { color: #f2f4f0; }
.share-sheet-close { color: #f2f4f0; border-color: rgba(230, 241, 233, 0.28); background: rgba(2, 36, 18, 0.8); }
.share-poster-preview { border-color: rgba(230, 241, 233, 0.24); background: rgba(2, 29, 15, 0.66); }
.poster-loading { color: rgba(230, 241, 233, 0.72); }
.share-conversion-note { border-color: rgba(230, 241, 233, 0.2); background: rgba(3, 45, 23, 0.78); }
.share-topics { color: #ff9cbd; }
.share-demo-note { color: rgba(230, 241, 233, 0.58); }

/* Transition */
.bubble-transition__core {
  background:
    radial-gradient(circle at 28% 22%, rgba(255,255,255,.18) 0 3%, transparent 14%),
    radial-gradient(circle at 72% 74%, rgba(240,76,131,.22), transparent 32%),
    linear-gradient(145deg, #176c3f, #0b4a2b 52%, #032416);
}
.bubble-transition__ring { border-color: rgba(235, 244, 238, 0.3); }
.bubble-transition__drop { border-color: rgba(235, 244, 238, 0.3); background: rgba(235, 244, 238, 0.1); }
.bubble-transition .drop-a { border-color: rgba(116, 245, 237, 0.4); }
.bubble-transition .drop-b { border-color: rgba(240, 76, 131, 0.44); }
.bubble-transition__name > b { color: #f3f3ee; }
.bubble-transition > strong small { color: rgba(230, 241, 233, 0.84); }

.site-footer {
  color: rgba(227, 239, 231, 0.56);
  border-color: rgba(227, 239, 231, 0.12);
}

@media (max-height: 700px) {
  .intro-kv-art {
    object-fit: cover;
    object-position: center top;
  }
  .intro-action { top: 61.4%; left: 50%; right: auto; bottom: auto; width: 104px; height: 104px; }
  .intro-enter,
  #startBtn { width: 104px; height: 104px; min-height: 104px; }
  .setup-view .hero { min-height: 232px; padding-top: 24px; }
}

@media (max-height: 620px) {
  .share-sheet-panel { padding-top: 14px; }
  .share-sheet-header { margin-bottom: 8px; }
  .share-poster-preview {
    width: min(190px, 68vw);
    margin-inline: auto;
  }
  .share-conversion-note {
    margin-block: 8px 6px;
    padding-block: 8px;
  }
  .share-sheet-actions { gap: 8px; margin-top: 8px; }
}

@media (max-width: 370px) {
  .intro-action { left: 50%; right: auto; width: 104px; height: 104px; }
  .setup-view .hero { margin-inline: -16px; padding-inline: 38px; }
}

@media (min-width: 560px) {
  body.intro-active { padding-top: 0; }
  body.intro-active .app-shell { min-height: 100vh; border-top: 0; border-radius: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .intro-kv-art { animation: none !important; }
  .intro-kv-motion__glow,
  .intro-kv-motion__mascot { animation: none !important; }
  .intro-kv-motion__glow { opacity: 0.6; }
}

/* ============================================================
   手机端:让选日期 / 选口味两步在一屏内看完,不用滚动。
   尺寸跟着 dvh 走,屏幕越矮收得越紧,而不是写死一组数值。
   只作用于窄屏,桌面端保留原本大标题的气势。
   ============================================================ */
@media (max-width: 560px) {
  /* 只在表单页隐藏页脚(结果页仍然保留),省 60px */
  .setup-view.is-active ~ .site-footer { display: none; }

  /* 基础样式给 hero 定了 min-height:276px,是这一屏最大的一块死高度 */
  .setup-view { padding-bottom: clamp(10px, 2dvh, 28px); }

  .setup-view .hero {
    min-height: 0;
    padding-top: clamp(10px, 2dvh, 22px);
    padding-bottom: clamp(8px, 1.6dvh, 18px);
  }

  .setup-view .hero-orbit { display: none; }

  .topbar { padding-block: 2px; }
  .brand-lockup { height: clamp(26px, 4dvh, 38px); }

  .setup-view .form-block legend { margin-bottom: 2px; }
  .setup-view .field-heading-row { margin-block: 4px 6px; }

  .setup-view .hero h1.brand-page-title {
    font-size: clamp(24px, 5.1dvh, 42px);
    line-height: 0.96;
  }

  /* 第二步的说明与卡片内提示重复,窄屏隐去 */
  .setup-view .hero-copy {
    margin-top: clamp(6px, 1.2dvh, 16px);
    font-size: 13px;
    line-height: 1.5;
  }
  .setup-view.is-taste-step .hero-copy { display: none; }

  /* 这是个文字链接,基础样式给了 44px 触控高度,窄屏上太占地方 */
  .setup-step-back {
    min-height: 0;
    height: auto;
    padding-block: 3px;
    margin-bottom: clamp(4px, 1dvh, 10px);
  }

  .setup-view .form-block {
    padding-top: clamp(10px, 1.7dvh, 18px);
    padding-bottom: clamp(10px, 1.7dvh, 18px);
    margin-bottom: clamp(10px, 1.6dvh, 16px);
  }

  /* 口味格:8 个 4 行是最占地方的一块 */
  .taste-grid { gap: clamp(6px, 1dvh, 10px); }
  .taste-chip {
    min-height: 0;
    height: clamp(36px, 6.1dvh, 60px);
    padding-block: 0;
  }

  .day-picker { gap: clamp(8px, 1.4dvh, 14px); }

  .generate-wrap { margin-top: clamp(10px, 1.8dvh, 20px); }
  .primary-button {
    min-height: 0;
    height: clamp(42px, 6.9dvh, 60px);
  }
  .surprise-button {
    min-height: 0;
    height: clamp(34px, 5dvh, 44px);
    margin-top: 6px;
  }

  .micro-note {
    margin-top: clamp(5px, 1dvh, 14px);
    font-size: 10.5px;
    line-height: 1.45;
  }
}

/* 保存海报的副标题按端切换:手机上 <a download> 在 WebView 里无效,
   实际靠长按图片保存,文案必须说实话。
   特异性要压过基础样式表里的 .sheet-primary small { display: block }。 */
.sheet-primary small.save-hint-mobile { display: none; }
.sheet-primary small.save-hint-desktop { display: block; }
body.is-touch-save .sheet-primary small.save-hint-desktop { display: none; }
body.is-touch-save .sheet-primary small.save-hint-mobile { display: block; }

/* ============================================================
   移动端满屏高度统一
   手机浏览器地址栏会伸缩:100vh 是「地址栏隐藏时」的高度,
   100svh 是「地址栏显示时」的高度。原来 body/.app-shell 用 vh、
   .intro-view 用 svh,两者差出一个地址栏,首页下方就能滑出一条空白。
   统一用 dvh(跟随当前可见高度),并锁死首页滚动。
   ============================================================ */
body { min-height: 100dvh; }
.app-shell { min-height: 100dvh; }

body.intro-active,
body.intro-active .app-shell,
.intro-view { min-height: 100dvh; }

/* 首页是一整屏 KV,没有需要滚动的内容 */
body.intro-active { overflow: hidden; }
body.intro-active .app-shell { overflow: clip; }

/* 顶栏右侧的主赞助方标识。首页 topbar 已被隐藏,不会出现在启动页。 */
.topbar-sponsor {
  flex: 0 0 auto;
  height: clamp(26px, 4dvh, 34px);
  width: auto;
  opacity: 0.92;
  filter: drop-shadow(0 4px 10px rgba(0, 19, 10, 0.4));
  user-select: none;
  pointer-events: none;
}

/* ============================================================
   艺人区背景:米白容器 → 绿色泡泡质感
   原来容器是米白 #f1f2ed,里面的演出卡又是近白,白压白显得平,
   也和整个深绿世界脱节。改成:容器走品牌绿(复用 KV 的绿色纹理 +
   两团柔光泡泡),演出卡保持白色浮在上面 —— 层次出来了,
   而卡内文字颜色一个都不用动。
   没有选黑色星空:那会引入第三套视觉世界,和绿色 KV 打架。
   ============================================================ */
.content-card {
  color: #eef4f0;
  border-color: rgba(235, 244, 238, 0.18);
  background:
    radial-gradient(circle at 14% 8%, rgba(116, 245, 237, 0.10), transparent 34%),
    radial-gradient(circle at 88% 82%, rgba(240, 76, 131, 0.12), transparent 36%),
    url("assets/jzh-green-surface-v1.webp") center top / 130% auto repeat-y,
    linear-gradient(158deg, #0d5230, #073a22 58%, #042416);
  /* 必须放在 background 简写之后:简写会把 background-color 重置成透明。
     纹理图万一加载失败时,这个兜底色保证不会露出透明底。 */
  background-color: #073a22;
  box-shadow: 0 24px 56px rgba(0, 20, 10, 0.34);
}

/* 容器自己的文字翻成浅色(演出卡内部不受影响) */
.content-card .section-heading h2 { color: #f3f3ee; }
.content-card .section-kicker { color: var(--bb-cyan); }
.content-card .live-mark {
  color: #06301c;
  background: rgba(190, 240, 210, 0.92);
}
.content-card .live-mark i { background: #0b9655; }
.content-card .map-note,
.content-card .map-legend { color: rgba(230, 241, 233, 0.66); }

/* 场地图本来就是深绿,放在绿容器上要有边界感 */
.content-card .venue-map {
  border-color: rgba(235, 244, 238, 0.22);
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.18);
}

/* 顶栏两个标识挨在一起(基础样式是 space-between,会把赞助标推到最右) */
.topbar { justify-content: flex-start; gap: 14px; }
.topbar .brand { flex: 0 0 auto; }

/* 泡泡岛标识的 img 盒子被拉到 101px 宽,而图本身 775×558、object-fit:contain,
   实际只画 45px,两侧 56px 是透明留白 —— 看起来就是两个标识中间空了一大块。
   宽度交回给比例,间距才是 gap 说了算。 */
.topbar .brand,
.topbar .brand-lockup { width: auto; }

/* 顶栏和结果页头部原来从 topbar 底到大标题空了近 100px:
   topbar 58 + view 上边距 7 + hero 上内边距 34 + 返回键下外边距 20。
   逐项收紧,整体上提约 55px;hero 下边距和 day-tabs 的负外边距是一对,
   不动,免得日期条压到口味标签上。 */
.topbar { min-height: 48px; padding-top: 0; padding-bottom: 0; }
.result-view { padding-top: 2px; }
.result-view .result-hero { padding-top: 8px; }
.result-view .result-hero .text-back { margin-bottom: 6px; }

/* 小人中心往外冒的泡泡。原来启动页只有光晕自转和小人呼吸,
   中心是静的;这层让它持续往四周吐泡泡,由小变大再淡出。
   容器零尺寸、定在 .intro-action 正中,所有位移都从小人中心算起。 */
.intro-bubbles {
  position: absolute;
  z-index: 2;
  top: 50%;
  left: 50%;
  width: 0;
  height: 0;
  pointer-events: none;
}

.intro-bubbles i {
  position: absolute;
  top: 0;
  left: 0;
  display: block;
  width: var(--size);
  height: var(--size);
  border: 2px solid rgba(255, 255, 255, 0.94);
  border-radius: 50%;
  background:
    radial-gradient(circle at 32% 27%,
      rgba(255, 255, 255, 1) 0 18%,
      rgba(255, 255, 255, 0.55) 34%,
      rgba(190, 240, 214, 0.34) 64%,
      rgba(255, 255, 255, 0.16) 100%);
  box-shadow: 0 0 16px rgba(198, 250, 226, 0.55);
  opacity: 0;
  animation: jzh-bubble-out 3.6s ease-out infinite;
  animation-delay: var(--delay);
  will-change: transform, opacity;
}

@keyframes jzh-bubble-out {
  0% { opacity: 0; transform: translate(-50%, -50%) scale(0.16); }
  14% { opacity: 0.96; }
  72% { opacity: 0.9; }
  100% { opacity: 0; transform: translate(-50%, -50%) translate(var(--tx), var(--ty)) scale(1); }
}

/* 系统开了「减少动态效果」就不要满屏飘 */
@media (prefers-reduced-motion: reduce) {
  .intro-bubbles i { animation: none; opacity: 0; }
}

/* 过渡页名称改成纯英文两行(BUBBLING / BOILING)。
   字体沿用 --font-label,也就是 BB Harmony Latin(HarmonyOS Sans Black)
   —— 海报上的 MY PERSONAL LINE-UP、舞台名用的是同一支,所以天然协调。
   只剩 8 个字符一行,可以比原来放大不少;行距压到 0.88 让两行读成一个整体。 */
.bubble-transition__name { gap: 0; }

.bubble-transition__name > b[lang="en"] {
  font-family: var(--font-label);
  font-size: clamp(36px, 12.5vw, 52px);
  line-height: 0.88;
  letter-spacing: 0.005em;
  text-shadow: 0 12px 34px rgba(0, 0, 0, 0.46);
}

/* 过渡页的名字上一层品牌渐变(青→奶白→粉→柠檬),而不是纯白。
   刻意全部用高明度的浅色调:底下是深绿 + 视频,饱和的正粉/正青压上去
   会掉对比、糊成一团,浅调既"花"又保住可读性。
   背景裁切文字要是不被支持,@supports 外面那条纯色就是兜底,不会变透明。 */
.bubble-transition__name > b[lang="en"] { color: #f3f3ee; }

@supports ((-webkit-background-clip: text) or (background-clip: text)) {
  .bubble-transition__name > b[lang="en"] {
    background-image: linear-gradient(96deg, #9ff6ee 0%, #f6f5ef 40%, #ffc2d8 76%, #e9ff9e 100%);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    color: transparent;
    /* 文字被镂空后 text-shadow 会从字背后透出来一坨,改用 drop-shadow 描形 */
    text-shadow: none;
    filter: drop-shadow(0 10px 26px rgba(0, 0, 0, 0.5));
  }
}

/* ── 蓝色兜底 ────────────────────────────────────────────────
   styles.css 是改版前的蓝色主题,:root 里这几个是蓝色系,且在
   styles.css 内被引用几十次(--ink 32 次、--muted 6 次)。
   本主题原先只逐条覆盖具体规则,漏掉任何一条,底下的蓝就会露出来
   (日期按钮的副标题 rgb(159,176,201) 就是这么漏的)。
   在变量层改掉,等于把所有引用一次性换成绿系,不用再逐个追。
   都是等明度替换,对比度不受影响。 */
:root {
  --ink: #082719;
  --ink-2: #0b3a22;
  --panel: #0a3820;
  --muted: #b6cbbd;
  --cyan: #74f5ed;
  --purple: #f04c83;
}

/* 选中日期是浅底,副标题要用深绿墨色而不是深蓝 */
.day-option[aria-pressed="true"] small { color: rgba(8, 39, 25, 0.74); }

/* 结果页残留的蓝(styles.css 旧配色,主题此前没盖到):
   艺人图占位底、契合标签、转场说明、场地图的 SOSO 节点与舞台副标题。
   前四项肉眼可见,图片加载瞬间那块navy 也会闪一下。 */
.artist-artwork.has-photo { background: #06301c; }
.show-type { color: color-mix(in srgb, var(--stage-color), #0b4a2b 34%); }
.match-label { color: #2f7a55; }
.transfer-line strong { color: #1d5c3c; }
.soso-node circle,
.soso-node rect { fill: #12614a; }
.stage-node .stage-sub { fill: #bcd8c8; }

/* ── 场地图(重画版)──────────────────────────────────────────
   规则:舞台=品牌实色块(最该被一眼找到),观演区=虚线描边的空块,
   服务区=低饱和填充。三档层级,不靠颜色数量取胜。
   所有类名都是新的,不会被 styles.css 的旧地图样式(椭圆/发光/动线)命中。 */
.venue-map svg { display: block; width: 100%; height: auto; }

.vmap-frame { fill: #052e1b; stroke: rgba(235, 244, 238, 0.2); stroke-width: 2; }

.vmap-caption {
  fill: rgba(226, 239, 230, 0.66);
  font: 700 9px "BB Harmony SC", "Microsoft YaHei", sans-serif;
  letter-spacing: 0.06em;
}

.vmap-road { fill: rgba(243, 243, 238, 0.09); stroke: rgba(243, 243, 238, 0.24); stroke-width: 1; }
.vmap-road-dash { stroke: rgba(243, 243, 238, 0.42); stroke-width: 1.6; stroke-dasharray: 7 6; stroke-linecap: round; fill: none; }

.vmap-entry rect { fill: #d8ff72; }
.vmap-entry text {
  fill: #082719; text-anchor: middle;
  font: 900 9.5px "BB Harmony SC", "Microsoft YaHei", sans-serif;
}
.vmap-arrow { stroke: rgba(216, 255, 114, 0.85); stroke-width: 1.8; fill: none; stroke-linecap: round; stroke-linejoin: round; }

/* 观演区:留空 + 虚线,读起来是「可以站人的地方」,不跟舞台抢注意力 */
.vmap-zone rect {
  fill: rgba(243, 243, 238, 0.055);
  stroke: rgba(235, 244, 238, 0.34);
  stroke-width: 1.2;
  stroke-dasharray: 5 4;
}
.vmap-zone-label {
  fill: #eef4f0; text-anchor: middle;
  font: 800 13px "BB Harmony SC", "Microsoft YaHei", sans-serif;
}
.vmap-zone-sub {
  fill: rgba(190, 226, 205, 0.72); text-anchor: middle;
  font: 800 8.5px "BB Harmony Latin", Arial, sans-serif;
  letter-spacing: 0.08em;
}

/* 舞台:品牌实色,深色字压在上面 */
.vmap-stage rect { stroke: rgba(3, 26, 14, 0.34); stroke-width: 1.4; }
.vmap-stage.seeu rect { fill: #d8ff72; }
.vmap-stage.soso rect { fill: #74f5ed; }
.vmap-stage.buzz rect { fill: #ff9cbd; }
.vmap-stage-label {
  fill: #082719; text-anchor: middle;
  font: 900 17px "BB Harmony Latin", Arial, sans-serif;
  letter-spacing: 0.01em;
}
.vmap-stage-sub {
  fill: rgba(8, 39, 25, 0.72); text-anchor: middle;
  font: 800 9px "BB Harmony SC", "Microsoft YaHei", sans-serif;
}

/* 命中今天路线的舞台:加一圈描边,不改填色,免得三个舞台的辨识色失效 */
.vmap-stage.is-highlighted rect {
  stroke: #f3f3ee;
  stroke-width: 3;
  filter: drop-shadow(0 0 6px rgba(255, 255, 255, 0.5));
}


.route-overlay .route-path {
  fill: none;
  stroke: #f04c83;
  stroke-width: 3;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-dasharray: 8 6;
}

/* 场次编号:深绿圆底 + 浅字,压在舞台的亮色块上也读得清 */
.route-number circle { fill: #06301c; stroke: rgba(243, 243, 238, 0.9); stroke-width: 1.4; }
.route-number text {
  fill: #f3f3ee; text-anchor: middle;
  font: 900 8.5px "BB Harmony Latin", Arial, sans-serif;
}

/* 编号放大到 r=8 / 10.5px,原来 6.6 + 8.5px 在手机上(整图只有 ~302px)糊成一团 */
.route-number text { font: 900 10.5px "BB Harmony Latin", Arial, sans-serif; }

/* 图例:原来的「推荐路线」是一根线,连线去掉后换成编号示意 */
.map-legend .legend-num {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 17px;
  height: 17px;
  border: 1.4px solid rgba(243, 243, 238, 0.9);
  border-radius: 50%;
  background: #06301c;
  color: #f3f3ee;
  font: 900 10px "BB Harmony Latin", Arial, sans-serif;
  font-style: normal;
}

/* 演示版角标。只在 <html data-build="demo"> 下出现,清版构建没有这个属性。 */
html[data-build="demo"] body::after {
  content: "预览版 PREVIEW";
  position: fixed;
  z-index: 9998;
  right: 10px;
  bottom: 10px;
  padding: 7px 13px;
  border: 1.5px solid rgba(255, 255, 255, 0.55);
  border-radius: 999px;
  background: rgba(8, 39, 25, 0.86);
  color: #ffd7e4;
  font: 900 11px "BB Harmony SC", "Microsoft YaHei", sans-serif;
  letter-spacing: 0.08em;
  pointer-events: none;
}

/* ── 购票入口:整张卡片就是按钮 ──────────────────────────────
   原来卡片里再套一颗纯白大按钮 —— 层级重复,而且那块白把整片绿版面切断了。
   改成整卡可点:左侧粉色竖条做视觉锚点,右下角一颗小胶囊说明"点了会怎样",
   右侧圆形箭头表示"打开弹窗"而不是"跳走"(所以用 → 不用 ↗)。 */
.ticket-block {
  position: relative;
  display: block;
  width: 100%;
  margin-top: 12px;
  padding: 16px 62px 16px 20px;
  overflow: hidden;
  border: 1.5px solid rgba(235, 244, 238, 0.22);
  border-radius: 22px;
  background: linear-gradient(150deg, rgba(11, 74, 44, 0.96), rgba(4, 40, 24, 0.96));
  box-shadow: 0 14px 30px rgba(0, 20, 10, 0.3);
  text-align: left;
  cursor: pointer;
}

/* 左侧粉色竖条 */
.ticket-block::before {
  content: "";
  position: absolute;
  top: 14px;
  bottom: 14px;
  left: 0;
  width: 4px;
  border-radius: 0 4px 4px 0;
  background: linear-gradient(180deg, #ff5f93, #f04c83);
}

.ticket-block__kicker {
  display: inline-block;
  margin-bottom: 9px;
  padding: 4px 11px;
  border-radius: 999px;
  background: rgba(240, 76, 131, 0.2);
  color: #ff8fa3;
  font: 900 10px "BB Harmony Latin", Arial, sans-serif;
  letter-spacing: 0.14em;
}

.ticket-block__title {
  display: block;
  color: #f3f3ee;
  font: 900 21px "BB Harmony SC", "Microsoft YaHei", sans-serif;
}

.ticket-block__note {
  display: block;
  margin-top: 5px;
  color: rgba(226, 239, 230, 0.76);
  font: 700 12.5px "BB Harmony SC", "Microsoft YaHei", sans-serif;
}


/* → 表示打开弹窗,不是跳走。跳走才用 ↗。 */
.ticket-block__arrow {
  position: absolute;
  top: 50%;
  right: 18px;
  display: grid;
  place-items: center;
  width: 42px;
  height: 42px;
  transform: translateY(-50%);
  border-radius: 14px;
  background: #ffc2d8;
  color: #0b3a22;
  font: 900 19px "BB Harmony Latin", Arial, sans-serif;
}

.ticket-block--sheet {
  margin-top: 10px;
  padding: 14px 58px 14px 18px;
  border-radius: 20px;
}

.ticket-block--sheet .ticket-block__title { font-size: 18px; }

/* 分享到社交媒体。原来是一颗描边胶囊,夹在"保存海报"(米白实心)和
   "购票"(整块卡片)中间,视觉分量最轻,反而像被遗漏的次要项。
   改成和购票同款的卡片结构,底部两块就成了一组对仗,层次也清楚了:
   保存(主) → 分享(同级) → 购票(转化)。 */
.share-block {
  display: block;
  width: 100%;
  margin-top: 10px;
  padding: 14px 16px 15px;
  border: 1.5px solid rgba(235, 244, 238, 0.22);
  border-radius: 22px;
  background: linear-gradient(150deg, rgba(11, 74, 44, 0.96), rgba(4, 40, 24, 0.96));
  box-shadow: 0 14px 30px rgba(0, 20, 10, 0.3);
  text-align: left;
  cursor: pointer;
}

.share-block__title {
  display: flex;
  flex-direction: column;
  gap: 3px;
  margin-bottom: 11px;
  color: #f3f3ee;
  font: 900 17px "BB Harmony SC", "Microsoft YaHei", sans-serif;
}

.share-block__title small {
  color: var(--bb-cyan);
  font: 900 10px "BB Harmony Latin", Arial, sans-serif;
  letter-spacing: 0.14em;
}

/* 五个标签用弹性换行会排成 4+1,第二行只剩一个像掉队。
   改成三列网格,固定排成 3+2 两行对齐,读起来才像是设计过的。 */
.share-block__apps {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 7px;
}

/* 平台图标(iconfont 素材)。统一加白色圆底 —— 微博没有底色、黑色细节会融进深绿,
   抖音本身就是黑底圆,直接放上去两个都看不清。加白底后五个视觉重量也一致。 */
.app-chip {
  display: flex;
  align-items: center;
  gap: 5px;
  padding: 5px 11px 5px 5px;
  border: 1px solid rgba(235, 244, 238, 0.2);
  border-radius: 999px;
  background: rgba(243, 243, 238, 0.07);
  color: rgba(232, 243, 236, 0.9);
  font: 800 11.5px "BB Harmony SC", "Microsoft YaHei", sans-serif;
  font-style: normal;
}

.app-chip b {
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  width: 19px;
  height: 19px;
  overflow: hidden;
  border-radius: 50%;
  background: #fff;
}

.app-chip b svg { width: 15px; height: 15px; display: block; }

/* 路线依据:从整张卡片降为一行细注。
   内容保留(这是全站唯一解释推荐逻辑的地方),但不该占着两个 CTA 上方的黄金位置。 */
.logic-line {
  display: flex;
  gap: 9px;
  align-items: flex-start;
  margin: 12px 4px 0;
  color: rgba(226, 239, 230, 0.7);
  font-size: 12px;
  line-height: 1.6;
}

.logic-line > span:first-child {
  flex: 0 0 auto;
  color: var(--bb-cyan);
  font-size: 13px;
  line-height: 1.5;
}

.logic-line b {
  margin-right: 6px;
  color: #eef4f0;
  font-weight: 900;
}

/* 提示条原来 z-index:200,而分享面板是 300 —— 在面板里点"保存海报"时,
   提示确实弹了,但整条被面板盖住,用户看到的就是"点了没反应"。
   抬到面板之上。 */
.toast { z-index: 400; }

/* 分享块现在排在第一位(它才是真正能用的动作),不需要顶部外边距;
   保存降为第二位,补上间距。 */
.share-sheet-actions > .share-block:first-child { margin-top: 0; }
.share-sheet-actions > .share-block + .sheet-primary { margin-top: 10px; }

/* ── 可读性修正(甲方 2026-08-30 反馈「看不清」)────────────────
   实测对比度:转场提示 3.34 / 其中 strong 只有 1.62,地图图例 1.16。
   1.16 基本等于看不见。根因是级联没盖全:图例胶囊的底色仍是基础样式里的
   rgba(255,255,255,.62)(浅色),而主题只把文字改成了浅色 —— 浅字压浅底。
   这里连底色一起改,并把 8-9px 的字号抬到 11px。 */
.map-legend { font-size: 11px; }

.content-card .map-legend span,
.map-legend span {
  padding: 6px 10px;
  border-color: rgba(235, 244, 238, 0.34);
  background: rgba(3, 40, 22, 0.82);
  color: #eef4f0;
  font-weight: 800;
}

.map-legend span:nth-child(3) { border-color: rgba(216, 255, 114, 0.5); }

.content-card .transfer-line,
.transfer-line {
  color: rgba(232, 243, 236, 0.9);
  font-size: 11px;
  font-weight: 700;
}

.content-card .transfer-line strong,
.transfer-line strong {
  color: #d8ff72;
  font-weight: 900;
}

/* 启动页入口提示。整个 section 已接管点击,所以提示不必贴在小人身上 ——
   放到 KV 底部,不压主体画面。绿点 + 粉色箭头是甲方设计稿的样式。 */
/* 轻触提示。
   居中基准是「文字本身」,不是「文字+圆点+箭头」这一整组:
   整组居中时,右边的箭头比左边的圆点占位宽,文字就会被顶得偏左一点点,
   量出来只差 1px,但眼睛看着就是不在小人正下方。所以圆点和箭头改成
   绝对定位挂在文字左右两侧,不参与父级的宽度计算。 */
.intro-tap-hint {
  position: absolute;
  z-index: 3;
  /* 用 clamp 夹住:纯百分比在极端屏幕比例下会漂,固定 px 又不自适应。
     下限 76px 保证不压到底部日期,上限 140px 保证不爬到主体角色上。 */
  bottom: clamp(76px, 13%, 140px);
  left: 50%;
  display: block;
  /* letter-spacing 会在最后一个字后面也留一份间距,使可见字形整体左偏半格。
     补一个等宽的左内边距抵消掉。 */
  padding-left: 0.08em;
  transform: translateX(-50%);
  color: #f2f8f4;
  font: 800 13px "BB Harmony SC", "Microsoft YaHei", sans-serif;
  letter-spacing: 0.08em;
  /* 提示落在瓶盖、仙人掌这些密集画面上,靠两层阴影拉开层次。
     按需求不加底色、边框和胶囊背景。 */
  text-shadow: 0 1px 2px rgba(0, 18, 9, 0.92), 0 3px 12px rgba(0, 18, 9, 0.72);
  white-space: nowrap;
  pointer-events: none;
  animation: jzh-tap-hint-breathe 2.4s ease-in-out infinite;
}

.intro-tap-hint::before,
.intro-tap-hint::after {
  position: absolute;
  top: 50%;
}

.intro-tap-hint::before {
  right: 100%;
  margin-top: -3px;
  margin-right: 10px;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: #d8ff72;
  box-shadow: 0 0 0 3px rgba(216, 255, 114, 0.14), 0 0 10px rgba(216, 255, 114, 0.8);
  content: "";
}

.intro-tap-hint::after {
  left: 100%;
  margin-left: 9px;
  transform: translateY(-50%);
  color: #ff7ba8;
  font: 900 17px/1 "BB Harmony Latin", Arial, sans-serif;
  letter-spacing: 0;
  text-shadow: 0 1px 3px rgba(0, 18, 9, 0.85);
  content: "\203A";
}

@keyframes jzh-tap-hint-breathe {
  0%, 100% { opacity: 0.72; }
  50% { opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
  .intro-tap-hint { animation: none; opacity: 1; }
}

.ticket-open-button b { color: #d8253c; font-size: 13px; }

.ticket-sheet {
  position: fixed;
  z-index: 320;
  inset: 0;
  display: flex;
  align-items: flex-end;
  justify-content: center;
}

.ticket-sheet__backdrop {
  position: absolute;
  inset: 0;
  border: 0;
  background: rgba(2, 16, 9, 0.62);
  backdrop-filter: blur(2px);
  cursor: pointer;
}

.ticket-sheet__panel {
  position: relative;
  width: min(520px, 100%);
  max-height: 86vh;
  overflow-y: auto;
  padding: 20px 18px 26px;
  border: 1.5px solid rgba(235, 244, 238, 0.24);
  border-radius: 26px 26px 0 0;
  background: linear-gradient(160deg, #0b4a2c, #04281a);
  box-shadow: 0 -18px 50px rgba(0, 16, 8, 0.5);
}

.ticket-sheet__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 16px;
}

.ticket-sheet__head h2 {
  margin: 4px 0 0;
  color: #f3f3ee;
  font: 900 19px "BB Harmony SC", "Microsoft YaHei", sans-serif;
}

.ticket-sheet__close {
  flex: 0 0 auto;
  width: 34px;
  height: 34px;
  border: 1.5px solid rgba(235, 244, 238, 0.32);
  border-radius: 50%;
  background: rgba(3, 40, 22, 0.6);
  color: #eef4f0;
  font-size: 19px;
  line-height: 1;
  cursor: pointer;
}

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

.tk-row {
  padding: 13px 14px;
  border: 1px solid rgba(235, 244, 238, 0.2);
  border-radius: 16px;
  background: rgba(243, 243, 238, 0.06);
}

.tk-row__head { display: flex; align-items: center; gap: 8px; margin-bottom: 7px; }
.tk-row__head b { color: #f3f3ee; font: 900 16px "BB Harmony SC", "Microsoft YaHei", sans-serif; }

.tk-row__kind {
  padding: 2px 8px;
  border-radius: 999px;
  background: rgba(216, 255, 114, 0.16);
  color: #d8ff72;
  font: 800 10.5px "BB Harmony SC", "Microsoft YaHei", sans-serif;
  font-style: normal;
}

/* 链接本身可选中 —— 这是复制的最后一层保底:两种复制接口都被拦时,
   用户还能长按选中手动复制。所以刻意不设 user-select:none。 */
.tk-row__link {
  display: block;
  margin-bottom: 9px;
  color: rgba(190, 226, 205, 0.92);
  font: 600 11px "BB Harmony Latin", Arial, sans-serif;
  line-height: 1.5;
  word-break: break-all;
  user-select: text;
}

.tk-row__note {
  display: block;
  margin-bottom: 2px;
  color: rgba(232, 243, 236, 0.86);
  font: 700 12.5px "BB Harmony SC", "Microsoft YaHei", sans-serif;
}

.tk-row__copy {
  padding: 8px 16px;
  border: 0;
  border-radius: 999px;
  background: #f4f4ef;
  color: #0b3a22;
  font: 900 12.5px "BB Harmony SC", "Microsoft YaHei", sans-serif;
  cursor: pointer;
}

.tk-agents-label {
  margin: 18px 0 9px;
  color: var(--bb-cyan);
  font: 900 10.5px "BB Harmony Latin", Arial, sans-serif;
  letter-spacing: 0.12em;
}

.tk-agents {
  display: flex;
  flex-wrap: wrap;
  gap: 7px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.tk-agents li {
  padding: 6px 11px;
  border: 1px solid rgba(235, 244, 238, 0.2);
  border-radius: 999px;
  background: rgba(243, 243, 238, 0.06);
  color: rgba(232, 243, 236, 0.9);
  font: 800 12px "BB Harmony SC", "Microsoft YaHei", sans-serif;
}

.tk-foot {
  margin: 16px 0 0;
  color: rgba(226, 239, 230, 0.66);
  font-size: 11.5px;
  line-height: 1.6;
}

body.ticket-open { overflow: hidden; }

/* ============================================================
   1)标题上的白框
   翻页后 JS 会把焦点移到该页 h1(tabindex="-1")上,方便读屏用户。
   桌面 Chrome 判定这不是 :focus-visible,不画焦点圈;安卓 Chrome 的
   判定更宽松,直接给 h1 画了一整圈 UA 默认白框,看起来像界面漏了个框。
   tabindex="-1" 的元素本来就按不到(不在 Tab 顺序里),去掉这圈不影响
   键盘可达性,读屏播报也照常。
   ============================================================ */
[tabindex="-1"]:focus {
  outline: none;
}

/* ============================================================
   2)表单页底部大片空白
   选日期这一步内容只有 634px,而可视区有 812px;小红书里没有浏览器
   地址栏,可视区还要再高 100px 左右,底下就空出接近一屏的三分之一。
   做法:让 .setup-view 撑满顶栏以下的高度,上下各放一个弹性占位。
   占位用 flex: 1 1 0,内容装不下时会被压回 0,内容照常往下撑、页面
   照常滚,不会出现「顶部被顶出可视区、划不回去」的老毛病。
   上下按 6:4 分,多出来的高度大头放在上面,内容整体往下坐,
   下方那块空白就明显收窄,主按钮也更靠近拇指。
   ============================================================ */
/* 顶栏实测只有 48px,写死 100dvh - 74px 会少算一截;带刘海的机器顶栏还会
   跟着安全区变高。改成让外壳自己分配:外壳竖向弹性,当前这一页占满剩余高度。
   flex: 1 0 auto —— 能长不能缩,内容比屏幕高时保持原尺寸、页面照常滚动。 */
.app-shell {
  display: flex;
  flex-direction: column;
}

.app-shell > .view {
  flex: 1 0 auto;
}

.setup-view {
  display: flex;
  flex-direction: column;
  min-height: 0;
}

.setup-view::before,
.setup-view::after {
  flex: 6 1 0;
  min-height: 0;
  content: "";
}

.setup-view::after {
  flex-grow: 4;
}

/* 弹性布局下相邻外边距不再合并,抵掉多出来的那一份 */
.setup-view > form {
  margin-top: 0;
}

/* ============================================================
   3)购票弹窗里的平台图标
   之前 app.js 已经把 SVG 画进 .ticket-ico 了,但样式表里没有这个类,
   内联 svg 拿不到尺寸,塌成 0×0,所以手机上一个图标都看不见。
   ============================================================ */
.ticket-ico {
  display: inline-flex;
  flex: 0 0 auto;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  border-radius: 6px;
  background: rgba(255, 255, 255, 0.94);
  overflow: hidden;
}

.ticket-ico svg {
  display: block;
  width: 16px;
  height: 16px;
}

/* 还没拿到官方素材的平台:统一票券图形,不带白底方块,
   直接用品牌柠檬绿画在透明底上,和旁边的官方彩色图标区分得开。 */
.ticket-ico.is-generic {
  background: none;
  color: #d8ff72;
}

.ticket-ico.is-generic svg {
  width: 19px;
  height: 19px;
}

.tk-agents li {
  display: inline-flex;
  align-items: center;
  gap: 7px;
}

.tk-agents .ticket-ico {
  width: 18px;
  height: 18px;
  border-radius: 5px;
}

.tk-agents .ticket-ico svg {
  width: 13px;
  height: 13px;
}

.tk-agents .ticket-ico.is-generic svg {
  width: 16px;
  height: 16px;
}

/* ============================================================
   表单页标题区的那条横向接缝
   .setup-view .hero 自带一层背景:一条 180deg 的深绿渐变 + 右上角粉色
   径向光。原来 hero 紧贴顶栏,这层背景的上边缘正好压在屏幕最顶端,看不见;
   加了上方弹性留白之后 hero 整体下移约 100px,那条硬边就露到页面中间,
   看起来像给页面拦腰划了一道线。
   这层背景本来就是为「贴顶」设计的,现在去掉,让标题区和页面底色连成一片。
   ============================================================ */
.setup-view .hero {
  background: none;
}

/* 购票卡上的平台图标条。只放拿到官方素材的那几家,
   排在标题和说明文字之间,和右侧粉色箭头方块拉开距离。 */

/* 说明行里的「图标 + 平台名」。图标贴在各自名字左边成对出现,
   平台之间靠 margin 分隔,不用间隔点。
   vertical-align 让图标视觉中心对齐汉字中心,而不是坐在基线上。 */
.tk-brand {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  margin-right: 12px;
  vertical-align: -3px;
}

.tk-brand .ticket-ico {
  width: 17px;
  height: 17px;
  border-radius: 5px;
}

.tk-brand .ticket-ico svg {
  width: 12px;
  height: 12px;
}

/* 右侧粉色箭头方块是绝对定位的,给说明行留出它的宽度,避免长文字压上去 */
.ticket-block__note {
  padding-right: 62px;
}

/* 右侧箭头方块占掉 61px,「图标+大麦 图标+秀动 创娱无界等平台同步开售」
   一行放不下(实测差 49px),缩字号或缩图标都补不回来。
   与其让它自己折成半截,不如主动断行:品牌一行,承接文字一行。 */
.ticket-block__brands {
  display: block;
  margin-bottom: 5px;
}

.tk-brand {
  margin-right: 16px;
}

/* ============================================================
   舞台名(SEE U / BUZZ / SOSO)看不清
   styles.css:2751 有一条 `.stage-node text { fill:#fff; font-size:8px }`,
   优先级 (0,1,1);我原来那条 `.vmap-stage-label` 只有 (0,1,0),被压掉了,
   所以线上一直是 8px 白字 —— 白字压柠檬绿的对比度只有 1.14:1,基本看不见。
   这里用 `.vmap-stage .vmap-stage-label` 提到 (0,2,0) 赢回来,同时按主办方
   要求放大并改深色。深绿 #082719 压三种品牌色的对比度分别是
   柠檬绿 14.3:1 / 粉 8.4:1 / 青 12.4:1,都远超 WCAG 4.5:1。
   ============================================================ */
.vmap-stage .vmap-stage-label {
  fill: #082719;
  font-size: 16px;
  font-weight: 900;
  letter-spacing: 0.02em;
}

/* ============================================================
   检票口 + VIP 前排观演区(主办方 2026-08-30 参考图新增)
   检票口用白色胶囊,和绿色的「入口」区分开:一个是进场前的检票,
   一个是进场口。深字压白底,对比度约 15:1。
   VIP 前排沿用观演区的虚线框语言,只是尺寸更窄,表示是前排区域。
   ============================================================ */
.vmap-gate rect {
  fill: rgba(243, 243, 238, 0.94);
  stroke: rgba(8, 39, 25, 0.28);
  stroke-width: 1;
}

.vmap-gate text {
  fill: #082719;
  text-anchor: middle;
  font: 800 8.5px "BB Harmony SC", "Microsoft YaHei", sans-serif;
}

.vmap-vip rect {
  fill: rgba(243, 243, 238, 0.075);
  stroke: rgba(235, 244, 238, 0.32);
  stroke-width: 1;
  stroke-dasharray: 4 3.5;
}

.vmap-vip-label {
  fill: #eef4f0;
  text-anchor: middle;
  font: 800 8.5px "BB Harmony SC", "Microsoft YaHei", sans-serif;
}

.vmap-vip-sub {
  fill: rgba(190, 226, 205, 0.78);
  text-anchor: middle;
  font: 800 8px "BB Harmony SC", "Microsoft YaHei", sans-serif;
}

/* ============================================================
   选口味那步:「帮我抽一组」和底部说明去掉底色边框
   这两块原来带 rgba(3,45,23,.84) 的深绿底 + 一圈边,压在页面绿底上
   像是两个多出来的面板。改成完全透明,和页面底色连成一片。
   只作用于这两个类:.surprise-button 在主题表里和另外三个真按钮共用
   一条规则,那三个还要保留底色,所以这里单独覆盖。
   ============================================================ */
.surprise-button,
.micro-note {
  border: 0;
  background: none;
}

/* ============================================================
   平台图标改成直接放在绿底上,不再套白色圆角方块
   官方素材已经裁成透明底、只留标识,四家(秀动/猫眼/蓝花火/票星球)
   都是高饱和彩色,压在深绿上本来就清楚,白底方块反而像贴了块补丁。
   ============================================================ */
.ticket-ico {
  background: none;
  border-radius: 0;
}

.ticket-ico img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
}

/* 内联 SVG(大麦)按外框铺满,和图片版对齐 */
.ticket-ico svg {
  width: 100%;
  height: 100%;
}

.tk-agents .ticket-ico,
.tk-brand .ticket-ico,
.ticket-ico.is-generic {
  background: none;
}

/* 购票卡上的品牌:创娱无界(官方自营)独占第一行,大麦、秀动并排第二行。
   用 flex + 100% 宽度换行,不在 HTML 里插 <br>,渠道增减时不会错位。 */
.ticket-block__brands .tk-brand:first-child {
  display: flex;
  width: 100%;
  margin-right: 0;
  margin-bottom: 5px;
}
