:root { color-scheme: light dark; --shell: #2a1d4d; --ink: #f3eefc; --pop: #b9f36a; --muted: #b8a9d9; }
/* Each language on its own system stack for body text — a Japanese page on
   PingFang TC would draw its kanji in Taiwanese forms — and its own heading
   face (tools/site_assets.py subsets each to the headings of its pages; a
   page downloads only the faces its stack names). */
:root {
  --body: -apple-system, "PingFang TC", "Noto Sans TC", "Microsoft JhengHei", system-ui, sans-serif;
  --display: "PEITE Latin", "PEITE Han", -apple-system, "PingFang TC", "Noto Sans TC", system-ui, sans-serif;
}
:root:lang(ja) {
  --body: -apple-system, "Hiragino Sans", "Hiragino Kaku Gothic ProN", "Noto Sans JP", "Yu Gothic", Meiryo, system-ui, sans-serif;
  --display: "PEITE Latin", "PEITE JP", -apple-system, "Hiragino Sans", "Noto Sans JP", system-ui, sans-serif;
}
:root:lang(ko) {
  --body: -apple-system, "Apple SD Gothic Neo", "Noto Sans KR", "Malgun Gothic", system-ui, sans-serif;
  --display: "PEITE Latin", "PEITE KR", -apple-system, "Apple SD Gothic Neo", "Noto Sans KR", system-ui, sans-serif;
}
/* Korean breaks between words, never inside one; Japanese headlines are
   written in lines short enough for a phone (Safari has no auto-phrase). */
:root:lang(ko) { word-break: keep-all; overflow-wrap: anywhere; }
.home:lang(ja) h1 { font-size: clamp(2rem, 6.6vw, 4.2rem); }
* { box-sizing: border-box; }
body { margin: 0; background: var(--shell); color: var(--ink); font: 17px/1.7 var(--body); }
main { max-width: 42rem; margin: 0 auto; padding: 4rem 1.25rem 6rem; }
h1 { font-size: 2.4rem; margin: 0 0 .25rem; letter-spacing: .02em; }
h2 { font-size: 1.25rem; margin: 2.5rem 0 .5rem; color: var(--pop); }
.latin { color: var(--pop); font-weight: 600; }
.lede { font-size: 1.4rem; margin: 0 0 1.5rem; }
.en, .soon, .meta { color: var(--muted); }
nav { display: flex; flex-wrap: wrap; gap: 1rem 1.5rem; margin-top: 3rem; }
a { color: var(--pop); }
ul { padding-left: 1.2rem; }
li { margin: .3rem 0; }
.draft { border: 1px solid var(--muted); border-radius: .5rem; padding: .6rem .9rem; color: var(--muted); font-size: .95rem; }
main [id] { scroll-margin-top: 84px; }
blockquote { margin: 1rem 0; padding: .1rem 0 .1rem 1rem; border-left: 2px solid var(--muted); color: var(--muted); font-size: .95rem; }

@font-face { font-family: "PEITE Latin"; src: url(assets/fredoka-b.woff2) format("woff2"); font-weight: 700; font-display: swap; }
@font-face { font-family: "PEITE Han"; src: url(assets/gensen-b.woff2) format("woff2"); font-weight: 700; font-display: swap; }
@font-face { font-family: "PEITE JP"; src: url(assets/notojp-b.woff2) format("woff2"); font-weight: 700; font-display: swap; }
@font-face { font-family: "PEITE KR"; src: url(assets/notokr-b.woff2) format("woff2"); font-weight: 700; font-display: swap; }

.home, .top, .auth {
  --shell: #3D2470; --hud: #2E1859; --edge: #1F0F42; --ink: #F6F0FF;
  --panel: #F6F0FF; --panel-ink: #3D2470; --muted: #7C6BA5; --track: #E0D5F2;
  --pop: #B8F26A; --pop-ink: #243D0A; --glow: #FF9CE0; --label: #B9A7DE;
  --ok: #1F7A4D; --ok-surface: #E2F4EA; --no: #B3261E;
}
.home {
  --px: 2;                                 /* one sprite pixel, in CSS px */
  background: var(--shell);
  color: var(--ink);
  font: 17px/1.75 var(--body);
  -webkit-text-size-adjust: 100%;
}
@media (min-width: 700px) { .home { --px: 3; } }
@media (min-width: 1000px) { .home { --px: 4; } }

.home h1, .home h2, .home h3, .home nav, .home summary, .home .display, .home .brand,
.home .eyebrow, .home .num, .home .key, .home .card-top, .home .facts, .home .chips,
.top .brand, .langs { font-family: var(--display); font-weight: 700; }

.home main { max-width: none; margin: 0; padding: 0; }
.home section[id] { scroll-margin-top: 76px; }
.home em { font-style: normal; color: var(--pop); }
.home a:focus-visible, .home summary:focus-visible { outline: 3px solid var(--glow); outline-offset: 3px; border-radius: 6px; }
.home p { margin: 0 0 1rem; }
.wrap { max-width: 1120px; margin: 0 auto; padding: 0 16px; }
.wrap.narrow { max-width: 760px; }
@media (min-width: 700px) { .wrap { padding: 0 32px; } }

/* A pet: 1× GIF, scaled by a whole number so every sprite pixel is square. */
.pet { display: block; line-height: 0; }
.pet img { display: block; width: calc(var(--w) * var(--px) * 1px); height: auto; image-rendering: pixelated; image-rendering: crisp-edges; }
/* --w is the GIF's width in sprite pixels, which its width attribute already
   says: read from there, because the CSP allows no style attribute. A pet of a
   new width needs its line (site_assets.py --check says so). */
.pet img[width="36"] { --w: 36; }
.pet img[width="40"] { --w: 40; }
.pet img[width="46"] { --w: 46; }
.pet img[width="48"] { --w: 48; }
.pet img[width="56"] { --w: 56; }

/* ---- header: the app's title bar, pink rule and all ---- */
.top { position: sticky; top: 0; z-index: 5; background: var(--hud); border-bottom: 3px solid var(--glow); }
.top-row { display: flex; align-items: center; gap: 28px; height: 64px; }
.brand { display: inline-flex; align-items: center; gap: 10px; color: var(--ink); text-decoration: none; font-size: 1.3rem; line-height: 1.2; letter-spacing: .04em; }
.brand img { border: 2px solid var(--edge); border-radius: 10px; }
.brand .latin { font-weight: 700; }
.top .brand { margin-right: auto; }
.home .top nav { display: flex; gap: 28px; margin: 0; }
.top nav a { color: var(--ink); text-decoration: none; line-height: 1.2; }
.top nav a:hover { color: var(--pop); }
/* The language key: the current language's own name on a pixel key with a
   globe, and under it the four, each a real link to this page in that
   language (or that language's home, where the page has none) — a <details>,
   so it opens with no script and from the keyboard. The one picked is the
   lime key, as a chosen chip is in the app. site.js shuts it on Escape or a
   tap outside and remembers the pick for the root's redirect only. */
.langs { position: relative; flex: none; }
.langs > summary { display: flex; align-items: center; gap: 7px; padding: 6px 10px; color: var(--ink); background: var(--shell); border: 2px solid var(--edge); border-radius: 10px; box-shadow: 0 3px 0 var(--edge); font-size: 1rem; line-height: 1.3; cursor: pointer; list-style: none; -webkit-user-select: none; user-select: none; -webkit-tap-highlight-color: transparent; }
.langs > summary::-webkit-details-marker { display: none; }
.langs > summary:hover { color: var(--pop); }
.langs svg { display: block; flex: none; }
.langs .globe { width: 18px; height: 18px; }
.langs .caret { width: 10px; height: 6px; }
.langs[open] .caret { transform: scaleY(-1); }
.langs ul { position: absolute; top: calc(100% + 12px); right: 0; z-index: 6; display: grid; gap: 6px; width: max-content; min-width: 100%; margin: 0; padding: 8px; list-style: none; background: var(--panel); border: 3px solid var(--edge); border-radius: 14px; box-shadow: 0 5px 0 var(--edge); }
.langs li { margin: 0; }
.langs a { display: block; padding: 7px 14px; color: var(--panel-ink); text-decoration: none; font-size: 1rem; line-height: 1.3; border: 2px solid transparent; border-radius: 10px; }
.langs a:hover { background: var(--track); }
.langs a[aria-current] { color: var(--pop-ink); background: var(--pop); border-color: var(--edge); box-shadow: 0 3px 0 var(--edge); }
.langs summary:focus-visible, .langs a:focus-visible { outline: 3px solid var(--glow); outline-offset: 3px; }
/* The sound switch, put in by site.js after the first tap: a 10×8 pixel speaker. */
.speaker { display: inline-grid; place-items: center; width: 42px; height: 34px; margin-right: -16px; padding: 0; color: var(--ink); background: var(--shell); border: 2px solid var(--edge); border-radius: 10px; box-shadow: 0 3px 0 var(--edge); cursor: pointer; }
.speaker svg { display: block; width: 20px; height: 16px; }
.speaker[aria-pressed="false"] { color: var(--label); }
.speaker:hover { color: var(--pop); }
.speaker:focus-visible { outline: 3px solid var(--glow); outline-offset: 3px; }
@media (max-width: 699px) {
  .top-row { gap: 10px; }
  .home .top nav { display: none; }
  .speaker { margin: 0; }
}

/* ---- hero: the pets, alive, on a floor ---- */
.hero { padding: 56px 0 0; text-align: center; }
.eyebrow { color: var(--label); letter-spacing: .12em; font-size: .95rem; line-height: 1.2; }
.home h1 { margin: 0; font-size: clamp(2.3rem, 7.2vw, 4.4rem); line-height: 1.22; letter-spacing: .03em; text-wrap: balance; }
/* One sentence, two clauses: from a tablet up, the line wraps between them
   when it has to, never inside one. On a phone a clause can be wider than the
   screen at the smallest heading size, so there it wraps where it must. */
@media (min-width: 700px) { .home h1 .cl { display: inline-block; } }
.home h1 em { white-space: nowrap; }   /* the lime word never splits across lines */
.home .lede { max-width: 30em; margin: 22px auto 28px; font-size: clamp(1.05rem, 2.2vw, 1.25rem); }
.cta { display: flex; flex-direction: column; align-items: center; gap: 12px; }
.badge { display: inline-block; line-height: 0; border-radius: 10px; }
.badge img { height: 50px; width: auto; }
/* /i/<code>, an invite link opened without the app (site/i/index.html): the
   icon, the name, the badge and one line under it, in the middle of the
   phone. */
.invite { min-height: 100vh; min-height: 100dvh; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 18px; padding: 24px 16px; text-align: center; }
.invite h1 { margin: 0; line-height: 1.3; }
.invite-icon { border: 2px solid #1F0F42; border-radius: 22px; }
.invite p { margin: 0; max-width: 22em; }
/* With the app, in another app's browser: the link, and the key that copies
   it (lang.js) — hidden until the page knows the link. */
.invite .have { display: flex; flex-direction: column; align-items: center; gap: 12px; }
.invite .have[hidden] { display: none; }
.invite .link { padding: 8px 12px; color: var(--ink); background: #2E1859; border: 2px solid #1F0F42; border-radius: 10px; font-size: .95rem; overflow-wrap: anywhere; -webkit-user-select: all; user-select: all; }
.invite .copy { padding: 14px 22px; color: #243D0A; background: var(--pop); font: inherit; font-weight: 600; line-height: 1.2; border: 3px solid #1F0F42; border-radius: 14px; box-shadow: 0 5px 0 #1F0F42; cursor: pointer; -webkit-tap-highlight-color: transparent; }
.invite .copy:active { transform: translateY(3px); box-shadow: 0 2px 0 #1F0F42; }
.invite .copy:focus-visible { outline: 3px solid #FF9CE0; outline-offset: 3px; }
.invite .none-line { margin-top: 10px; }
/* The age stamp beside the badge: our own pixel frame, the height of the badge,
   in the ink colour — a rating mark, not a sentence tacked onto the species line. */
.cta .row { display: flex; align-items: center; gap: 12px; }
.age { display: inline-block; line-height: 0; color: var(--ink); }
.age svg { display: block; height: 50px; width: auto; }
.home .fine { margin: 0; font-size: .9rem; color: var(--label); }
.stage { position: relative; display: flex; align-items: flex-end; justify-content: space-evenly; max-width: 1040px; margin: 44px auto 0; padding: 36px 12px 14px; background: var(--panel); border: 3px solid var(--edge); border-bottom: 0; border-radius: 22px 22px 0 0; }
.stage::after { content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 30px; background: var(--track); border-top: 3px solid var(--edge); }
.stage .pet { position: relative; z-index: 1; }
@media (max-width: 439px) { .stage .opt { display: none; } }

/* The floor, once site.js has it: every pet placed in whole sprite pixels on
   one floor line, the treats and dust between them. An actor's box is its
   walk strip's cell — the pet's drawing, symmetric on its centre, so a mirror
   of the box is the app's left-facing frame. The GIF sits in it where the
   drawing puts it; walking and eating, the strip shows instead. */
.stage.live { display: block; height: calc(var(--tall) * var(--px) * 1px + 50px); overflow: hidden; cursor: pointer; -webkit-user-select: none; user-select: none; -webkit-tap-highlight-color: transparent; touch-action: manipulation; }
.stage.live .actor { position: absolute; bottom: 14px; left: calc(var(--x) * var(--px) * 1px); z-index: 1; width: calc(var(--cw) * var(--px) * 1px); height: calc(var(--ch) * var(--px) * 1px); pointer-events: none; }
.actor .pet { position: absolute; left: calc(var(--ix) * var(--px) * 1px); top: calc(var(--iy) * var(--px) * 1px); pointer-events: auto; }
.actor.mirror .pet { left: calc((var(--cw) - var(--ix) - var(--iw)) * var(--px) * 1px); transform: scaleX(-1); }
.actor .sheet { position: absolute; inset: 0; display: none; background-repeat: no-repeat; image-rendering: pixelated; image-rendering: crisp-edges; pointer-events: auto; }
.actor.left .sheet { transform: scaleX(-1); }
.actor.moving .sheet { display: block; }
.actor.moving .pet { visibility: hidden; }
.stage .treat { position: absolute; z-index: 1; background-repeat: no-repeat; image-rendering: pixelated; image-rendering: crisp-edges; pointer-events: none; }
.stage .treat.air { z-index: 2; }
.stage .dust { position: absolute; z-index: 2; background: var(--muted); pointer-events: none; }
/* ♥ and ♪: the app's emote glyphs, rising a block per step and gone. */
.mark { position: absolute; z-index: 3; background-size: 100% 100%; image-rendering: pixelated; image-rendering: crisp-edges; pointer-events: none; animation: mark-rise 1s steps(var(--steps, 2), end) forwards; }
@keyframes mark-rise {
  0% { transform: none; opacity: 1; }
  70% { opacity: 1; }
  100% { transform: translateY(var(--rise)); opacity: 0; }
}

/* ---- how: three beats, the store panels ---- */
.how { background: var(--hud); padding: 72px 0 88px; }
.home h2 { margin: 0 0 44px; font-size: clamp(1.8rem, 4.4vw, 2.7rem); line-height: 1.28; letter-spacing: .03em; text-align: center; color: var(--ink); }
.beats { display: grid; grid-template-columns: repeat(3, 1fr); gap: 40px; margin: 0; padding: 0; list-style: none; }
.beat { display: flex; flex-direction: column; align-items: center; margin: 0; text-align: center; }
.beat > .zoom { width: 100%; max-width: 300px; }
.beat > .zoom:focus-visible { border-radius: 25px; }
.panel { display: block; width: 100%; height: auto; border: 3px solid var(--edge); border-radius: 22px; box-shadow: 0 8px 0 var(--edge); }
.home .num { display: grid; place-items: center; width: 46px; height: 46px; margin: 32px auto 14px; background: var(--pop); color: var(--pop-ink); border: 3px solid var(--edge); border-radius: 12px; box-shadow: 0 4px 0 var(--edge); font-size: 1.35rem; line-height: 1; }
.beat h3 { margin: 0 0 8px; font-size: 1.4rem; line-height: 1.35; }
.beat-copy p:last-child { margin: 0; max-width: 22em; }
@media (max-width: 699px) {
  .how { padding: 56px 0 64px; }
  .beats { grid-template-columns: 1fr; gap: 40px; }
  .beat { flex-direction: row; align-items: center; gap: 18px; text-align: left; }
  .beat:nth-child(even) { flex-direction: row-reverse; }
  .beat > .zoom { flex: none; width: 40%; max-width: 190px; }
  .beat > .zoom:focus-visible { border-radius: 17px; }
  .panel { border-radius: 14px; box-shadow: 0 5px 0 var(--edge); }
  .home .num { margin: 0 0 10px; width: 38px; height: 38px; font-size: 1.1rem; }
  .beat h3 { font-size: 1.2rem; }
  .beat-copy p:last-child { font-size: .98rem; }
}

/* ---- shelter ---- */
.shelter { padding: 88px 0; }
.split { display: grid; grid-template-columns: 1.1fr .9fr; gap: 56px; align-items: center; }
.shelter h2 { text-align: left; margin-bottom: 24px; }
.key { display: inline-block; padding: 14px 20px; background: var(--pop); color: var(--pop-ink); text-decoration: none; line-height: 1.2; border: 3px solid var(--edge); border-radius: 14px; box-shadow: 0 5px 0 var(--edge); }
.key::after { content: " ↗"; }
.home .source { margin-top: 24px; font-size: .88rem; color: var(--label); }
.home .source a { color: var(--label); }
.shelter-card { justify-self: center; width: 100%; max-width: 380px; margin: 0; overflow: hidden; background: var(--panel); color: var(--panel-ink); border: 3px solid var(--edge); border-radius: 22px; box-shadow: 0 8px 0 var(--edge); }
.home .card-top { display: flex; align-items: center; gap: 10px; margin: 0; padding: 14px 18px; font-size: 1.05rem; line-height: 1.3; }
.tag { padding: 3px 8px; font-size: .78rem; border: 2px solid var(--panel-ink); border-radius: 8px; }
.card-stage { --px: 4; position: relative; display: flex; justify-content: center; align-items: flex-end; padding: 44px 0 30px; background: var(--shell); border-top: 3px solid var(--edge); border-bottom: 3px solid var(--edge); }
.shelter-card figcaption { padding: 14px 18px 18px; }
.home .facts { margin: 0 0 10px; font-size: 1.1rem; line-height: 1.3; }
.home .chips { display: flex; flex-wrap: wrap; gap: 8px; margin: 0; font-size: .85rem; line-height: 1.2; }
.chip { padding: 6px 10px; color: var(--muted); background: var(--track); border-radius: 8px; }
.chip.ok { color: var(--ok); background: var(--ok-surface); }
@media (max-width: 859px) {
  .shelter { padding: 64px 0; }
  .split { grid-template-columns: 1fr; gap: 40px; }
  .card-stage { --px: 3; }
}

/* ---- FAQ: native <details>, no script ---- */
.faq { background: var(--hud); padding: 72px 0; }
.faq details { margin: 0 0 16px; background: var(--panel); color: var(--panel-ink); border: 3px solid var(--edge); border-radius: 16px; box-shadow: 0 5px 0 var(--edge); }
.faq summary { position: relative; padding: 18px 56px 18px 20px; font-size: 1.1rem; line-height: 1.4; cursor: pointer; list-style: none; }
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after { content: "+"; position: absolute; top: 50%; right: 16px; display: grid; place-items: center; width: 30px; height: 30px; margin-top: -15px; font: 700 1.2rem/1 var(--display); color: var(--panel-ink); background: var(--track); border-radius: 8px; }
.faq details[open] summary::after { content: "−"; background: var(--pop); color: var(--pop-ink); }
.faq details > p, .faq details > ul { margin: 0; padding: 0 20px 16px; }
.faq details > ul { padding-left: 40px; }
.faq details li { margin: 0 0 8px; }
.faq details a { color: var(--panel-ink); }
.home .more { margin: 28px 0 0; color: var(--label); }

/* ---- 邀請制 (2026-10-18): the door to the application page ----
   The key that leads there (no ↗: it is ours), in the hero and in the
   invitation under the FAQ — the FAQ's panel, one line in the heading face,
   one of plain words and the key. */
.key.join::after { content: none; }
.cta .join-line { margin: 4px 0 0; }
.join-sec { background: var(--hud); padding: 0 0 72px; }
.join-panel { padding: 26px 22px; text-align: center; background: var(--panel); color: var(--panel-ink); border: 3px solid var(--edge); border-radius: 16px; box-shadow: 0 5px 0 var(--edge); }
.home .join-panel p { margin: 0 auto 16px; max-width: 32em; }
.home .join-panel p:last-child { margin-bottom: 0; }
.home .join-title { font-size: clamp(1.3rem, 3.4vw, 1.7rem); line-height: 1.35; }
/* On the panel the lime word is a lime mark: lime ink would vanish on it. */
.home .join-panel em, .home .apply-form em { color: var(--pop-ink); background: var(--pop); padding: 0 .2em; border-radius: 6px; }

/* ---- 申請: the application page (site/apply/, apply.js) ----
   Why, what happens next, and the form: the photos first, each kind with
   its examples (tools/site_assets.py apply_examples) — ✓ what we can judge,
   ✕ what we cannot — then the words. The field nobody sees (.hp) is off the
   page for a person and there for a script. */
.apply .hero { padding-bottom: 0; }
.apply .cta { margin-bottom: 8px; }
.why { padding: 72px 0; background: var(--hud); }
.why-list { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; margin: 0; padding: 0; list-style: none; }
.why-list li { margin: 0; padding: 22px 20px; background: var(--panel); color: var(--panel-ink); border: 3px solid var(--edge); border-radius: 16px; box-shadow: 0 5px 0 var(--edge); }
.home .why-list h3 { margin: 0 0 8px; font-size: 1.2rem; line-height: 1.35; }
.home .why-list p { margin: 0; }
.next { padding: 72px 0; }
.steps { display: grid; grid-template-columns: repeat(3, 1fr); gap: 32px; margin: 0; padding: 0; list-style: none; text-align: center; }
.steps li { margin: 0; }
.home .steps .num { margin: 0 auto 12px; }
.home .steps h3 { margin: 0 0 6px; font-size: 1.2rem; line-height: 1.35; }
.home .steps p:last-child { margin: 0 auto; max-width: 20em; }
@media (max-width: 859px) {
  .why-list, .steps { grid-template-columns: 1fr; }
  .steps { gap: 28px; }
}
.apply-sec { background: var(--hud); padding: 72px 0 88px; }
.apply-form { position: relative; display: grid; gap: 24px; margin: 0; padding: 26px 22px; background: var(--panel); color: var(--panel-ink); border: 3px solid var(--edge); border-radius: 16px; box-shadow: 0 5px 0 var(--edge); }
.home .apply-form p { margin: 0; }
.home .apply-title { font-size: clamp(1.4rem, 3.6vw, 1.8rem); line-height: 1.3; }
.apply-form .apply-lede { margin-top: -16px; color: var(--muted); }
.apply-form fieldset { display: grid; gap: 12px; min-width: 0; margin: 0; padding: 0; border: 0; }
.apply-form legend { margin: 0 0 12px; padding: 0; font-weight: 700; line-height: 1.4; }
.apply-form legend .count, .apply-form .hint { font-weight: 400; font-size: .9rem; color: var(--muted); }
.home .apply-form .hint { margin-top: -6px; }
.examples { display: grid; grid-template-columns: repeat(auto-fill, minmax(96px, 1fr)); gap: 12px; margin: 0; padding: 0; list-style: none; }
.ex { margin: 0; }
.ex img { display: block; width: 100%; height: auto; aspect-ratio: 1; border: 2px solid var(--edge); border-radius: 10px; background: var(--track); }
.ex.person img { image-rendering: pixelated; image-rendering: crisp-edges; }
.ex .cap { display: block; margin-top: 6px; font-size: .82rem; line-height: 1.35; }
.ex .cap::before { margin-right: 4px; font-weight: 700; }
.ex.ok .cap::before { content: "✓"; color: var(--ok); }
.ex.no .cap::before { content: "✕"; color: var(--no); }
.home .credits { font-size: .78rem; line-height: 1.5; color: var(--muted); }
.home .credits a { color: var(--muted); }
.picked { display: flex; flex-wrap: wrap; gap: 14px; }
.picked:empty { display: none; }
.shot { position: relative; width: 88px; }
.shot canvas { display: block; width: 88px; height: 88px; background: var(--track); border: 2px solid var(--edge); border-radius: 10px; }
.shot.going canvas { opacity: .5; }
.shot.no canvas { opacity: .3; }
.home .shot .say { margin: 4px 0 0; font-size: .78rem; line-height: 1.3; color: var(--no); }
.shot .drop { position: absolute; top: -9px; right: -9px; display: grid; place-items: center; width: 28px; height: 28px; padding: 0; font: 700 .85rem/1 var(--body); color: var(--ink); background: var(--shell); border: 2px solid var(--edge); border-radius: 8px; cursor: pointer; }
.pick { position: relative; justify-self: start; padding: 10px 18px; font-weight: 700; color: var(--panel-ink); background: var(--track); border: 2px solid var(--edge); border-radius: 12px; box-shadow: 0 3px 0 var(--edge); cursor: pointer; }
.pick input { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; cursor: pointer; }
.pick:focus-within, .chip-in:focus-within { outline: 3px solid var(--glow); outline-offset: 2px; }
.apply-form .field { display: grid; gap: 6px; font-size: .92rem; color: var(--muted); }
.apply-form input[type="text"], .apply-form input[type="email"], .apply-form textarea { width: 100%; padding: 10px 12px; font: inherit; font-size: 1rem; color: var(--panel-ink); background: #fff; border: 2px solid var(--edge); border-radius: 10px; }
.apply-form input[type="text"]:focus-visible, .apply-form input[type="email"]:focus-visible, .apply-form textarea:focus-visible { outline: 3px solid var(--glow); outline-offset: 1px; }
/* 聯絡我們 (site/contact/): the application's form, a message box in it. */
.apply-form textarea { min-height: 10em; resize: vertical; line-height: 1.6; }
.apply-form .field .count { font-size: .85rem; opacity: .85; }
.contact .apply-sec { min-height: 60vh; }
/* …and our two social accounts under it, a second way to reach us. */
.home .contact-social { margin: 28px 0 0; text-align: center; font-size: .95rem; color: var(--label); }
.home .contact-social a { color: inherit; white-space: nowrap; }
.chips-in { display: flex; flex-wrap: wrap; gap: 10px; }
.chip-in { position: relative; padding: 9px 14px; font-size: .95rem; line-height: 1.3; color: var(--panel-ink); background: var(--track); border: 2px solid var(--edge); border-radius: 12px; cursor: pointer; }
.chip-in input { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; opacity: 0; cursor: pointer; }
.chip-in:has(input:checked) { color: var(--pop-ink); background: var(--pop); box-shadow: 0 3px 0 var(--edge); }
.apply-form .hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }
.apply-send { justify-self: start; padding: 12px 22px; font: inherit; font-weight: 700; color: var(--pop-ink); background: var(--pop); border: 3px solid var(--edge); border-radius: 14px; box-shadow: 0 5px 0 var(--edge); cursor: pointer; }
.apply-send:disabled { opacity: .6; cursor: default; }
.home .apply-line { color: var(--no); font-weight: 700; }
.home .apply-thanks { color: var(--ok); font-weight: 700; }
/* The account's own links (site/auth/): one panel a state, the
   application's form for the new password. Not a .home page — its
   headings are the body's face, so no heading face has to carry them. */
.auth { background: var(--shell); color: var(--ink); }
.auth .apply-form[hidden] { display: none; }
.auth .apply-form p { margin: 0; }
.auth .apply-title { margin: 0; font-size: clamp(1.4rem, 3.6vw, 1.8rem); line-height: 1.3; }
.auth .apply-form .apply-lede { margin-top: -12px; }
.auth .apply-form .auth-email { color: var(--panel-ink); word-break: break-all; }
.auth .apply-form input[type="password"] { width: 100%; padding: 10px 12px; font: inherit; font-size: 1rem; color: var(--panel-ink); background: #fff; border: 2px solid var(--edge); border-radius: 10px; }
.auth .apply-form input[type="password"]:focus-visible { outline: 3px solid var(--glow); outline-offset: 1px; }
.auth .apply-line { color: var(--no); font-weight: 700; }
.auth .auth-help { margin: 24px 0 0; text-align: center; font-size: .95rem; color: var(--label); }
.auth .auth-help a { color: inherit; }

.angles { display: grid; gap: 12px; margin: 0 0 24px; padding: 0; list-style: none; }
.press .wrap > p { color: var(--label); }

/* ---- the last word: the icon's cat sitting on the panel's edge ---- */
.team { padding: 72px 0 0; text-align: center; }
.team h2 { margin: 0 0 12px; }
.team .dots { display: block; margin: 0 auto 16px; }
.team p { max-width: 560px; margin: 0 auto; }
.last { padding: calc(44px * var(--px) + 48px) 0 96px; }
@media (min-width: 1000px) { .last { --px: 3; } }
.last-panel { position: relative; max-width: 760px; margin: 0 auto; padding: 56px 24px 40px; text-align: center; background: var(--hud); border: 3px solid var(--edge); border-radius: 22px; box-shadow: 0 8px 0 var(--edge); }
.sitter { position: absolute; left: 50%; top: 0; transform: translate(-50%, calc(-100% + 3px)); }
.home .last .display { margin: 0 0 24px; font-size: clamp(1.6rem, 4vw, 2.4rem); line-height: 1.3; }
/* The badge, and beside it the sponsor key in the quiet colour: the app is
   the ask, a coffee is the aside. /sponsor is a redirect in firebase.json,
   the one place the Buy Me a Coffee address is written. */
.home .last-cta { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 16px; margin: 0; }
.key.alt { padding: 10px 16px; font-size: .95rem; background: var(--panel); color: var(--panel-ink); }
/* Under the keys, the founder's bills line: why the app is free and what a coffee is for. */
.home .last .fine { max-width: 30em; margin: 20px auto 0; }

/* ---- footer ---- */
.foot { padding: 40px 0 56px; font-size: .92rem; color: var(--label); background: var(--edge); }
.foot .brand { margin: 0 0 8px; font-size: 1.1rem; }
.home .foot nav { display: flex; flex-wrap: wrap; gap: 10px 24px; margin: 0 0 20px; }
.foot nav a { color: var(--ink); }
.foot p { margin: 0 0 6px; }
.foot a { color: var(--ink); }

/* ---- a picture, large ----
   A picture in main that is not a key (怎麼玩's panels, the shelter card's
   cat) is a link to its own file; site.js opens it here instead: centred on
   the dimmed page, which stops scrolling under it. A tap outside, Escape,
   the ✕ key or a swipe down puts it back. A store panel keeps its slab; a
   pixel pet stands on the card's stage at a whole multiple (--px). */
.zoom { display: block; line-height: 0; cursor: zoom-in; -webkit-tap-highlight-color: transparent; }
html.zoomed { overflow: hidden; overscroll-behavior: none; scrollbar-gutter: stable; }
.zoom-box { position: fixed; inset: 0; display: grid; place-items: center; width: 100%; height: 100%; max-width: none; max-height: none; margin: 0; padding: 76px 16px 24px; overflow: hidden; color: var(--ink); background: rgb(31 15 66 / calc(.9 * var(--fade, 1))); border: 0; overscroll-behavior: contain; touch-action: pinch-zoom; cursor: zoom-out; -webkit-tap-highlight-color: transparent; }
.zoom-box:not([open]) { display: none; }
.zoom-box::backdrop { background: transparent; }
.zoom-fig { position: relative; margin: 0; line-height: 0; cursor: default; }
.zoom-fig img { display: block; max-width: none; }
.zoom-fig:not(.pixel) img { border: 3px solid var(--edge); border-radius: 22px; box-shadow: 0 8px 0 var(--edge); }
.zoom-fig.pixel { padding: calc(var(--px) * 6px) calc(var(--px) * 8px) calc(var(--px) * 4px); background: var(--shell); border: 3px solid var(--edge); border-radius: 22px; box-shadow: 0 8px 0 var(--edge); cursor: pointer; }
.zoom-fig.pixel img { image-rendering: pixelated; image-rendering: crisp-edges; }
.zoom-shut { position: absolute; top: 16px; right: 16px; display: grid; place-items: center; width: 44px; height: 44px; padding: 0; color: var(--ink); background: var(--shell); border: 2px solid var(--edge); border-radius: 10px; box-shadow: 0 3px 0 var(--edge); cursor: pointer; }
.zoom-shut svg { display: block; width: 16px; height: 16px; }
.zoom-shut:hover { color: var(--pop); }
.zoom-shut:focus-visible { outline: 3px solid var(--glow); outline-offset: 3px; }

/* ==========================================================================
   Press, hover and the steps. Everything that moves is in here.
   ========================================================================== */
@media (prefers-reduced-motion: no-preference) {
  /* Keys and cards: up a pixel under the pointer, down onto the slab when
     pressed — the slab left 2px deep, ChunkyKey's travel. */
  .key:hover { transform: translateY(-1px); box-shadow: 0 6px 0 var(--edge); }
  .key:active { transform: translateY(3px); box-shadow: 0 2px 0 var(--edge); }
  .langs > summary:hover, .speaker:hover { transform: translateY(-1px); box-shadow: 0 4px 0 var(--edge); }
  .langs > summary:active, .speaker:active { transform: translateY(1px); box-shadow: 0 2px 0 var(--edge); }
  .langs a[aria-current]:active { transform: translateY(1px); box-shadow: 0 2px 0 var(--edge); }
  .langs[open] ul { animation: drop 200ms steps(4, end) backwards; }
  .langs[open] .caret { animation: flip-open 210ms steps(3, end); }
  .faq details:hover { transform: translateY(-1px); box-shadow: 0 6px 0 var(--edge); }
  .faq details:has(> summary:active) { transform: translateY(3px); box-shadow: 0 2px 0 var(--edge); }
  .shelter-card:hover, .panel:hover { transform: translateY(-1px); box-shadow: 0 9px 0 var(--edge); }
  .shelter-card:active, .panel:active { transform: translateY(6px); box-shadow: 0 2px 0 var(--edge); }
  .angles li:active { transform: translateY(2px); box-shadow: 0 2px 0 var(--edge); }
  @media (max-width: 699px) {
    .panel:hover { box-shadow: 0 6px 0 var(--edge); }
    .panel:active { transform: translateY(3px); }
  }
  /* The badge nudges: a wiggle a step at a time, and down when pressed. */
  .badge:hover img, .badge:focus-visible img { animation: nudge 480ms steps(1) both; }
  .badge:active img { transform: translateY(2px); animation: none; }
  @keyframes nudge {
    0% { transform: translateY(-2px) rotate(-4deg); }
    25% { transform: translateY(-2px) rotate(3deg); }
    50% { transform: translateY(-1px) rotate(-2deg); }
    75% { transform: translateY(-1px) rotate(1deg); }
    100% { transform: translateY(-1px); }
  }
  .speaker { animation: pop 240ms backwards; }

  /* Panels rise into view: six steps of one sprite pixel each (site.js
     marks what is below the fold with .reveal, and .in as it arrives). */
  .reveal:not(.in) { opacity: 0; }
  .reveal.in { animation: rise 360ms steps(6, end) backwards; animation-delay: calc(var(--i, 0) * 90ms); }
  @keyframes rise {
    from { opacity: 0; transform: translateY(calc(var(--px) * 6px)); }
    to { opacity: 1; transform: none; }
  }
  /* 怎麼玩's numbers pop once their panel is up. */
  .beat.reveal.in .num { animation: pop 300ms backwards; animation-delay: calc(var(--i, 0) * 90ms + 380ms); }
  @keyframes pop {
    0% { transform: scale(.25); animation-timing-function: steps(2, end); }
    50% { transform: scale(1.2); animation-timing-function: steps(2, end); }
    100% { transform: none; }
  }
  /* FAQ: the + flips over to a − (and back), and the answer drops in. */
  .faq details[open] summary::after { animation: flip-open 210ms steps(3, end); }
  .faq details.shut summary::after { animation: flip-shut 210ms steps(3, end); }
  @keyframes flip-open { from { transform: scaleY(0); } to { transform: none; } }
  @keyframes flip-shut { from { transform: scaleY(0); } to { transform: none; } }
  .faq details[open] > :not(summary) { animation: drop 200ms steps(4, end) backwards; }
  @keyframes drop {
    from { opacity: 0; transform: translateY(-8px); }
    to { opacity: 1; transform: none; }
  }
  /* A picture, large: the page dims in steps and the picture pops; shut, it
     sinks and fades. Under a finger it follows the drag, the dim thinning
     with the distance, and a short drag steps back into place. */
  .zoom-box { transition: background-color 160ms steps(4, end); }
  .zoom-box[open] { animation: dim 160ms steps(4, end) backwards; }
  .zoom-fig { transition: transform 160ms steps(4, end), opacity 160ms steps(4, end); }
  .zoom-box[open] .zoom-fig { animation: pop 300ms backwards; }
  .zoom-box.out { --fade: 0; }
  .zoom-box.out .zoom-fig { opacity: 0; transform: translateY(24px); }
  .zoom-box.dragging, .zoom-box.dragging .zoom-fig { transition: none; }
  @keyframes dim { from { background-color: transparent; } }
  .zoom-shut:hover { transform: translateY(-1px); box-shadow: 0 4px 0 var(--edge); }
  .zoom-shut:active { transform: translateY(1px); box-shadow: 0 2px 0 var(--edge); }
}
@media (prefers-reduced-motion: reduce) {
  /* Nothing moves: a press lights the face, as FeelTap does. */
}
