/* ============================================================================
   Pactroll marketing site — shared design system.

   A gacha-native blocker. The look follows the app 1:1: the same single Palette
   (frontend/src/constants/theme.ts, 放鬆藍 + cool off-white), the same Soft
   radii / shadows, the same typeface (Plus Jakarta Sans, self-hosted — no
   third-party font request, on-brand for a privacy-first product) and the
   hand-built vector wordmark from design/brand/ (assets/brand/*.svg).

   The home page is the "Manifesto" design (owner 2026-09-29): a full-bleed
   brand-blue field — the same brand screen the app's onboarding uses — with
   editorial type and a short creed that lights up word by word.

   The app is light-only, so this site commits to a single light look and
   paints backgrounds explicitly.

   Loaded by every page. Page-specific markup lives in each index.html;
   everything visual lives here.
   ============================================================================ */

/* ── Reset ────────────────────────────────────────────────────────────────── */
* { box-sizing: border-box; margin: 0; padding: 0; }
html { color-scheme: light; scroll-behavior: smooth; -webkit-text-size-adjust: 100%; }

/* ── Typeface: Plus Jakarta Sans, the face the app ships (OFL, see
   assets/fonts/PlusJakartaSans-OFL.txt). Only the weights the site uses. ── */
@font-face { font-family: 'Plus Jakarta Sans'; src: url('/assets/fonts/PlusJakartaSans_400Regular.ttf') format('truetype'); font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: 'Plus Jakarta Sans'; src: url('/assets/fonts/PlusJakartaSans_600SemiBold.ttf') format('truetype'); font-weight: 600; font-style: normal; font-display: swap; }
@font-face { font-family: 'Plus Jakarta Sans'; src: url('/assets/fonts/PlusJakartaSans_700Bold.ttf') format('truetype'); font-weight: 700; font-style: normal; font-display: swap; }
@font-face { font-family: 'Plus Jakarta Sans'; src: url('/assets/fonts/PlusJakartaSans_800ExtraBold.ttf') format('truetype'); font-weight: 800; font-style: normal; font-display: swap; }

/* ── Tokens: sourced 1:1 from the app's single Palette + Soft design tokens. ── */
:root {
  --surface: #FFFFFF;   /* card fill */
  --bg:      #F6F8FB;   /* page ground — cool off-white */
  --sunken:  #EFF3F8;   /* inset block */
  --ink:     #1B2432;   /* primary text — deep blue-ink, not pure black */
  --ink2:    #5A6576;   /* secondary text (AA on white and on bg) */
  --muted:   #8C97A8;   /* decoration only — never text that must be read */
  --faint:   #B7BCC8;   /* weakest / disabled */
  --line:    #E4E9F0;

  /* Brand blue (放鬆藍) — the brand field, links, accents. */
  --primary:      #3F72A8;
  --primary-soft: #EAF1F9;   /* tinted fill */
  --primary-line: #C6D8EC;   /* tinted border */
  --on-primary:   #FFFFFF;
  --on-brand-fill: rgba(255, 255, 255, .16); /* translucent white on the brand field (app: onBrandFill) */

  /* Calm green / soft red — kept in step with the app, used sparingly. */
  --success: #2F7D57;
  --danger:  #C23B3B;

  /* Soft radii (app Radii). */
  --r-sm: 10px;
  --r-md: 16px;
  --r-lg: 24px;
  --r-pill: 999px;

  /* Soft shadows — alphas of `ink` (27,36,50), matching theme.ts Shadows. */
  --shadow-soft: 0 1px 2px rgba(27, 36, 50, .04), 0 6px 20px rgba(27, 36, 50, .06);
  --shadow-pop:  0 12px 30px rgba(27, 36, 50, .14);

  /* The brand screen's sheen: the top-left keeps the pure blue, the bottom-right
     darkens with ink (theme.ts Gradients.brandSheen). White text stays ≥ 5:1. */
  --brand-sheen: linear-gradient(to bottom right, rgba(27, 36, 50, 0) 0%, rgba(27, 36, 50, 0) 35%, rgba(27, 36, 50, .18) 100%);

  /* The one translucent material (the header bar) — surface at 68% + blur. */
  --glass:      rgba(255, 255, 255, .68);
  --glass-blur: blur(24px) saturate(180%);

  --font-sans: 'Plus Jakarta Sans', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --ease-out: cubic-bezier(.23, 1, .32, 1);

  --wrap: 1180px;   /* page column (header, home, footer) */
  --measure: 760px; /* reading column for docs */
  --gutter: clamp(16px, 5vw, 56px);
}

/* ── Base ─────────────────────────────────────────────────────────────────── */
body {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-sans);
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

a { color: inherit; }
img { display: block; max-width: 100%; }

/* <main> is the growing flex column between the header and footer, so the footer
   sticks to the bottom. */
main { flex: 1 1 auto; display: flex; flex-direction: column; }

/* Page column shared by header, home and footer. */
.container {
  width: 100%;
  max-width: var(--wrap);
  margin: 0 auto;
  padding-left: var(--gutter);
  padding-right: var(--gutter);
}

/* The vector wordmark (assets/brand/*.svg). Never narrower than 120px — below
   that the pause bars inside the o blur (design/brand/README §4). */
.wordmark { width: 124px; height: auto; }

/* Display headlines: Plus Jakarta's period carries wide side-bearings — tuck it
   in at large sizes. */
.pd { margin-left: -.07em; }

/* ── Site header (injected by layout.js on doc pages): a slim translucent bar
   carrying the wordmark — a single glass layer with content scrolling under it.
   Pinned to the top, hidden on scroll-down / revealed on scroll-up (headroom,
   see layout.js). The home page has no bar: its header lives in the brand field. */
:root { --hdr-h: 64px; }
#site-header:empty { display: none; }        /* no-JS: the empty placeholder collapses */
body { padding-top: var(--hdr-h); }          /* leave room for the fixed bar */
body.page-home { padding-top: 0; }

.site-header {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 50;
  background: var(--glass);
  backdrop-filter: var(--glass-blur);
  -webkit-backdrop-filter: var(--glass-blur);
  border-bottom: 1px solid var(--line);
  transition: transform .28s var(--ease-out), box-shadow .2s var(--ease-out);
  will-change: transform;
}
.site-header.headroom--unpinned { transform: translateY(-100%); }
.site-header.headroom--pinned { transform: translateY(0); }
.site-header:not(.headroom--top) { box-shadow: var(--shadow-soft); }

.header-inner {
  display: flex;
  align-items: center;
  gap: 16px;
  height: var(--hdr-h);
}
.site-header .brand { display: block; flex: 0 0 auto; border-radius: 6px; }
.site-header .brand:focus-visible { outline: 2px solid var(--primary); outline-offset: 4px; }

@media (max-width: 820px) {
  :root { --hdr-h: 56px; }
}
@media (prefers-reduced-motion: reduce) {
  .site-header { transition: none; }
}
/* Solid chrome when the viewer asks for less transparency. */
@media (prefers-reduced-transparency: reduce) {
  .site-header { background: var(--surface); backdrop-filter: none; -webkit-backdrop-filter: none; }
}

/* ── "Coming soon" pill on the brand field. ─────────────────────────────── */
.pill {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 9px 16px;
  border-radius: var(--r-pill);
  background: var(--on-brand-fill);
  color: var(--on-primary);
  font-size: 14px;
  font-weight: 600;
  line-height: 1.2;
}
.pill .dot { width: 7px; height: 7px; border-radius: 50%; background: var(--on-primary); flex: 0 0 auto; }

/* ══ Home — Manifesto ════════════════════════════════════════════════════════ */

/* Brand field: hero + closing band. */
.brand-field {
  position: relative;
  overflow: hidden;
  background: var(--primary);
  color: var(--on-primary);
}
.brand-field::before {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--brand-sheen);
  pointer-events: none;
}

.m-hero { min-height: min(100vh, 920px); display: flex; flex-direction: column; }

/* The pause-o, very large and faint, cropped by the right edge. */
.m-mark {
  position: absolute;
  top: 50%;
  right: max(-22vw, -300px);
  width: clamp(420px, 60vw, 820px);
  aspect-ratio: 1;
  margin-top: calc(clamp(420px, 60vw, 820px) / -2);
  pointer-events: none;
}
.m-mark svg { display: block; width: 100%; height: 100%; opacity: .1; animation: m-mark 900ms var(--ease-out) 120ms backwards; }
.m-mark .sym-ring, .m-mark .sym-bar { fill: var(--on-primary); }
.m-mark .sym-bar { transform-box: fill-box; transform-origin: center; animation: press 520ms var(--ease-out) 620ms backwards; }
.m-mark .sym-bar2 { animation-delay: 690ms; }

.m-top {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding-top: 22px;
  padding-bottom: 22px;
}
.m-top a { display: block; border-radius: 6px; }
.m-top a:focus-visible,
.m-down:focus-visible { outline: 2px solid var(--on-primary); outline-offset: 4px; }

.m-body {
  position: relative;
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  padding-top: 48px;
  padding-bottom: clamp(48px, 9vh, 96px);
}
.m-eyebrow { font-size: 13px; font-weight: 700; letter-spacing: .16em; text-transform: uppercase; }
.m-h1 {
  margin-top: 18px;
  font-size: clamp(48px, 10.5vw, 136px);
  line-height: .98;
  font-weight: 800;
  letter-spacing: -.045em;
}
/* Each line rises out of its own mask. */
.m-h1 .ln { display: block; overflow: hidden; padding-bottom: .07em; margin-bottom: -.07em; }
.m-h1 .ln > span { display: block; animation: m-up 800ms var(--ease-out) backwards; }
.m-lede { margin-top: 28px; max-width: 30em; font-size: clamp(17px, 1.8vw, 20px); line-height: 1.55; text-wrap: pretty; }
.m-down {
  margin-top: 32px;
  align-self: flex-start;
  display: inline-flex;
  align-items: center;
  gap: 12px;
  font-size: 15px;
  font-weight: 600;
  text-decoration: none;
  border-radius: var(--r-pill);
}
.m-down .arr {
  width: 38px; height: 38px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: var(--on-brand-fill);
  transition: transform 200ms var(--ease-out);
}
.m-down .arr svg { width: 16px; height: 16px; }
@media (hover: hover) and (pointer: fine) { .m-down:hover .arr { transform: translateY(3px); } }
.m-down:active .arr { transform: scale(.94); }

/* The creed. */
.m-list { padding-top: clamp(72px, 13vh, 144px); padding-bottom: clamp(56px, 10vh, 112px); }
.m-kicker { font-size: 13px; font-weight: 700; letter-spacing: .16em; text-transform: uppercase; color: var(--primary); }
.m-items { list-style: none; margin-top: 36px; }
.m-item {
  display: grid;
  grid-template-columns: 88px minmax(0, 1fr);
  gap: 8px 24px;
  padding: 36px 0;
  border-top: 1px solid var(--line);
}
.m-n { padding-top: .6em; font-size: 15px; font-weight: 700; color: var(--primary); font-variant-numeric: tabular-nums; }
.m-say {
  max-width: 21em;
  font-size: clamp(24px, 3.3vw, 42px);
  line-height: 1.22;
  font-weight: 600;
  letter-spacing: -.02em;
  color: var(--ink2);
  text-wrap: pretty;
}
.m-say b { font-weight: 800; color: var(--ink); }
/* home.js splits each line into words; they start faint and light up in reading
   order once the line scrolls into view. Without JS the text is simply shown. */
.m-w { opacity: .14; transition: opacity 420ms var(--ease-out); }
.m-item.is-in .m-w { opacity: 1; }

/* Closing band. */
.m-close-in {
  position: relative;
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: 28px;
  padding-top: clamp(64px, 12vh, 128px);
  padding-bottom: clamp(64px, 12vh, 128px);
}
.m-close-l { font-size: clamp(36px, 5.6vw, 76px); line-height: 1.02; font-weight: 800; letter-spacing: -.04em; }
.m-close-l > span { display: block; }

@media (max-width: 640px) {
  .m-item { grid-template-columns: minmax(0, 1fr); padding: 28px 0; }
  .m-n { padding-top: 0; }
  .m-top .pill { font-size: 13px; padding: 8px 12px; }
}

/* ══ Legal / doc pages ═══════════════════════════════════════════════════════ */
.doc { flex: 1 1 auto; padding: 40px 0 72px; }
/* Docs read in a narrower, centered measure. Masthead and body share this
   column so the wordmark aligns with the text's left edge. */
.doc-wrap {
  max-width: var(--measure);
  margin: 0 auto;
  padding-left: var(--gutter);
  padding-right: var(--gutter);
}
.doc .masthead { margin-bottom: 48px; }
/* The masthead is the no-JS brand line; once layout.js fills the header bar
   with the wordmark, a second one right under it is just repetition. */
#site-header:not(:empty) ~ main .masthead { display: none; }
.doc .masthead a { display: inline-block; border-radius: 6px; }
.doc .masthead a:focus-visible { outline: 2px solid var(--primary); outline-offset: 4px; }
.doc h1 {
  font-weight: 800;
  font-size: clamp(34px, 5.4vw, 48px);
  letter-spacing: -.035em;
  line-height: 1.08;
  text-wrap: balance;
}
.doc .meta { color: var(--ink2); font-size: 14px; margin-top: 12px; }
.doc .note {
  margin-top: 24px;
  padding: 14px 18px;
  background: var(--primary-soft);
  border-radius: var(--r-md);
  color: var(--ink2);
  font-size: 14px;
  line-height: 1.55;
}
.doc h2 {
  font-size: 20px;
  font-weight: 700;
  color: var(--ink);
  margin-top: 40px;
  margin-bottom: 12px;
  letter-spacing: -.01em;
}
.doc p, .doc li { color: var(--ink2); font-size: 16px; line-height: 1.75; }
.doc p { margin-top: 12px; }
.doc ul { margin-top: 12px; padding-left: 22px; }
.doc li { margin-top: 8px; }
.doc a:not(.masthead a) {
  color: var(--primary);
  text-decoration: underline;
  text-decoration-color: var(--primary-line);
  text-underline-offset: 3px;
}
.doc a:not(.masthead a):hover { text-decoration-color: var(--primary); }
.doc strong { color: var(--ink); font-weight: 700; }

/* ══ Footer (injected by layout.js) — quiet chrome ═══════════════════════════ */
.site-footer {
  padding: 28px 0 40px;
  border-top: 1px solid var(--line);
  color: var(--ink2);
  font-size: 13px;
  line-height: 1.6;
}
.footer-links { display: flex; flex-wrap: wrap; gap: 4px 22px; }
.site-footer a {
  color: var(--ink2);
  font-weight: 600;
  text-decoration: none;
  border-radius: 4px;
  transition: color .15s var(--ease-out);
}
.site-footer a:hover { color: var(--primary); }
.site-footer a:focus-visible { outline: 2px solid var(--primary); outline-offset: 3px; }
.footer-fine { margin-top: 8px; }

/* ── Motion ───────────────────────────────────────────────────────────────── */
@keyframes rise { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }
@keyframes press { from { transform: scaleY(.25); } to { transform: none; } }
@keyframes m-up { from { transform: translateY(105%); } to { transform: none; } }
@keyframes m-mark { from { opacity: 0; transform: scale(.96); } to { opacity: .1; transform: none; } }
/* One restrained load reveal; delays are set per element in the markup. */
.a-rise { animation: rise 560ms var(--ease-out) backwards; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .a-rise, .m-h1 .ln > span, .m-mark svg, .m-mark .sym-bar { animation: none; }
  .m-w, .m-down .arr, .site-footer a { transition: none; }
}
