/* ═══ cosmic-silver tokens (spec §1) ═══ */
:root {
  --void: #0c0c0c;
  --deep-space: #10141f;
  --heading: #e5e4e2;
  --text: #dde2ec;
  --silver-dim: #a9b0bc;
  --silver-faint: #8a919c;
  --starlight: #f5f7fa;
  --rose: #fb7185;   /* the ONLY hue on the site: transformation stars + errors */
  --glass-bg: rgba(255, 255, 255, 0.05);
  --glass-bg-strong: rgba(16, 20, 31, 0.72);
  --glass-border: rgba(255, 255, 255, 0.1);

  /* mirror chrome gradients — single source of truth: the base heading rules
     and the animated glint overlay (@supports block below) MUST be the same
     two mirrors, so both reference these tokens */
  --chrome-mirror-lg: linear-gradient(
    180deg,
    #ffffff 0%,
    #eef2f8 16%,
    #c8d0dc 34%,
    #8e97a6 45%,
    #6f7787 49%,
    #dfe6ee 53%,
    #f8fafc 78%,
    #ffffff 100%
  );
  --chrome-mirror-sm: linear-gradient(
    180deg,
    #fdfeff 0%,
    #ccd4df 40%,
    #939da9 70%,
    #b9c2cf 100%
  );

  /* metallic silver sheen — the entire interaction language is chrome now:
     states are expressed by luminance (edge → brighter edge → inverted
     chrome plate), never by hue (user direction: no blue-violet) */
  --metal-hi: #f8fafc;        /* hover/focus highlight          15.2:1 */
  --metal-mid: #c8d0dc;       /* interactive text base          10.1:1 */
  --metal-lo: #9aa3b2;        /* control edges                   6.4:1 */
  --metal-deep: #6f7787;      /* horizon band / dark edge floor  3.62:1 — large text / decor only */
  --metal-deep-small: #8a93a5; /* small text on dark — AA-safe replacement for #6f7787 */
  --ink-on-chrome: #10141f;   /* text on a chrome plate          >=6.2:1 */
  /* WCAG AA contrast tokens (spec § contrast) */
  --text-muted-on-dark: #9aa3b2;  /* secondary on #1c202a — was #6b7280 (fails) */
  --text-muted-on-light: #4b5563; /* secondary on white/#fdf2f8 — was #9ca3af (fails) */
  --error-on-light: #b91c1c;      /* error on #fff — was #ef4444 (fails) */
  --error-on-dark: #fb7185;       /* error on #1c202a / var(--deep-space) — was #ef4444 */
  --gen-title: #f5f3ff;           /* generation title on subtle purple — was #6d28d9 (1.62:1) */
  --metal-line: rgba(200, 208, 220, 0.22);
  /* moving glint layer for the mirror chrome (user direction 2026-09-13/14):
     one diagonal light band crossing the glyphs, silver-white, no hue.
     45deg（使用者指定，最好辨認）；純白核心在已白的鏡面上不可見，故帶一段
     淡暗前導邊（墨色低透明）造出反光邊界的對比 — 亮區暗區都看得到移動。 */
  --chrome-glint: linear-gradient(
    45deg,
    transparent 0%,
    transparent 30%,
    rgba(16, 20, 31, 0.32) 36%,
    rgba(248, 250, 252, 0.95) 42%,
    rgba(248, 250, 252, 0.95) 50%,
    rgba(255, 255, 255, 0.15) 58%,
    transparent 64%,
    transparent 100%
  );
  --metal-edge: linear-gradient(
    135deg,
    rgba(255, 255, 255, 0.55),
    rgba(154, 163, 178, 0.18) 35%,
    rgba(240, 244, 250, 0.4) 60%,
    rgba(154, 163, 178, 0.15)
  );
}

/* ═══ deep-space ground (spec §3 layer 1) ═══ */
body {
  background:
    radial-gradient(120vw 90vh at 15% 8%, rgba(245, 247, 250, 0.05), transparent 60%),
    radial-gradient(90vw 70vh at 85% 92%, rgba(154, 163, 178, 0.04), transparent 55%),
    linear-gradient(135deg, var(--void), var(--deep-space));
  background-attachment: fixed;
  color: var(--text);
}

/* ═══ starfield: fixed decorative layers (spec §3) ═══ */
.sky-nebula,
.sky-stars-a,
.sky-stars-b {
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: -3;
}
.sky-nebula { z-index: -4; }

/* galaxy particle layer (spec §3 layer 4) — above CSS stars, below content */
#galaxy-canvas {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  z-index: -2;
}

/* band haze — same -18deg axis as the canvas particles (spec §4) */
.sky-nebula::before {
  content: '';
  position: absolute;
  left: -40%;
  right: -40%;
  top: 50%;
  height: 130vmax;
  transform: translateY(-50%) rotate(-18deg);
  background:
    radial-gradient(42% 10% at 50% 50%, rgba(245, 247, 250, 0.12), transparent 72%),
    radial-gradient(70% 18% at 50% 50%, rgba(245, 247, 250, 0.07), transparent 78%),
    radial-gradient(55% 15% at 50% 50%, rgba(154, 163, 178, 0.05), transparent 72%);
}

/* static star field — generated by scripts/gen-stars.js, do not edit */
.sky-stars-a,
.sky-stars-b {
  border-radius: 50%;
  animation: twinkleA 3.5s ease-in-out infinite alternate;
}
.sky-stars-a { width: 1px; height: 1px; box-shadow: 55.19vw 3.32vh 0 0 rgba(229,228,226,0.94),
  46.89vw 31.78vh 0 0 rgba(229,228,226,0.53),
  75.65vw 28.64vh 0 0 rgba(229,228,226,0.88),
  96.80vw 84.94vh 0 0 rgba(229,228,226,0.55),
  29.60vw 33.54vh 0 0 rgba(229,228,226,0.57),
  14.68vw 88.25vh 0 0 rgba(229,228,226,0.83),
  40.94vw 86.19vh 0 0 rgba(229,228,226,0.81),
  17.79vw 84.05vh 0 0 rgba(229,228,226,0.88),
  5.17vw 55.80vh 0 0 rgba(229,228,226,0.70),
  66.08vw 93.42vh 0 0 rgba(229,228,226,0.67),
  20.59vw 41.67vh 0 0 rgba(229,228,226,0.85),
  86.61vw 98.40vh 0 0 rgba(229,228,226,0.55),
  11.32vw 67.12vh 0 0 rgba(229,228,226,0.74),
  2.22vw 13.68vh 0 0 rgba(229,228,226,0.68),
  23.53vw 18.72vh 0 0 rgba(229,228,226,0.65),
  41.83vw 66.55vh 0 0 rgba(229,228,226,0.97),
  44.23vw 79.17vh 0 0 rgba(229,228,226,0.76),
  8.59vw 17.67vh 0 0 rgba(229,228,226,0.65),
  59.45vw 62.56vh 0 0 rgba(229,228,226,0.68),
  0.40vw 86.92vh 0 0 rgba(229,228,226,0.68),
  16.93vw 24.85vh 0 0 rgba(229,228,226,0.98),
  34.85vw 93.27vh 0 0 rgba(229,228,226,0.88),
  46.42vw 41.09vh 0 0 rgba(229,228,226,0.77),
  20.60vw 49.03vh 0 0 rgba(229,228,226,0.81),
  40.78vw 43.43vh 0 0 rgba(229,228,226,0.60),
  85.05vw 56.21vh 0 0 rgba(229,228,226,0.84),
  82.10vw 81.47vh 0 0 rgba(229,228,226,0.82),
  89.14vw 89.53vh 0 0 rgba(229,228,226,0.57),
  10.87vw 72.86vh 0 0 rgba(229,228,226,0.77),
  17.75vw 91.67vh 0 0 rgba(229,228,226,0.67); }
.sky-stars-b {
  width: 2px; height: 2px;
  animation-name: twinkleB;
  animation-duration: 7s;
  animation-delay: -2.2s;
  box-shadow: 86.52vw 79.11vh 0 0 rgba(229,228,226,0.58),
  5.51vw 54.68vh 0 0 rgba(229,228,226,0.71),
  0.23vw 98.23vh 0 0 rgba(229,228,226,0.54),
  17.64vw 56.39vh 0 0 rgba(229,228,226,0.74),
  68.62vw 74.67vh 0 0 rgba(229,228,226,0.52),
  37.49vw 18.99vh 0 0 rgba(229,228,226,0.71),
  48.98vw 95.72vh 0 0 rgba(229,228,226,0.44),
  17.63vw 95.93vh 0 0 rgba(229,228,226,0.70),
  17.94vw 69.18vh 0 0 rgba(229,228,226,0.63),
  78.25vw 13.85vh 0 0 rgba(229,228,226,0.74),
  73.70vw 81.62vh 0 0 rgba(229,228,226,0.73),
  26.66vw 27.93vh 0 0 rgba(229,228,226,0.48),
  60.25vw 84.44vh 0 0 rgba(229,228,226,0.67),
  7.34vw 36.19vh 0 0 rgba(229,228,226,0.53),
  59.06vw 90.09vh 0 0 rgba(229,228,226,0.41),
  12.32vw 94.38vh 0 0 rgba(229,228,226,0.43),
  71.27vw 36.63vh 0 0 rgba(229,228,226,0.52),
  18.20vw 56.51vh 0 0 rgba(229,228,226,0.57),
  1.69vw 84.02vh 0 0 rgba(229,228,226,0.43),
  56.67vw 90.25vh 0 0 rgba(229,228,226,0.59),
  90.67vw 76.78vh 0 0 rgba(229,228,226,0.58),
  48.73vw 56.46vh 0 0 rgba(229,228,226,0.68),
  43.41vw 16.66vh 0 0 rgba(229,228,226,0.60),
  94.71vw 71.26vh 0 0 rgba(229,228,226,0.49),
  53.81vw 13.11vh 0 0 rgba(229,228,226,0.61),
  16.92vw 46.24vh 0 0 rgba(229,228,226,0.60),
  0.14vw 75.28vh 0 0 rgba(229,228,226,0.41),
  57.50vw 61.10vh 0 0 rgba(229,228,226,0.69),
  19.47vw 17.89vh 0 0 rgba(229,228,226,0.40),
  72.40vw 73.51vh 0 0 rgba(229,228,226,0.71);
}
@keyframes twinkleA { from { opacity: 1; } to { opacity: 0.35; } }
@keyframes twinkleB { from { opacity: 0.8; } to { opacity: 0.3; } }

/* serif headings (spec §2) — Latin/digits via Playfair, CJK via Noto Serif TC.
   Mirror chrome (user-requested): a STATIC vertical reflection gradient —
   sky highlight, a sharp horizon break, then the ground reflection — like
   polished chrome plating. No sweeping animation; a mirror does not marquee.
   Falls back to solid --heading where background-clip: text is unsupported. */
h1, h2, h3, h4, h5, h6,
.nav-brand {
  font-family: 'Playfair Display', 'Noto Serif TC', serif;
  color: var(--heading);
  background: var(--chrome-mirror-lg);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.55)) drop-shadow(0 0 10px rgba(214, 224, 240, 0.28));
}
/* small headings can't carry the full mirror's dark horizon band (it melts
   into the card glass at 1.25rem) — light silver only, AA-safe throughout.
   background-image (not the shorthand) so background-clip: text survives. */
h3, h4, h5, h6 {
  background-image: var(--chrome-mirror-sm);
}

/* mirror chrome glint (user direction 2026-09-13, supersedes "no sweeping
   animation"): a slow light pass ACROSS the static mirror — the mirror
   gradient itself never moves; an oversized clipped sheen layer slides
   over it. The long rest between passes IS the effect: the eye is caught
   by change and habituates to constant motion. Periods differ per level
   (7.5s vs 13s) and are phase-offset, so headings drift out of sync and
   never pulse together. Sweeping band is fully off-text at both keyframe
   ends, so the loop seam is invisible. Only inside @supports: without
   background-clip: text the sheen would paint as a moving block. */
@supports (-webkit-background-clip: text) or (background-clip: text) {
  h1, h2, .nav-brand {
    background-image: var(--chrome-glint), var(--chrome-mirror-lg);
    background-size: 240% 100%, 100% 100%;
    background-position: 130% 0, 0 0;
    background-repeat: no-repeat;
    animation: chrome-glint 10s ease-in-out infinite;
  }
  h3, h4, h5, h6 {
    background-image: var(--chrome-glint), var(--chrome-mirror-sm);
    background-size: 240% 100%, 100% 100%;
    background-position: 130% 0, 0 0;
    background-repeat: no-repeat;
    animation: chrome-glint 16s ease-in-out 5.5s infinite;
  }
}
/* band center at position p: x = 1.2C − 1.4C·p/100 → p=130% fully off the
   left edge, p=−30% fully off the right; the pass runs left→right（閱讀方向）
   and takes 45% of the cycle — 大標 4.5s、小標 7.2s 的可追蹤速度
   (使用者回饋:原 2s 太快追不到)，其餘時間完全靜止。 */
@keyframes chrome-glint {
  0%   { background-position: 130% 0, 0 0; }
  45%  { background-position: -30% 0, 0 0; }
  100% { background-position: -30% 0, 0 0; }
}

/* ═══ reduced motion: freeze to a static sky (spec §4) ═══ */
@media (prefers-reduced-motion: reduce) {
  .sky-stars-a,
  .sky-stars-b {
    animation: none;
    opacity: 0.7;
  }
  h1, h2, h3, h4, h5, h6, .nav-brand {
    animation: none;  /* glint off — static mirror */
  }
}

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

body {
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', sans-serif;
  line-height: 1.6;
}

/* links: "clickable" is carried by the underline and luminance, not hue */
a {
  color: #cfd6e0;
  text-decoration: underline;
  text-decoration-color: rgba(200, 208, 220, 0.4);
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  transition: color 0.18s ease, text-decoration-color 0.18s ease;
}
a:hover {
  color: var(--metal-hi);
  text-decoration-color: var(--metal-hi);
  text-shadow: 0 0 10px rgba(248, 250, 252, 0.35);
}

button {
  font-family: inherit;
  cursor: pointer;
}

button:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}

input, select {
  font-family: inherit;
  background: var(--glass-bg);
  border: 1px solid var(--glass-border);
  border-radius: 4px;
  color: var(--text);
}

select option {
  background: var(--deep-space);
  color: var(--text);
}

select option:checked,
select option:hover,
select option:focus {
  background: var(--metal-mid);
  color: var(--ink-on-chrome);
}

input::placeholder { color: var(--silver-faint); }

input:focus, select:focus {
  outline: 2px solid var(--starlight);
  outline-offset: 1px;
  border-color: var(--metal-lo);
}

@media (max-width: 768px) {
  body {
    font-size: 14px;
  }
}

/* ── layout ── */
.app { min-height: 100vh; display: flex; flex-direction: column; }
.nav {
  background: var(--glass-bg-strong);
  -webkit-backdrop-filter: blur(20px);
  backdrop-filter: blur(20px);
  border-bottom: 1px solid var(--metal-line);
  color: var(--text);
  padding: 1rem 2rem;
  display: flex; justify-content: space-between; align-items: center;
  flex-wrap: wrap; gap: 1rem;
}
.nav a { color: var(--silver-dim); }
.nav a:hover { color: var(--starlight); }
.nav-brand { color: var(--heading); font-size: 1.25rem; font-weight: bold; text-decoration: none; }
.nav-links { display: flex; gap: 1rem; align-items: center; }
.nav-logout {
  background: transparent; border: 1px solid var(--glass-border); color: var(--silver-dim);
  padding: 0.25rem 0.75rem; border-radius: 4px;
}
.nav-logout:hover { border-color: var(--silver-dim); color: var(--starlight); }
main { flex: 1; }
.footer { padding: 1rem; text-align: center; font-size: 0.875rem; color: var(--silver-faint); }

/* ── shared ── */
.card {
  position: relative;
  border: 1px solid transparent;
  background:
    linear-gradient(var(--glass-bg), var(--glass-bg)) padding-box,
    var(--metal-edge) border-box;
  -webkit-backdrop-filter: blur(20px);
  backdrop-filter: blur(20px);
  padding: 1.5rem; border-radius: 18px 6px 18px 6px;  /* tailfin cut */
  margin-bottom: 1.5rem;
}
/* one line of skylight along the card's top edge */
.card::before {
  content: '';
  position: absolute; inset: 0 0 auto 0; height: 1px;
  border-radius: inherit; pointer-events: none;
  background: linear-gradient(90deg, transparent, rgba(248, 250, 252, 0.55), transparent);
}
.card,
.feature {
  transition: filter 0.4s ease;
}
.card:hover,
.feature:hover {
  filter: brightness(1.12);
}

.page { padding: 1.5rem; max-width: 800px; margin: 0 auto; }
.page-narrow { padding: 1.5rem; max-width: 600px; margin: 0 auto; }
.center-note { padding: 2rem; text-align: center; }
.error { color: var(--rose); margin-bottom: 1rem; font-size: 0.875rem; }
.muted { color: var(--silver-faint); }
/* primary CTA = chrome plate: on a dark site a bright plate with dark ink
   IS the strongest call-to-action signal (no hue needed). Bullet-nose
   silhouette + top reflection line = Jet Age streamline. */
.cta,
.btn-primary {
  position: relative; overflow: hidden;
  border: 1px solid transparent;
  border-radius: 999px;
  background:
    linear-gradient(180deg,
      #f8fafc 0%, #dbe2eb 34%, #aab3c1 50%,
      #8e97a6 56%, #c4ccd8 82%, #eef2f7 100%) padding-box,
    linear-gradient(160deg,
      rgba(255, 255, 255, 0.75), rgba(154, 163, 178, 0.35) 40%,
      rgba(248, 250, 252, 0.6) 65%, rgba(154, 163, 178, 0.3)) border-box;
  color: var(--ink-on-chrome);
}
.btn-primary {
  padding: 0.75rem 1.5rem; cursor: pointer; font-size: 1rem;
  font-weight: 500; text-decoration: none;
}
.cta { padding: 0.75rem 2rem; font-weight: 500; }
.cta::before,
.btn-primary::before {
  content: '';
  position: absolute; left: 6%; right: 6%; top: 2px; height: 42%;
  border-radius: 999px 999px 50% 50% / 999px 999px 100% 100%;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.9), rgba(255, 255, 255, 0));
  pointer-events: none;
}
.btn-primary:hover,
.cta:hover {
  filter: brightness(1.06);
  box-shadow: 0 0 18px rgba(248, 250, 252, 0.32);
}
.btn-primary:active,
.cta:active { filter: brightness(0.95); transform: translateY(1px); }
.btn-block { width: 100%; padding: 1rem 1.5rem; border-radius: 8px; border: none; font-size: 1rem; }
.btn-link, .back-link { background: none; border: none; color: #cfd6e0; cursor: pointer; }
.back-link { margin-bottom: 1rem; }
.prose { white-space: pre-wrap; line-height: 1.8; }

/* ── home ── */
.hero { padding: 3rem 2rem; max-width: 1200px; margin: 0 auto; }
.hero-head { text-align: center; margin-bottom: 3rem; position: relative; }
/* Jet Age speed lines, top-right of the hero */
.hero-head::after {
  content: '';
  position: absolute; right: 0; top: 0.5rem;
  width: 64px; height: 9px; pointer-events: none; opacity: 0.75;
  background:
    linear-gradient(#d5dde7, #d5dde7) 0 0 / 64px 1.5px,
    linear-gradient(#98a1af, #98a1af) 10px 3.5px / 54px 1px,
    linear-gradient(#6f7787, #6f7787) 20px 7px / 44px 1px;
  background-repeat: no-repeat;
}
.hero-head h1 { font-size: 2.5rem; margin-bottom: 1rem; color: var(--heading); }
.hero-sub { font-size: 1.25rem; color: var(--silver-dim); margin-bottom: 2rem; }
.hero-actions { display: flex; gap: 1rem; justify-content: center; flex-wrap: wrap; }
.cta-alt {
  color: #cfd6e0; padding: 0.75rem 2rem;
  border-radius: 999px; text-decoration: none; font-weight: 500;
  border: 1px solid var(--metal-lo);
  background: rgba(255, 255, 255, 0.04);
}
.cta-alt:hover {
  color: var(--metal-hi);
  border-color: var(--metal-hi);
  background: rgba(255, 255, 255, 0.08);
}
.feature-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 2rem; margin-top: 3rem;
}
.feature {
  border: 1px solid transparent;
  background:
    linear-gradient(var(--glass-bg), var(--glass-bg)) padding-box,
    var(--metal-edge) border-box;
  -webkit-backdrop-filter: blur(20px); backdrop-filter: blur(20px);
  padding: 2rem; border-radius: 18px 6px 18px 6px;  /* tailfin cut */
}
.feature h3 { font-size: 1.25rem; margin-bottom: 0.5rem; color: var(--heading); }
.feature p { color: var(--silver-dim); }

/* chrome ring on the ONE featured card — silver-white only (hue-rotate
   drift removed: it does nothing on a hueless gradient) */
.feature-grid .feature:first-child {
  position: relative;
  isolation: isolate;
}
.feature-grid .feature:first-child::before {
  content: '';
  position: absolute;
  inset: 0;
  padding: 1px;
  border-radius: inherit;
  pointer-events: none;
  background: conic-gradient(
    from 210deg,
    #8a93a5,
    #c8d0dc,
    #f8fafc,
    #eef2f7,
    #9aa3b2,
    #8a93a5
  );
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  mask-composite: exclude;
}

/* ── forms ── */
.auth-page { padding: 2rem; max-width: 400px; margin: 3rem auto; }
.field { margin-bottom: 1rem; }
.field label { display: block; margin-bottom: 0.5rem; font-size: 0.875rem; font-weight: 500; color: var(--silver-dim); }
.field input { width: 100%; padding: 0.75rem; font-size: 1rem; }
.form-grid3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 0.5rem; }
.form-col { display: flex; flex-direction: column; gap: 1rem; }
.form-label { font-size: 0.875rem; color: var(--silver-faint); }
.form-input {
  padding: 0.5rem; border: 1px solid var(--glass-border); border-radius: 4px;
  width: 100%; background: var(--glass-bg); color: var(--text);
}
.hour-row { display: flex; gap: 0.5rem; align-items: center; }
.hour-unknown { display: flex; align-items: center; gap: 0.25rem; font-size: 0.875rem; color: var(--silver-dim); }

/* ── ziwei palace grid ── */
.chart-meta { display: flex; flex-wrap: wrap; gap: 1rem; font-size: 0.9rem; color: var(--silver-dim); }
.palace-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 0.5rem; }
.palace {
  border: 1px solid var(--glass-border); border-radius: 8px; padding: 0.5rem;
  background: rgba(16, 20, 31, 0.55);
}
/* life palace: informational highlight — chrome border + inner glow,
   distinct from the inverted-plate "selected" state used by quiz */
.palace.life {
  border: 1px solid transparent;
  background:
    linear-gradient(rgba(255, 255, 255, 0.07), rgba(255, 255, 255, 0.03)) padding-box,
    linear-gradient(180deg, rgba(248, 250, 252, 0.85), rgba(154, 163, 178, 0.25) 45%, rgba(248, 250, 252, 0.5)) border-box;
  box-shadow:
    inset 0 0 0 1px rgba(255, 255, 255, 0.06),
    0 0 14px -4px rgba(248, 250, 252, 0.4);
}
.palace-head { font-weight: 600; font-size: 0.85rem; color: var(--heading); }
.palace-stars { margin-top: 0.25rem; display: flex; flex-wrap: wrap; gap: 0.25rem; }
.star { font-size: 0.8rem; padding: 0.15rem 0.35rem; border-radius: 4px; background: rgba(255, 255, 255, 0.07); color: var(--silver-dim); }
.star.main { background: rgba(229, 228, 226, 0.14); color: var(--starlight); }
.star.transformation { background: rgba(251, 113, 133, 0.12); color: var(--rose); }

/* ── /personality result: OCEAN score tracks (Grok design review) ── */
.ocean-dim {
  background: rgba(255, 255, 255, 0.04);
  border-radius: 8px;
  padding: 1rem 1.125rem 1.125rem;
  margin-bottom: 0.75rem;
}
.ocean-dim:last-of-type { margin-bottom: 0; }
.ocean-dim-head {
  display: flex; justify-content: space-between; align-items: baseline;
  gap: 1rem; margin-bottom: 0.375rem;
}
.ocean-dim-head strong { font-size: 0.9375rem; color: var(--heading); font-weight: 600; }
.ocean-score {
  font-variant-numeric: tabular-nums;
  font-size: 1.375rem;
  font-weight: 700;
  line-height: 1;
  letter-spacing: -0.02em;
  background-image: linear-gradient(180deg, #fdfeff 0%, #dbe2eb 55%, #a8b1bf 100%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
}
.ocean-track-wrap { padding: 10px 12px 8px; }
.ocean-track {
  position: relative;
  height: 8px;
  background: rgba(255, 255, 255, 0.08);
  border-radius: 999px;
}
.ocean-band {
  position: absolute; top: 0; height: 100%;
  background: linear-gradient(90deg, #8e97a6, #e2e8f0);  /* value = length, not hue */
  border-radius: 999px;
}
.ocean-mean {
  position: absolute;
  top: -5px; width: 2px; height: 18px;
  background: var(--silver-faint);
  border-radius: 1px;
  transform: translateX(-50%);
}
.ocean-marker {
  position: absolute; top: 50%;
  width: 14px; height: 14px;
  background: var(--starlight);
  border: 2px solid var(--deep-space);
  box-shadow: 0 0 0 1px var(--metal-mid), 0 0 8px rgba(248, 250, 252, 0.45);
  border-radius: 50%;
  transform: translate(-50%, -50%);
}
.ocean-caption {
  font-size: 0.75rem;
  color: var(--silver-faint);
  margin: 0.375rem 0 0;
}
.ocean-copy {
  margin-top: 0.75rem;
  font-size: 0.9375rem;
  line-height: 1.65;
  color: var(--silver-dim);
}
.ocean-foot {
  margin-top: 1.5rem;
  padding-top: 1.25rem;
  border-top: 0;
}
/* chrome trim: divider between the result body and actions */
.ocean-foot::before {
  content: '';
  display: block;
  width: 8rem;
  height: 2px;
  border-radius: 2px;
  margin-bottom: 1rem;
  background: linear-gradient(90deg,
    transparent 0%, #6f7787 10%, #f8fafc 45%,
    #8e97a6 55%, #3f4756 90%, transparent 100%);
  opacity: 0.75;
}
.ocean-foot strong {
  display: block;
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--silver-dim);
}
.ocean-foot > .muted { font-size: 0.8rem; margin-top: 0.375rem; }
.ocean-foot details { margin-top: 1rem; }
.ocean-foot summary { color: var(--silver-faint); font-size: 0.875rem; cursor: pointer; }
.ocean-foot .actions { display: flex; flex-wrap: wrap; gap: 0.75rem; margin-top: 1.25rem; }

/* ── /personality quiz: Likert matrix (Grok design review) ── */
.quiz-head { display: flex; justify-content: space-between; gap: 1rem; align-items: start; margin-bottom: 1rem; }
.quiz-head .muted { color: var(--silver-dim); }
.quiz-head .btn-link { flex-shrink: 0; font-size: 0.875rem; white-space: nowrap; }
.quiz-consent { font-size: 0.8125rem; margin-bottom: 1.25rem; color: var(--silver-dim); }
.quiz-progress { font-size: 0.8125rem; color: var(--silver-dim); margin: 0; font-variant-numeric: tabular-nums; }
.quiz-progress strong { color: var(--text); font-weight: 700; }
.quiz-progress-bar { height: 3px; background: rgba(255, 255, 255, 0.12); border-radius: 999px; margin: 0.5rem 0 1.25rem; overflow: hidden; }
.quiz-progress-bar > span { display: block; height: 100%; background: linear-gradient(90deg, #8e97a6, #f8fafc); border-radius: inherit; }
.quiz-key {
  display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 0.375rem;
  padding: 0 1rem 0.75rem; font-size: 0.6875rem; line-height: 1.3;
  color: var(--silver-dim); text-align: center;
}
.quiz-item {
  border: 0; min-width: 0; background: rgba(255, 255, 255, 0.04); border-radius: 8px;
  margin: 0 0 0.5rem; padding: 0.75rem 1rem 0.875rem;
}
.quiz-item:last-of-type { margin-bottom: 0; }
.quiz-item legend {
  float: none; width: 100%; padding: 0; margin: 0 0 0.625rem;
  font-weight: 600; font-size: 0.9375rem; color: var(--heading);
}
.quiz-no {
  display: inline-block; min-width: 1.5rem; text-align: center; margin-right: 0.5rem;
  font-size: 0.75rem; font-weight: 700; font-variant-numeric: tabular-nums;
  color: var(--ink-on-chrome); background: linear-gradient(180deg, #e8edf4, #b6bfcc); border-radius: 4px; padding: 0.1rem 0.35rem;
}
.quiz-choices { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 0.375rem; }
.quiz-choice {
  position: relative; display: flex; align-items: center; justify-content: center;
  min-height: 44px; border: 1px solid var(--glass-border); border-radius: 8px;
  background: rgba(16, 20, 31, 0.55);
  cursor: pointer; font-variant-numeric: tabular-nums; font-weight: 600; color: var(--silver-dim);
}
.quiz-choice:hover { border-color: var(--metal-mid); background: rgba(255, 255, 255, 0.07); }
/* selected = inverted chrome plate — inversion is reserved for selection only */
.quiz-choice:has(input:checked) {
  background: linear-gradient(180deg, #f8fafc, #c8d0dc);
  border-color: var(--metal-hi);
  color: var(--ink-on-chrome);
}
.quiz-choice:has(input:focus-visible) { outline: 2px solid var(--starlight); outline-offset: 2px; }
.quiz-choice input {
  appearance: none; position: absolute; inset: 0; opacity: 0; margin: 0; border: 0; cursor: pointer;
}
.quiz-submit {
  position: sticky; bottom: 0;
  margin: 1.25rem -1.5rem -1.5rem;
  padding: 0.75rem 1.5rem calc(0.75rem + env(safe-area-inset-bottom));
  background: var(--glass-bg-strong);
  -webkit-backdrop-filter: blur(20px); backdrop-filter: blur(20px);
  border-top: 1px solid var(--metal-line);
}
.quiz-submit .btn-primary { width: 100%; }
.quiz-submit .btn-primary:disabled { opacity: 1; background: rgba(255, 255, 255, 0.08); color: var(--silver-faint); cursor: not-allowed; }
@media (max-width: 639px) {
  .quiz-key { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 0.25rem 0.75rem; padding: 0 0.25rem 0.75rem; }
  .quiz-key { counter-reset: k; }
  .quiz-key span { counter-increment: k; }
  .quiz-key span::before { content: counter(k) " "; font-weight: 600; color: var(--metal-mid); }
}

/* dark scrollbar polish */
::-webkit-scrollbar { width: 10px; }
::-webkit-scrollbar-track { background: var(--void); }
::-webkit-scrollbar-thumb { background: rgba(255, 255, 255, 0.12); border-radius: 999px; }
::-webkit-scrollbar-thumb:hover { background: rgba(255, 255, 255, 0.2); }

/* coarse-pointer fallback (spec §8): drop blur (which would recompute
   over the animating canvas every frame) and raise the strong-glass
   alpha so nav/sticky bars stay legible */
@media (pointer: coarse) {
  .nav,
  .card,
  .feature,
  .quiz-submit {
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }
  .card,
  .feature {
    background: rgba(16, 20, 31, 0.82);  /* solid ground: no blur to rely on */
  }
  :root { --glass-bg-strong: rgba(12, 14, 22, 0.9); }
  /* glint off on touch devices too: every pass repaints the heading over
     the animating galaxy canvas — same reason blur is dropped above */
  h1, h2, h3, h4, h5, h6, .nav-brand {
    animation: none;
  }
}

/* ── light-surface safety (contrast fix) ──
   任何白/淺底面板內的文字必須用深墨色，否則會繼承 var(--text)/var(--starlight)
   的淡色而隱形（如 divination 西洋行星白卡）。掛上 .on-light 即自動翻正，
   並把鏡面標題的漸層關掉改實色，避免白字在白底上消失。
   另外提供 .text-frame 給疊在不確定背景上的淡字（加描邊/陰影）備用。 */
.on-light { color: var(--ink-on-chrome); }
.on-light h1, .on-light h2, .on-light h3, .on-light h4, .on-light h5, .on-light h6,
.on-light .palace-head {
  background: none;
  -webkit-background-clip: border-box;
  background-clip: border-box;
  -webkit-text-fill-color: var(--ink-on-chrome);
  filter: none;
  color: var(--ink-on-chrome);
  animation: none;  /* glint layer is clipped-text only; keep light surfaces fully static */
}
.on-light .muted { color: var(--text-muted-on-light); }
.on-light a { color: #1e3a8a; text-decoration-color: rgba(30, 58, 138, 0.35); }
.on-light a:hover { color: #1e40af; text-decoration-color: #1e40af; }
/* 淺底上的 star 標籤：覆蓋深色玻璃版的淡字設定 */
.on-light .star { background: #fff; color: var(--text-muted-on-light); border-color: #e5e7eb; }
.on-light .star.main { background: #fff; color: #374151; border-color: #e5e7eb; }

/* 字框備用：淡字疊在照片/漸層等不確定底色上時，描邊保底線可讀性 */
.text-frame {
  text-shadow:
    0 1px 2px rgba(16, 20, 31, 0.75),
    0 0 1px rgba(16, 20, 31, 0.9),
    0 0 8px rgba(16, 20, 31, 0.45);
}
.text-frame--light {
  -webkit-text-stroke: 0.45px rgba(16, 20, 31, 0.55);
  paint-order: stroke fill;
}
