/* Shared by every page: tokens, type, chrome and components. Page-only styles live beside their page. */
:root {
  --lichen: #f4efe3;
  --lichen-deep: #e9e2d1;
  --paper: rgba(255, 253, 247, .62);
  --ink: #173526;
  --ink-soft: #4d5e52;
  --sprout: #a9c46a;
  --sprout-soft: #e2e8cc;
  --fern: #2f5d3e;
  --bark: #6b5443;
  --canopy: #0f2a1d;
  --line: rgba(23, 53, 38, .13);
  --line-strong: rgba(23, 53, 38, .28);
  --warn: #8a5d0a;
  --warn-bg: #f6ecd2;
  --err: #a03c28;
  --err-bg: #f7e4de;
  --err-line: rgba(160, 60, 40, .4);
  /* text on surfaces that stay dark in both schemes (the canopy section, the Grove card) */
  --cream: #f4efe3;
  --cream-soft: rgba(244, 239, 227, .75);
  --on-ink: #f4efe3;            /* text on a var(--ink) fill: cream by day, deep green at night */
  --grove: #173526;             /* the Grove card and the live pill, dark in both schemes */
  --nav-glass: rgba(244, 239, 227, .82);
  --field-bg: rgba(255, 255, 255, .7);
  --head-bg: rgba(255, 255, 255, .35);
  --tile-bg: rgba(255, 255, 255, .4);
  --sticky-bg: #eef1ea;
  --done-bg: #dbe8e3;
  --done: #2f6b5a;
  --paused-bg: #efe4d8;
  --grain: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 .35  0 0 0 0 .3  0 0 0 0 .2  0 0 0 .55 0'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)' opacity='.22'/%3E%3C/svg%3E");
  --veins: url("/leaf-veins.svg");
  --serif: "Fraunces", Georgia, serif;
  --sans: "Public Sans", system-ui, sans-serif;
  --leaf: 22px 22px 22px 4px;
  --gutter: clamp(20px, 4vw, 48px);
}
/* night: the same forest after dark. theme-boot.js and theme.js set data-scheme on <html>. */
:root[data-scheme="dark"] {
  --lichen: #0b1612;
  --lichen-deep: #12211b;
  --paper: rgba(26, 46, 38, .55);
  --ink: #ebe8dc;
  --ink-soft: #a3b0a6;
  --sprout: #c4da8c;
  --sprout-soft: #1f3529;
  --fern: #a6cf95;
  --bark: #c2a58a;
  --line: rgba(236, 230, 214, .14);
  --line-strong: rgba(236, 230, 214, .3);
  --warn: #e2b866;
  --warn-bg: #3a2f17;
  --err: #f0a08c;
  --err-bg: #3d1f18;
  --err-line: rgba(240, 160, 140, .4);
  --on-ink: #10241a;
  --grove: #1d3a2a;
  --nav-glass: rgba(11, 22, 18, .84);
  --field-bg: rgba(255, 255, 255, .06);
  --head-bg: rgba(255, 255, 255, .04);
  --tile-bg: rgba(255, 255, 255, .04);
  --sticky-bg: #12211b;
  --done-bg: #1e3a33;
  --done: #8fd0b8;
  --paused-bg: #33291f;
  --grain: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 .92  0 0 0 0 .9  0 0 0 0 .84  0 0 0 .5 0'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)' opacity='.07'/%3E%3C/svg%3E");
  --veins: url("/leaf-veins-night.svg");
}
* { box-sizing: border-box; margin: 0; padding: 0; }
html { scroll-behavior: smooth; scroll-padding-top: 88px; } /* anchor jumps land below the fixed nav */
/* paper: a fine grain over faint leaf skeletons on the cream ground */
body { background: var(--grain), var(--veins) 0 0 / 720px 720px, var(--lichen); color: var(--ink); font-family: var(--sans); font-size: 17px; line-height: 1.6; -webkit-font-smoothing: antialiased; }
a { color: inherit; }
img, svg { max-width: 100%; }
:focus-visible { outline: 2px solid var(--fern); outline-offset: 3px; border-radius: 4px; }
[hidden] { display: none !important; }
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

h1, h2 { font-family: var(--serif); font-weight: 340; font-variation-settings: "SOFT" 100, "opsz" 144; letter-spacing: -.02em; line-height: 1.02; }
h1 { font-size: clamp(3rem, 6.4vw, 5.6rem); }
h2 { font-size: clamp(2.2rem, 4vw, 3.3rem); margin-bottom: 28px; }
h3 { font-family: var(--serif); font-weight: 450; font-variation-settings: "SOFT" 100; font-size: 1.35rem; line-height: 1.2; margin-bottom: 6px; }
/* Chinese headings: Fraunces has no CJK glyphs, so let the system serif carry them at a calmer size */
html[lang="zh-Hant"] h1, html[lang="zh-Hant"] h2, html[lang="zh-Hant"] h3 { font-family: var(--serif), "Noto Serif TC", "Songti TC", serif; letter-spacing: 0; line-height: 1.2; }
html[lang="zh-Hant"] h1 { font-size: clamp(2.2rem, 4vw, 3.5rem); }
.lede { margin-top: 22px; font-size: 1.15rem; color: var(--ink-soft); max-width: 34rem; }
.muted { color: var(--ink-soft); }
.small { font-size: .88rem; }

/* No flash of English when Chinese is saved; reveals anyway after 1.5s if a script fails */
.lang-pending body { visibility: hidden; animation: reveal 0s 1.5s forwards; }
@keyframes reveal { to { visibility: visible; } }
.skip-link { position: absolute; left: 8px; top: 8px; z-index: 1000; padding: 10px 16px; background: var(--ink); color: var(--on-ink); border-radius: 8px; font-weight: 600; text-decoration: none; transform: translateY(-200%); }
.skip-link:focus { transform: none; }

/* ---------- nav (rendered by site.js into [data-site-nav]) ---------- */
[data-site-nav] { display: block; min-height: 72px; }
.nav { position: fixed; inset: 0 0 auto 0; z-index: 10; display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 18px var(--gutter); transition: background .4s, box-shadow .4s; }
.nav.scrolled { background: var(--nav-glass); backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px); box-shadow: 0 1px 0 var(--line); }
.nav, .nav * { transition: color .6s, border-color .6s, background .4s; }
.brand { display: flex; align-items: center; gap: 10px; font-family: var(--serif); font-size: 1.25rem; font-variation-settings: "SOFT" 100; text-decoration: none; white-space: nowrap; }
.brand .sp.logo { width: 32px; height: 32px; }
.nav-right { display: flex; align-items: center; gap: 22px; font-size: .92rem; }
.tabs { display: flex; gap: 26px; }
.tabs a, .nav-link { text-decoration: none; color: var(--ink-soft); white-space: nowrap; }
.tabs a:hover, .nav-link:hover { color: var(--ink); }
.tabs a[aria-current="page"] { color: var(--ink); box-shadow: 0 1.5px 0 var(--sprout); }
.member-link { min-width: 68px; max-width: 40vw; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; padding: 8px 18px; border: 1px solid var(--ink); border-radius: 999px; background: none; font: inherit; text-align: center; text-decoration: none; color: var(--ink); cursor: pointer; }
.member-link[aria-current="page"] { background: var(--ink); color: var(--on-ink); }
.lang-toggle { background: none; border: 0; padding: 6px 2px; font: inherit; color: var(--ink-soft); cursor: pointer; }
.lang-toggle:hover { color: var(--ink); }
/* day/night button (site.js draws it, theme.js wires it): the sun turns into the moon */
.scheme-toggle { width: 38px; height: 38px; flex: none; display: grid; place-items: center; padding: 0; border: 1px solid var(--line-strong); border-radius: 50%; background: none; color: var(--ink); cursor: pointer; }
.scheme-toggle:hover { border-color: var(--ink); }
.scheme-toggle svg { grid-area: 1 / 1; width: 20px; height: 20px; overflow: visible; transition: opacity .6s, transform .8s cubic-bezier(.3, .7, .2, 1); }
.scheme-toggle .i-moon { opacity: 0; transform: rotate(-90deg) scale(.6); }
:root[data-scheme="dark"] .scheme-toggle .i-sun { opacity: 0; transform: rotate(90deg) scale(.6); }
:root[data-scheme="dark"] .scheme-toggle .i-moon { opacity: 1; transform: none; }
.who { color: var(--ink-soft); font-size: .85rem; max-width: 22ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ---------- footer (rendered by site.js into [data-site-footer]) ---------- */
footer[data-site-footer] { display: flex; flex-wrap: wrap; align-items: center; gap: 24px; padding: 28px var(--gutter); border-top: 1px solid var(--line); font-size: .85rem; color: var(--ink-soft); }
footer[data-site-footer] a { color: inherit; }

/* ---------- page layout ---------- */
.page { max-width: 1120px; margin: 0 auto; padding: 0 var(--gutter) 96px; }
.page-head { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: clamp(24px, 4vw, 64px); align-items: center; padding: clamp(40px, 7vw, 88px) 0 clamp(32px, 5vw, 56px); }
.page-head.solo { grid-template-columns: minmax(0, 1fr); }
.page-head .crumb { display: inline-block; margin-bottom: 18px; font-size: .9rem; color: var(--ink-soft); text-decoration: none; }
.page-head .crumb:hover { color: var(--ink); }
.page-head .hl-fig { margin: 0; }
.section { padding: clamp(40px, 6vw, 72px) 0; border-top: 1px solid var(--line); }
.section > h2 { max-width: 20ch; }
.actions { display: flex; flex-wrap: wrap; gap: 14px; margin-top: 32px; }

/* ---------- buttons ---------- */
.btn { display: inline-flex; align-items: center; justify-content: center; gap: 8px; padding: 12px 22px; border: 1px solid transparent; border-radius: 999px; background: none; font: inherit; font-weight: 500; font-size: .95rem; text-decoration: none; color: inherit; cursor: pointer; transition: background .25s, color .25s, border-color .25s; }
.btn.solid { background: var(--ink); color: var(--on-ink); }
.btn.solid:hover { background: var(--fern); }
.btn.ghost { border-color: var(--line-strong); }
.btn.ghost:hover { border-color: var(--ink); }
.btn.small { padding: 7px 14px; font-size: .85rem; }
.btn.danger { border-color: var(--err-line); color: var(--err); }
.btn.danger:hover { border-color: var(--err); }
.btn:disabled { opacity: .5; cursor: not-allowed; }

/* ---------- cards ---------- */
.card { padding: clamp(22px, 3vw, 32px); border: 1px solid var(--line); border-radius: var(--leaf); background: var(--paper); }
.card + .card { margin-top: 18px; }
.cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr)); gap: 18px; }
.card.dashed { border-style: dashed; background: transparent; }

/* ---------- forms ---------- */
label { display: block; font-size: .9rem; font-weight: 500; }
input[type="text"], input[type="email"], input[type="search"], input[type="number"], input:not([type]), select, textarea {
  width: 100%; padding: 10px 14px; border: 1px solid var(--line-strong); border-radius: 12px; background: var(--field-bg); font: inherit; font-size: .95rem; color: var(--ink);
}
textarea { min-height: 140px; resize: vertical; line-height: 1.5; }
input:focus, select:focus, textarea:focus { outline: 2px solid var(--sprout); outline-offset: 0; border-color: var(--fern); }
.field-row { display: grid; gap: 6px; margin-top: 16px; }
.check { display: flex; align-items: center; gap: 10px; font-weight: 400; }
.check input { width: auto; accent-color: var(--fern); }
.form-error, .notice.error { color: var(--err); }

/* ---------- notices ---------- */
.notice { padding: 12px 16px; border-radius: 12px; background: var(--sprout-soft); font-size: .92rem; }
.notice.error { background: var(--err-bg); }
.notice.warn { background: var(--warn-bg); color: var(--warn); }

/* ---------- tables ---------- */
.table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; border: 1px solid var(--line); border-radius: 16px; background: var(--paper); }
table.data { width: 100%; border-collapse: collapse; font-size: .9rem; }
table.data th, table.data td { padding: 11px 14px; border-bottom: 1px solid var(--line); text-align: left; vertical-align: top; }
table.data th { font-weight: 600; font-size: .8rem; color: var(--ink-soft); white-space: nowrap; background: var(--head-bg); position: sticky; top: 0; }
table.data tr:last-child td { border-bottom: 0; }
table.data td.empty { padding: 28px 14px; text-align: center; color: var(--ink-soft); }
table.data .num { text-align: right; font-variant-numeric: tabular-nums; }

/* ---------- status pills: one meaning per variant ---------- */
.pill { display: inline-flex; align-items: center; gap: 6px; padding: 3px 10px; border-radius: 999px; font-size: .78rem; font-weight: 600; white-space: nowrap; background: var(--lichen-deep); color: var(--ink-soft); }
.pill::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
.pill.ok { background: var(--sprout-soft); color: var(--fern); }
.pill.wait { background: var(--warn-bg); color: var(--warn); }
.pill.no { background: var(--err-bg); color: var(--err); }
.pill.off { background: var(--lichen-deep); color: var(--ink-soft); }
.pill.live { background: var(--grove); color: var(--sprout); }
.pill.done { background: var(--done-bg); color: var(--done); }
.pill.paused { background: var(--paused-bg); color: var(--bark); }

/* ---------- Grove gate ---------- */
.gate { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 20px; align-items: start; max-width: 40rem; }
.gate .sp { width: 72px; height: 72px; }
.gate h2 { font-size: clamp(1.6rem, 3vw, 2.2rem); margin-bottom: 8px; }
.gate p { color: var(--ink-soft); }
.gate .btn { margin-top: 18px; }

/* ---------- plan cards ---------- */
.tiers { display: grid; gap: 52px 22px; }
.tier-card { position: relative; padding: 28px 30px; border: 1px solid var(--line); border-radius: var(--leaf); background: var(--paper); backdrop-filter: blur(6px); }
.tier-top { display: flex; flex-wrap: wrap; align-items: baseline; gap: 10px; margin-bottom: 10px; padding-right: 90px; }
.tier-tag { font-size: .82rem; font-weight: 600; color: var(--fern); }
.tier-card p { color: var(--ink-soft); margin-top: 4px; }
.tier-card.grove { background: var(--grove); color: var(--cream); border-color: transparent; }
.tier-card.grove p { color: var(--cream-soft); }
.tier-card.grove .tier-tag { color: var(--sprout); }
.tier-card.grove a:not(.btn) { color: var(--sprout); }
.tier-card.grove .btn.solid { background: var(--sprout); color: var(--canopy); }
.tier-card.grove .btn.solid:hover { background: var(--cream); }
/* each plan's seal sits on the card's top edge; hairline.js draws it from [data-emblem] */
.tier-emblem { position: absolute; right: 24px; top: -38px; width: 78px; height: 78px; border-radius: 50%; box-shadow: 0 0 0 5px var(--lichen), 0 16px 26px -14px rgba(20, 39, 28, .55); will-change: transform; transition: transform .6s cubic-bezier(.2, .8, .2, 1); }
.tier-emblem svg { width: 100%; height: 100%; display: block; }
.tier-card:hover .tier-emblem { transform: translateY(-4px) rotate(-4deg); }
.tier-emblem .em-sway { animation: em-sway 7s ease-in-out infinite; }
.tier-emblem .em-sway.slow { animation-duration: 9s; animation-delay: -3s; }
.tier-emblem .em-sway.late { animation-duration: 8s; animation-delay: -5s; }
.tier-emblem .em-mote { transform-box: fill-box; animation: em-mote 6s ease-in-out infinite both; }
.tier-emblem .em-twinkle { animation: em-twinkle 4.5s ease-in-out infinite; }
.tier-emblem .em-rise { transform-box: fill-box; animation: em-rise 8s ease-in-out infinite; }
.tier-emblem .em-drift { transform-box: fill-box; animation: em-drift 11s ease-in-out infinite; }
@keyframes em-sway { 0%, 100% { transform: rotate(-3.5deg); } 50% { transform: rotate(3.5deg); } }
@keyframes em-mote { 0% { transform: translateY(4px); opacity: 0; } 30%, 65% { opacity: 1; } 100% { transform: translateY(-18px); opacity: 0; } }
@keyframes em-twinkle { 0%, 100% { transform: scale(.5); opacity: .25; } 50% { transform: scale(1); opacity: 1; } }
@keyframes em-rise { 0%, 100% { transform: translateY(2px); } 50% { transform: translateY(-2px); } }
@keyframes em-drift { 0%, 100% { transform: translateX(-6px); } 50% { transform: translateX(6px); } }

/* ---------- lists ---------- */
.list { list-style: none; border-top: 1px solid var(--line); }
.list li { padding: 22px 0; border-bottom: 1px solid var(--line); display: grid; grid-template-columns: 1fr; }
.list p { color: var(--ink-soft); font-size: .98rem; }
.list a { text-decoration: none; display: block; }
.list a h3 { display: flex; justify-content: space-between; align-items: baseline; }
.list a h3::after { content: ""; width: 9px; height: 9px; border-top: 1.5px solid currentColor; border-right: 1.5px solid currentColor; transform: rotate(45deg); transition: transform .3s; flex: none; }
.list a:hover h3::after { transform: translateX(4px) rotate(45deg); }

/* ---------- sprites (built by hairline.js from [data-sprite]) ---------- */
.sp { display: inline-block; width: 56px; height: 56px; flex: none; }
.sp svg { width: 100%; height: 100%; overflow: visible; display: block; }
.sp .eyes { transform-box: fill-box; transform-origin: center; animation: blink 6s infinite; }
.sp .bob { transform-box: fill-box; transform-origin: 50% 100%; animation: breathe 5s ease-in-out infinite; }
.sp .flutter { transform-box: fill-box; transform-origin: center; animation: flutter .9s ease-in-out infinite; }
.sp .zz { animation: zz 3.2s ease-in-out infinite; }
.sp[data-static] .eyes, .sp[data-static] .bob { animation: none; }
@keyframes blink { 0%, 93%, 100% { transform: scaleY(1); } 96% { transform: scaleY(.1); } }
@keyframes breathe { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.03, .98); } }
@keyframes flutter { 0%, 100% { transform: scaleX(1); } 50% { transform: scaleX(.45); } }
@keyframes zz { 0% { opacity: 0; transform: translate(0, 4px); } 30%, 70% { opacity: 1; } 100% { opacity: 0; transform: translate(4px, -6px); } }

/* ---------- hairline figures (drawn by hairline.js into .hl-fig) ---------- */
.hl-fig { width: 100%; aspect-ratio: 5 / 3; margin-bottom: 10px; touch-action: pan-y; }
.hl-fig svg { width: 100%; height: 100%; display: block; overflow: visible; }
.hl-fig .ln { vector-effect: non-scaling-stroke; }
.hl-fig.pre { opacity: 0; }
.hl-fig.draw .ln { stroke-dasharray: 1; animation: drawin 1.8s cubic-bezier(.45, .05, .25, 1) both; animation-delay: var(--d, 0s); }
.hl-fig text { font-family: var(--sans); font-size: 11px; fill: var(--ink-soft); }
/* ---------- the sky that crosses during a day/night switch (theme.js) ---------- */
.sky-pass { position: fixed; inset: 0; z-index: -1; pointer-events: none; }
.sky-pass .sky-day, .sky-pass .sky-night { position: absolute; inset: 0; }
.sky-pass .sky-day { background: radial-gradient(120% 80% at 50% 100%, #fbf8f0 0%, #f4efe3 45%, #e9e2d1 100%); }
.sky-pass .sky-night { background: radial-gradient(120% 80% at 50% 100%, #1a2f27 0%, #0b1612 50%, #060d0a 100%); opacity: 0; }
.heaven { position: absolute; inset: 0; overflow: hidden; pointer-events: none; }
.heaven .orb { position: absolute; left: 50%; top: 100%; width: 64px; height: 64px; margin: -32px 0 0 -32px; will-change: transform; visibility: hidden; }
.heaven.placed .orb { visibility: visible; } /* theme.js puts them on the arc first */
.heaven .orb svg { width: 100%; height: 100%; display: block; overflow: visible; }
.heaven .sun circle, .heaven .sun path { stroke: #c99a3e; }
.heaven .moon path { stroke: #efe6c4; }
.heaven .glow { position: absolute; inset: -40%; border-radius: 50%; background: radial-gradient(circle, rgba(243, 231, 166, .55) 0%, transparent 60%); opacity: .25; }
/* while the scheme switches, colours ease over with the sky (the sky and the button icons animate themselves) */
html.scheme-switching *:not(.sky-layer, .sky-layer *, .scheme-toggle svg) { transition: color .9s .3s, background-color .9s .3s, border-color .9s .3s, fill .9s .3s, stroke .9s .3s !important; }

/* Night repaint for the line figures and sprites. hairline.js writes literal colours as SVG attributes;
   CSS outranks those, and attribute selectors re-match when a figure switches a highlight on, so the
   drawings follow the scheme without the script knowing. Keep these strings in step with hairline.js. */
:root[data-scheme="dark"] .hl-fig [stroke="rgba(28,49,36,.62)"] { stroke: rgba(236, 230, 214, .62); }
:root[data-scheme="dark"] .hl-fig [fill="rgba(28,49,36,.62)"] { fill: rgba(236, 230, 214, .62); }
:root[data-scheme="dark"] .hl-fig [stroke="rgba(28,49,36,.22)"] { stroke: rgba(236, 230, 214, .22); }
:root[data-scheme="dark"] .hl-fig [fill="#f4efe3"] { fill: #13241c; }
:root[data-scheme="dark"] .hl-fig [stroke="#4f7a4a"] { stroke: #a6cf95; }
:root[data-scheme="dark"] .hl-fig [fill="#dfe8cf"] { fill: #24432f; }
:root[data-scheme="dark"] .hl-fig [fill="#ddd3c4"] { fill: #2b2a20; }
:root[data-scheme="dark"] .sp [fill="#a9c46a"][fill-opacity="0.45"] { fill: #c8d98a; fill-opacity: .95; stroke: #2f5236; }
:root[data-scheme="dark"] .sp [stroke="#3f6a42"] { stroke: #2f5236; }
@keyframes drawin { from { stroke-dashoffset: 1; fill-opacity: 0; } 55% { fill-opacity: 0; } to { stroke-dashoffset: 0; fill-opacity: 1; } }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .sp .eyes, .sp .bob, .sp .flutter, .sp .zz { animation: none; }
  .tier-emblem, .tier-emblem * { animation: none !important; transition: none !important; }
}

@media (max-width: 860px) {
  .tabs { display: none; }
  .nav-right { gap: 14px; }
  .page-head { grid-template-columns: minmax(0, 1fr); }
  .page-head .hl-fig { max-width: 30rem; }
}
@media (max-width: 520px) {
  /* brand, Sign in, the day/night button and 中文 share one phone-width row */
  .nav-right { gap: 10px; }
  .member-link { min-width: 0; padding: 7px 13px; }
  .scheme-toggle { width: 34px; height: 34px; }
  .lang-toggle { white-space: nowrap; }
  .gate { grid-template-columns: minmax(0, 1fr); }
  .who { display: none; }
}
