
:root {
  /* 2026-09-15 Andy 定案：前台整站套「成人頻道」活動官網的夜空配色（討論時的 C 方案）。
     🔴 不分深淺色模式——官網只有深色，前台也只有這一套，客人從官網點進來不會像換了一個網站。
     色碼來源：活動官網 session 整理的色票（夜空底、訊號藍、薄荷、ON AIR 粉、淺藍按鈕）。
     🔴 官網沒有定義成功／警告／錯誤色，這三個是前台自己的，調成深底上看得清楚的亮度；
        ON AIR 粉只做裝飾小圓點，絕不拿來當錯誤色。 */
  color-scheme: dark;
  --bg: #06101f; --surface: #0b3570; --line: #2a5286; --ink: #ffffff;
  --muted: rgba(255,255,255,.62); --accent: #42b5ff; --accent-ink: #00346a;
  --mint: #91d5df; --onair: #ee7dc6;
  --ok: #8fdcae; --warn: #f0c86a; --danger: #ff9a8a;
  /* 作廢票券的標示：深底上仍然用飽和的紅底＋白字，維持一公尺外看得見 */
  --void: #b3392c; --void-ink: #fff;
  --radius: 10px;
}
* { box-sizing: border-box; }
/* 🔴 錨點跳轉要用滑的，不要瞬間跳。
      日曆換日期與「重新整理發票狀態」都是【整頁重載＋錨點】，
      瞬間跳到頁面中段，客人分不清楚是換了內容還是網頁壞了；
      滑過去的那一下讓人看得出「我從上面移到下面了」。
      會暈眩的使用者（系統設定要求減少動態）一律不滑。 */
html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }
/* 錨點目標上方留白，不然標題會緊貼螢幕頂緣、看起來像被切掉 */
:target { scroll-margin-top: 16px; }
body {
  margin: 0; color: var(--ink);
  /* 官網的夜空：頂端一抹深藍光，往下沉進近黑，底部再微微回藍 */
  background: var(--bg) linear-gradient(180deg, #0a2a5c 0, #050912 520px, #071631 100%);
  font: 16px/1.65 "Noto Sans TC", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  -webkit-text-size-adjust: 100%;
}
.wrap { max-width: 680px; margin: 0 auto; padding: 24px 20px 64px; }
header.site { border-bottom: 1px solid var(--line); background: rgba(5,9,18,.55); }
/* 站名前的 ON AIR 小圓點（官網的狀態粉）——純裝飾 */
header.site .crumbs > :first-child::before {
  content: ""; display: inline-block; width: 8px; height: 8px; border-radius: 50%;
  background: var(--onair); margin-right: 7px; vertical-align: middle; }
header.site .wrap { padding: 16px 20px; display: flex; justify-content: space-between; align-items: baseline; gap: 12px; flex-wrap: wrap; }
header.site a { color: inherit; text-decoration: none; font-weight: 600; }
header.site .sub { color: var(--muted); font-size: 14px; }
/* 🔴 活動名稱要看得出來是可以點回去的入口。站名本身太抽象——
   內測回饋（2026-09-02 游晏寧）：「要回去買票的日曆總覽只能點『好奇心創意 售票』，
   甚至不是成人展」。（站名已於 2026-09-03 改為「HaoTix」，這裡保留當時的原話。） */
header.site .crumbs { display: flex; align-items: baseline; gap: 8px; min-width: 0; }
header.site .crumbs .sep { color: var(--muted); font-weight: 400; }
header.site .event { color: var(--muted); font-weight: 500; font-size: 15px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
header.site .event:hover { color: inherit; text-decoration: underline; }
h1 { font-size: 24px; line-height: 1.3; margin: 0 0 4px; color: var(--accent); }
h2 { font-size: 18px; margin: 32px 0 12px; }
p { margin: 0 0 12px; }
a { color: var(--accent); }
.muted { color: var(--muted); }
.small { font-size: 14px; }
.card {
  background: var(--surface) linear-gradient(180deg, #0a2f63, #0c3d7c); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 16px; margin-bottom: 12px;
}
.row { display: flex; justify-content: space-between; align-items: center; gap: 16px; }
/* 單選一列。🔴 不要拿 .row 來排選項——那是 space-between，
   會把圓鈕推到最左、文字推到最右，中間一大片空白看起來像壞掉。 */
.pick { display: flex; align-items: center; gap: 10px; padding: 10px 12px; margin: 0 0 8px;
  border: 1px solid var(--line); border-radius: var(--radius); cursor: pointer; font-size: 15px; }
.pick input { width: auto; margin: 0; }
.pick:hover { border-color: var(--accent); }
/* 邀請頁：場次多的時候按日期收合。summary 要夠大，手機上是用手指點的 */
.daygroup { border: 1px solid var(--line); border-radius: 8px; margin-bottom: 8px; }
.daygroup > summary { padding: 12px 14px; cursor: pointer; font-weight: 600; }
.daygroup[open] > summary { border-bottom: 1px solid var(--line); }
.daygroup .pick { margin: 8px 10px; }
.day { font-weight: 600; margin: 24px 0 8px; padding-bottom: 6px; border-bottom: 1px solid var(--line); }
.seat { font-variant-numeric: tabular-nums; font-size: 14px; }
.seat.few { color: var(--warn); font-weight: 600; }
.seat.out { color: var(--muted); }
/* 愛心票那一行：比席位數小一階、灰一階——它是給需要的人看的補充，
   不該跟「還有幾席」搶同一個視覺重量。 */
.seat.sub { font-size: 12.5px; color: var(--muted); margin-top: 2px; }
/* 🔴 選擇場次頁先不顯示愛心票剩餘／未開放（Andy 2026-09-17 正式開賣：「先用 css hidden」）。
   只藏畫面、HTML 照印，要恢復刪掉這一行即可；選擇票種頁的愛心票狀態不受影響。 */
.seat.sub.special-left { display: none; }
.btn {
  display: inline-block; color: var(--accent-ink);
  /* 官網的主要按鈕：淺藍漸層＋深藍字 */
  background: #bfe6f2 linear-gradient(180deg, #dff4fb 0%, #bfe6f2 45%, #a8d9ea 75%, #5fb4d6 100%);
  border: 0; border-radius: var(--radius); padding: 11px 20px;
  font: inherit; font-weight: 600; cursor: pointer; text-decoration: none;
}
.btn:disabled, .btn[aria-disabled="true"] {
  background: var(--line); color: var(--muted); cursor: not-allowed;
}
.btn.block { display: block; width: 100%; text-align: center; }
dialog.leave { border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface); color: var(--ink);
  padding: 20px; max-width: 360px; width: calc(100% - 32px); }
dialog.leave::backdrop { background: rgba(0,0,0,.45); }
dialog.leave .actions { margin: 16px 0 0; display: grid; gap: 8px; }
.btn.ghost { background: transparent; color: var(--accent); border: 1px solid var(--line); }
/* 場次列表售完那一格：平常顯示「候補通知」，「已售完」那顆收著 */
.btn.wl-soldout { display: none; }
/* 🔴 候補暫停（實驗，Boky／Andy 2026-10-14，Slack 1791948527.533299）：很多人先點售完場次、又開不了場，
   先關掉候補、把人導去有票的場次看效果。只藏場次列表的按鈕，候補頁與後台都照舊；
   要恢復候補，刪掉底下這兩行即可。 */
.btn.wl-entry { display: none; }
.btn.wl-soldout { display: inline-block; }
label { display: block; font-weight: 600; font-size: 14px; margin: 16px 0 4px; }
label .req { color: var(--danger); font-weight: 400; }
input, select {
  width: 100%; padding: 10px 12px; font: inherit;
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--bg); color: var(--ink);
}
.hint { font-size: 13px; color: var(--muted); margin-top: 4px; }
table.tiers { width: 100%; border-collapse: collapse; font-size: 14px; }
table.tiers td { padding: 6px 0; border-bottom: 1px solid var(--line); }
table.tiers td:last-child { text-align: right; font-variant-numeric: tabular-nums; }
table.tiers tr:last-child td { border-bottom: 0; }
/* ── 日曆 ── */
.cal { background: var(--surface) linear-gradient(180deg, #0a2f63, #0c3d7c); border: 1px solid var(--line); border-radius: var(--radius); padding: 14px; margin-bottom: 20px; }
.cal .head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; }
.cal .head .m { font-weight: 700; font-size: 17px; font-variant-numeric: tabular-nums; }
.cal .head a, .cal .head span.off { display: inline-flex; align-items: center; justify-content: center;
  width: 38px; height: 38px; border-radius: 9px; border: 1px solid var(--line);
  text-decoration: none; color: var(--accent); font-weight: 700; }
.cal .head span.off { color: var(--line); border-color: var(--line); }
/* 🔴 minmax(0, 1fr) 不是 1fr：1fr 的最小值是內容寬度，手機字級調大時格子會把欄撐開、
   六那一欄跑出月曆外框（Andy 2026-09-17 手機截圖）。欄寬固定平分，格子自己縮。 */
.cal .grid { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 4px; }
.cal .wd { text-align: center; font-size: 12px; color: var(--muted); padding: 4px 0 6px; }
.cal .d { position: relative; aspect-ratio: 1; min-width: 0; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 5px; padding: 6px 0; line-height: 1; border-radius: 9px;
  font-variant-numeric: tabular-nums; font-size: 15px; text-decoration: none; color: var(--ink); }
.cal .d.empty { color: var(--line); }
.cal .d.none { color: var(--muted); }
.cal a.d { border: 1px solid var(--line); }
.cal a.d:hover { border-color: var(--accent); }
.cal a.d.on { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); font-weight: 700; }
/* 🔴 有票＝實心品牌色；沒票＝空心淡灰。
   原本想用白點，但淺色底幾乎是白的，白點會消失。 */
.cal .dot { width: 7px; height: 7px; border-radius: 50%; }
.cal .dot.has { background: var(--accent); }
.cal .dot.out { background: transparent; border: 1.5px solid var(--line); }
/* 🔴 格子上下固定留 6px（Andy 2026-09-17：手機字級調大時點點貼著下框）。
   aspect-ratio 只是偏好：放得下時維持正方形，字很大時格子自己變高，不會貼框或壓字。 */
.cal a.d.on .dot.has { background: var(--accent-ink); }
.cal a.d.on .dot.out { border-color: var(--accent-ink); }
.cal .legend { display: flex; gap: 16px; margin-top: 12px; font-size: 13px; color: var(--muted); }
.cal .legend span { display: inline-flex; align-items: center; gap: 6px; }

.notice { border-left: 3px solid var(--accent); padding: 10px 14px; background: var(--surface); border-radius: 0 var(--radius) var(--radius) 0; margin-bottom: 16px; }
.notice.err { border-left-color: var(--danger); background: color-mix(in srgb, var(--danger) 10%, var(--surface)); font-weight: 600; }
.field-err { color: var(--danger); font-weight: 600; margin: 4px 0 8px; font-size: 14px; }
.notice.ok { border-left-color: var(--ok); }
/* 🔴 公告裡的圖片一定要鎖寬度。後台上傳的可能是一張 2000px 的照片，
   沒有這一行就會把整個頁面撐破——而且是在颱風當天、手機上。 */
.notice img { max-width: 100%; height: auto; display: block; margin: 8px 0; border-radius: var(--radius); }
/* 票種的詳細說明：沒被選中的票種先收起來。
 *
 * 🔴 為什麼要收：愛心票有三條又長又重要的規則，全部攤開會把「張數」與
 *    「前往填資料」推到手機畫面外，客人得捲很久才找得到下一步。
 *    選中了才展開，需要讀的人一定讀得到，不需要的人不必被擋路。
 *
 * 🔴 為什麼用純 CSS 不用 JS：這一頁的原則是「沒有 JavaScript 也要能買完」
 *    （decisions/0017）。:has() 不支援時整條選擇器失效，說明就維持全部展開——
 *    退化成現在的行為，不會有人看不到規則。
 *
 * 🔴 「現場需查驗證明正本」那一行【不收】，它留在卡片上永遠看得見：
 *    那是決定要不要買這張票的前提，收起來等於把門檻藏起來。
 */
.typenote { display: block; margin-top: 10px; }
.card:not(:has(input[type="radio"]:checked)) .typenote { display: none; }

/* 🔴 金額【絕不可】被擠成兩行。
      它是 flex 的子項，預設可以被壓縮；左邊的說明文字一長（例如愛心票多了
      「現場需查驗證明正本」），手機上就會把「NT$」和數字拆到上下兩行，
      看起來像壞掉，而金額正是這一頁最需要一眼看懂的東西。
      nowrap 擋掉斷行，flex-shrink:0 擋掉被壓窄。 */
.total {
  font-size: 20px; font-weight: 700; font-variant-numeric: tabular-nums;
  white-space: nowrap; flex-shrink: 0;
}
.countdown { font-variant-numeric: tabular-nums; font-weight: 600; }
.qr { background: #fff; padding: 12px; border-radius: var(--radius); display: inline-block; }
.qr svg { display: block; width: 190px; height: 190px; }
.ticket { text-align: center; border: 1px solid var(--line); border-radius: var(--radius); padding: 20px; background: var(--surface) linear-gradient(180deg, #0a2f63, #0c3d7c); margin-bottom: 12px; }
.ticket .no { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 13px; color: var(--muted); margin-top: 10px; }
/* 票券卡上的門口提醒。要在截圖裡看得見，所以用警示色而不是灰字；
   但仍小於場次資訊——截圖的主角是 QR 與「這是哪一場」。 */
/* 手機條碼／統編是拿來【核對】的，不是拿來讀的。
   等寬字 ＋ 拉開字距，才有機會讓人看出自己少打一個字母。 */
.carrier { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; letter-spacing: .06em; }
.ticket .verify { margin-top: 10px; font-size: 13.5px; line-height: 1.5; color: var(--warn); }
/*
 * 作廢票券的標示（已退票／已取消／已失效）。
 *
 * 🔴 這一段要【很大聲】，因為票券是靠截圖流通的：
 *    退票之後那張 QR 的截圖還躺在客人（或別人）的相簿裡，看起來跟有效票一模一樣。
 *    原本只在票號下面補一行灰色小字，在昏暗的門口、隔著一支手機根本看不到，
 *    而工讀生每場只有 10 分鐘、面對的是一直往前推的隊伍。
 *    真正擋住入場的是掃描時的資料庫檢查（那一層不依賴這裡），
 *    但畫面要讓「這張不能用」在一公尺外就看得出來，爭議才不會發生在門口。
 *
 * 三件事一起做，任何一件單獨都不夠：
 *   ① QR 上壓一條斜的紅色標記——截圖也帶得走
 *   ② QR 本身去色＋壓暗，一眼就知道它不是活的
 *   ③ 卡片頂端一條紅底橫幅寫明狀態
 */
.ticket.void { border-color: var(--void); }
.ticket .voidbar {
  background: var(--void); color: var(--void-ink); font-size: 19px; font-weight: 800;
  letter-spacing: .04em; border-radius: var(--radius); padding: 10px 12px; margin-bottom: 14px;
}
.ticket .voidbar .sub { display: block; font-size: 13px; font-weight: 500; opacity: .95; margin-top: 2px; }
/* QR 與斜標記要疊在一起，所以外面包一層定位容器 */
.ticket .qrwrap { position: relative; display: inline-block; }
.ticket.void .qr svg { filter: grayscale(1) contrast(.7); opacity: .45; }
.ticket .stamp {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%) rotate(-24deg);
  background: var(--void); color: var(--void-ink); font-size: 21px; font-weight: 800;
  letter-spacing: .08em; box-shadow: 0 2px 10px rgba(0,0,0,.35);
  padding: 7px 16px; border-radius: 6px; white-space: nowrap;
  /* 🔴 不吃點擊，免得擋住客人長按存圖 */
  pointer-events: none;
}
.steps { display: flex; gap: 6px; font-size: 13px; color: var(--muted); margin-bottom: 20px; flex-wrap: wrap; }
.steps span.on { color: var(--accent); font-weight: 600; }
/* 🔴 走過的步驟要看得出來可以點回去。內部測試回饋（2026-09-02 游晏寧）：
   步驟條是客人最直覺會去點的回頭路，比另外加一顆按鈕自然。 */
.steps a { color: var(--muted); text-decoration: underline; text-underline-offset: 3px;
  text-decoration-color: var(--line); }
.steps a:hover { color: var(--ink); text-decoration-color: currentColor; }
footer.site { border-top: 1px solid var(--line); margin-top: 48px; padding: 20px 0; font-size: 13px; color: var(--muted); }
footer.site .footer-notes { color: var(--ink); font-size: 14px; line-height: 1.7; margin: 0 0 16px; padding: 0 0 16px; border-bottom: 1px solid var(--line); }
footer.site .footer-notes img { max-width: 100%; height: auto; }
/* F-54 選日期頁底部的購票須知；F-55 段落選單（公告與月曆之間，不跟著捲） */
.page-notes { margin-top: 40px; padding-top: 20px; border-top: 1px solid var(--line); font-size: 15px; line-height: 1.75; }
.page-notes h3 { font-size: 16px; margin: 24px 0 8px; scroll-margin-top: 16px; }
.page-notes img { max-width: 100%; height: auto; }
.notes-menu { display: flex; flex-wrap: wrap; gap: 8px; margin: 12px 0 20px; }
.notes-menu a { display: inline-block; padding: 6px 12px; border: 1px solid var(--line); border-radius: 999px; font-size: 14px; text-decoration: none; color: var(--ink); background: var(--surface); }


#hx-progress { position: fixed; top: 0; left: 0; height: 3px; width: 0; background: var(--accent, #8a3324);
  z-index: 9999; opacity: 0; pointer-events: none; transition: width 8s cubic-bezier(.1,.7,.2,1), opacity .2s; }
#hx-progress.on { opacity: 1; width: 90%; }
@media (prefers-reduced-motion: reduce) { #hx-progress { transition: none; } #hx-progress.on { width: 100%; } }
