/* voca.boo hub — "Nightdesk". Vanilla CSS, no build. Rationale + contrast math: NOTES.md in the repo. */

/* 1. tokens */

:root {
  color-scheme: light;

  /* surfaces */
  --bg: #fbf6ee;
  --bg-sunken: #f3ebdf;
  --surface: #fffcf7;

  --raised-hover: #fffdf9;      /* == --surface: elevation is lift + border + hairline */
  --ghost-hover: #f1e7d8;       /* 1.09:1 vs --bg — visible, still quiet (was 1.03:1) */

  /* ink — three measured steps, no opacity anywhere */
  --text: #24190f;              /* 16.97 on --bg */
  --text-muted: #72614f;        /* 5.05 / 5.28 */
  --text-quiet: #776654;        /* 4.77 / 4.98 — replaces opacity .75/.8/.85 */
  --text-faint: #a08e7a;        /* 3.24 — decorative marks only (aria-hidden) */

  /* lines */
  --border: rgba(90, 55, 20, .12);
  --border-strong: rgba(90, 55, 20, .22);
  --border-dashed: rgba(90, 55, 20, .28);

  /* one hue, three jobs — the naive single value was 4.31:1 over the wash */
  --accent: #e2691c;            /* 4.94 on --bg */
  --accent-ink: #b4500f;
  --accent-ink-wash: #a5480c;
  --accent-wash: rgba(226, 105, 28, .13);
  --glow: rgba(240, 140, 50, .28);

  /* status — ≥3:1 on --bg and --surface; each dot also carries a Korean label */
  --ok: #4f7f3a;                /* 4.81 / 5.02 */
  --warn: #b7791f;              /* 4.81 / 5.02 */
  --down: #c73a2a;              /* 4.63 / 4.83 */
  --muted-dot: #9a8a76;         /* 4.63 / 4.83 */

  --keycap-shadow: inset 0 1px 0 rgb(255 255 255 / .6), 0 1px 0 var(--border-strong);
  --leaf: #4f7f3a;
  --leaf-ink: #3f6a2e;
  --peel-hi: rgba(255, 255, 255, .55);
  --skeleton: rgba(90, 55, 20, .08);
  --skeleton-hi: rgba(90, 55, 20, .035);
  --noise-alpha: .07;

  /* spacing scale — 4px base */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 24px;
  --space-6: 32px;
  --space-7: 48px;
  --space-8: 64px;
  --space-9: 96px;

  --card-min: 13.375rem;    /* 214px: three description lines */

  --r-card: 12px;
  --r-sm: 8px;
  --r-pill: 9999px;

  --pad: clamp(16px, 4vw, 32px);
  --maxw: 1280px;
  --bar-h: 56px;
  --tap: 44px;                  /* minimum interactive target */
  --chip-h: 36px;

  --font-sans: Inter, "Pretendard Variable", Pretendard, -apple-system, BlinkMacSystemFont,
               "Apple SD Gothic Neo", "Segoe UI", "Malgun Gothic", "Noto Sans KR", sans-serif;
  --font-mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  --font-calli: Caveat, "Nanum Pen Script", "Segoe Script", "Bradley Hand", cursive;
  --fs-hero: clamp(3.4rem, 2.4rem + 4vw, 6rem);
  --fs-body: clamp(0.9375rem, 0.9rem + 0.2vw, 1rem);
  --fs-card: 1.0625rem;
  --fs-desc: 0.9375rem;
  --fs-meta: 0.8125rem;

  --dur: 170ms;
  --ease: cubic-bezier(.2, .6, .3, 1);

  --noise-img: 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='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)'/%3E%3C/svg%3E");
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    --bg: #171210;
    --bg-sunken: #1d1613;
    --surface: #211a16;
    --raised-hover: #2a211b;    /* above --surface: the card brightens as it lifts */
    --ghost-hover: #2a211b;     /* above --bg #0a0a0c */
    --text: #f6ede2;
    --text-muted: #a89685;      /* 6.09 / 5.65 */
    --text-quiet: #9d8b79;      /* 5.21 / 4.84 */
    --text-faint: #6f6152;      /* 3.44 */
    --border: rgba(255, 220, 180, .10);
    --border-strong: rgba(255, 220, 180, .22);
    --border-dashed: rgba(255, 220, 180, .28);
    --accent: #f08a3e;          /* 7.27 on --bg */
    --accent-ink: #ffa964;      /* 9.31 / 8.65 */
    --accent-ink-wash: #ffb374; /* 7.81 / 7.01 over the wash */
    --accent-wash: rgba(240, 138, 62, .16);
    --glow: rgba(240, 130, 50, .30);
    --ok: #8cc470;
    --warn: #f0b64a;
    --down: #f07b6c;
    --muted-dot: #8a7a68;
    --keycap-shadow: inset 0 1px 0 rgb(255 255 255 / .09), 0 1px 0 rgb(0 0 0 / .5);
    --leaf: #8cc470;
    --leaf-ink: #a6d68c;
    --peel-hi: rgba(255, 235, 210, .25);
    --skeleton: rgba(255, 220, 180, .07);
    --skeleton-hi: rgba(255, 220, 180, .03);
    --noise-alpha: .09;
  }
}

:root[data-theme="dark"] {
  color-scheme: dark;
  --bg: #171210;
  --bg-sunken: #1d1613;
  --surface: #211a16;
  --raised-hover: #2a211b;
  --ghost-hover: #2a211b;
  --text: #f6ede2;
  --text-muted: #a89685;
  --text-quiet: #9d8b79;
  --text-faint: #6f6152;
  --border: rgba(255, 220, 180, .10);
  --border-strong: rgba(255, 220, 180, .22);
  --border-dashed: rgba(255, 220, 180, .28);
  --accent: #f08a3e;
  --accent-ink: #ffa964;
  --accent-ink-wash: #ffb374;
  --accent-wash: rgba(240, 138, 62, .16);
  --glow: rgba(240, 130, 50, .30);
  --ok: #8cc470;
  --warn: #f0b64a;
  --down: #f07b6c;
  --muted-dot: #8a7a68;
  --keycap-shadow: inset 0 1px 0 rgb(255 255 255 / .09), 0 1px 0 rgb(0 0 0 / .5);
    --leaf: #8cc470;
    --leaf-ink: #a6d68c;
    --peel-hi: rgba(255, 235, 210, .25);
  --skeleton: rgba(255, 220, 180, .07);
  --skeleton-hi: rgba(255, 220, 180, .03);
  --noise-alpha: .09;
}

/* 2. reset + base */

*, *::before, *::after { box-sizing: border-box; }
[hidden] { display: none !important; }

/* focus / fragment jumps land below the sticky bar, not under it */
html { -webkit-text-size-adjust: 100%; scroll-padding-top: calc(var(--bar-h) + var(--space-2)); }

body {
  margin: 0; min-height: 100%; background: var(--bg); color: var(--text);
  font-family: var(--font-sans); font-size: var(--fs-body); line-height: 1.5;
  -webkit-font-smoothing: antialiased; text-rendering: optimizeLegibility;
}

h1, h2, h3, p { margin: 0; }
a { color: inherit; text-decoration: none; }
button, input { font: inherit; color: inherit; }

.wrap { width: 100%; max-width: var(--maxw); margin-inline: auto; padding-inline: var(--pad); }

.mono {
  font-family: var(--font-mono); font-size: var(--fs-meta); font-variant-numeric: tabular-nums;
  letter-spacing: 0;
}

.sr {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}

.skip {
  position: absolute; left: var(--space-4); top: calc(var(--space-2) * -10); z-index: 50;
  padding: var(--space-3) var(--space-4); background: var(--surface);
  border: 1px solid var(--border-strong); border-radius: var(--r-sm); font-size: var(--fs-meta);
  transition: top var(--dur) var(--ease);
}
.skip:focus-visible { top: var(--space-2); }

:where(a, button, input, [tabindex]):focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* 3. top bar */

.topbar {
  position: sticky; top: 0; z-index: 20; background: var(--bg);
  border-bottom: 1px solid var(--border);
}

.topbar-inner { display: flex; align-items: center; gap: var(--space-3); min-height: var(--bar-h); }

.wordmark {
  position: relative; flex: 0 0 auto; font-size: 1.5rem; line-height: 1;
  padding: var(--space-1) var(--space-1); border-radius: var(--r-sm); white-space: nowrap;
}
.calli, .calli span { font-family: var(--font-calli); font-weight: 700; letter-spacing: 0; font-style: normal; }
.calli .mark { display: inline-block; width: .34em; height: .34em; margin: 0 .05em 0 .02em; vertical-align: -.04em; overflow: visible; }
.mark-fruit { fill: var(--accent); }
.mark-shine { fill: none; stroke: var(--peel-hi); stroke-width: 2.2; stroke-linecap: round; }
.mark-leaf { fill: var(--leaf); }
.mark-stem { fill: none; stroke: var(--leaf-ink); stroke-width: 1.6; stroke-linecap: round; }
/* the two o's in "boo" blink every few seconds, like eyes — the peekaboo wink */
.oo .o { display: inline-block; transform-origin: 50% 62%; animation: blink 5.2s var(--ease) infinite; }
.oo .o + .o { animation-delay: .07s; }
@keyframes blink {
  0%, 91%, 100% { transform: scaleY(1); }
  94.5% { transform: scaleY(.08); }
  98% { transform: scaleY(1); }
}
/* the fruit in the h1 is the unadvertised way into /admin/: five clicks, no cursor change, no hover */
.portal { display: inline-block; line-height: 0; cursor: inherit; user-select: none; -webkit-user-select: none; }

.wordmark::before, .iconbtn::before, .chip::before, .card-repo::before {
  content: ""; position: absolute; top: 50%; left: 50%;
  height: var(--tap); min-width: var(--tap); transform: translate(-50%, -50%);
}
.wordmark::before { width: calc(100% + 4px); }

.searchwrap {
  position: relative; flex: 1 1 auto; min-width: 0; max-width: 420px; margin-inline-end: auto;
  display: flex; align-items: center;
}

.search-icon { position: absolute; left: 13px; color: var(--text-muted); pointer-events: none; }

.search {
  width: 100%;
  min-width: 0;
  height: var(--tap);
  padding: 0 3.4rem 0 2.3rem;
  background: var(--bg-sunken);
  border: 1px solid transparent;
  border-radius: var(--r-pill);
  font-size: 1rem;   /* 16px — below that iOS Safari zooms on focus and never zooms back */
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease);
  appearance: none;
}
.search::placeholder { color: var(--text-muted); }
/* keyboards get the keycaps and no native ✕; touch gets the native ✕ and no keycaps */
@media (hover: hover) and (pointer: fine) {
  .search::-webkit-search-cancel-button { display: none; }
}
@media (hover: none), (pointer: coarse) {
  .keycap { display: none; }
  .search { padding-right: 2.4rem; }
}
.search:hover { border-color: var(--border); }
.search:focus { background: var(--surface); border-color: var(--accent); }
/* drop the ring for pointer focus only — keyboard focus keeps a compliant one */
.search:focus:not(:focus-visible) { outline: none; }
.searchwrap:focus-within .search-icon { color: var(--accent-ink); }

.keycap {
  position: absolute; right: 10px; display: inline-flex; align-items: center;
  justify-content: center; min-width: 20px; height: 20px; padding: 0 6px;
  background: var(--surface); border: 1px solid var(--border-strong); border-radius: 5px;
  box-shadow: var(--keycap-shadow);
  font-family: var(--font-mono); font-size: 11px; line-height: 1; color: var(--text-quiet);
  pointer-events: none; transition: transform 90ms var(--ease), color 90ms var(--ease),
  border-color 90ms var(--ease), box-shadow 90ms var(--ease), opacity 90ms var(--ease);
}
.keycap-esc { opacity: 0; }
.searchwrap:focus-within .keycap-slash { opacity: 0; }
.searchwrap:focus-within .keycap-esc { opacity: 1; }

.searchwrap.is-struck .keycap-slash {
  transform: translateY(1px); color: var(--accent-ink-wash); border-color: var(--accent);
  box-shadow: inset 0 1px 0 rgb(255 255 255 / .1), 0 0 0 3px var(--accent-wash); opacity: 1;
}
.searchwrap.is-struck .keycap-esc { opacity: 0; }

.iconbtn {
  position: relative; flex: 0 0 auto; display: inline-flex; align-items: center;
  justify-content: center; width: 40px; height: 40px; background: transparent;
  border: 1px solid var(--border); border-radius: var(--r-sm); color: var(--text-muted);
  cursor: pointer;
  transition: color var(--dur) var(--ease), border-color var(--dur) var(--ease),
  background var(--dur) var(--ease);
}
.iconbtn::before { width: var(--tap); }
@media (hover: hover) {
  .iconbtn:hover { color: var(--text); border-color: var(--border-strong); background: var(--ghost-hover); }
}
.i-sun { display: none; }
:root[data-theme="dark"] .i-sun { display: block; }
:root[data-theme="dark"] .i-moon { display: none; }

/* 4. hero */

.hero {
  position: relative; isolation: isolate; overflow: hidden;
  padding-block: clamp(var(--space-7), 9vw, var(--space-9)) var(--space-8);
}

/* the only atmosphere on the page: one noise layer, hero-scoped */
.hero::after {
  content: ""; position: absolute; inset: 0; z-index: -2; background-image: var(--noise-img);
  opacity: var(--noise-alpha); pointer-events: none;
  -webkit-mask-image: linear-gradient(to bottom, #000 20%, transparent 92%);
  mask-image: linear-gradient(to bottom, #000 20%, transparent 92%);
}

.hero-inner {
  display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between;
  gap: var(--space-4) var(--space-5);
}

.hero-copy { flex: 1 1 22rem; min-width: 0; }

h1 {
  position: relative; display: inline-block; font-size: var(--fs-hero); line-height: .95; white-space: nowrap;
}
h1 .mark { width: .3em; height: .3em; vertical-align: 0; margin: 0 .05em 0 .02em; }
/* hand-drawn brush stroke under the word */
h1::after {
  content: ""; display: block; height: .3em; margin: -.08em 0 0 .06em;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 300 20' preserveAspectRatio='none'%3E%3Cpath d='M3 12c40-6 90-9 150-7 45 1 90 5 144 9' fill='none' stroke='%23e2691c' stroke-width='5' stroke-linecap='round' opacity='.85'/%3E%3C/svg%3E") no-repeat left center / 100% 100%;
}
/* one soft radial glow, behind the h1 only */
h1::before {
  content: ""; position: absolute; z-index: -1; left: -12%; top: 50%; width: 130%; height: 420%;
  transform: translateY(-50%);
  background: radial-gradient(50% 50% at 30% 50%, var(--glow) 0%, transparent 72%);
  pointer-events: none;
}

.tagline {
  margin-top: var(--space-5); font-size: 1.125rem; font-weight: 500; line-height: 1.7;
  color: var(--text); word-break: keep-all; text-wrap: balance; max-width: 34ch;
}

.lede {
  margin-top: var(--space-2); color: var(--text-muted); line-height: 1.7; word-break: keep-all;
  max-width: 46ch;
}


/* 5. toolbar */

.toolbar {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: var(--space-3) var(--space-4); padding-bottom: var(--space-4);
}

.tagnav {
  display: flex; flex-wrap: wrap; gap: var(--space-2); min-width: 0; flex: 1 1 20rem;
  min-height: 44px; padding: 4px; margin: -4px; align-content: flex-start;
}
@media (max-width: 40rem) {
  .tagnav {
    flex-wrap: nowrap; overflow-x: auto; overflow-y: hidden; height: 44px;
    scrollbar-width: thin; scroll-padding-inline: 4px; overscroll-behavior-x: contain;
    -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent);
    mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent);
  }
}

.chip {
  position: relative; flex: 0 0 auto; display: inline-flex; align-items: center;
  justify-content: center; gap: var(--space-1); min-width: var(--tap); height: var(--chip-h);
  padding: 0 14px; background: transparent; border: 1px solid var(--border);
  border-radius: var(--r-pill); font-size: var(--fs-meta); color: var(--text-muted);
  white-space: nowrap; cursor: pointer;
  transition: color var(--dur) var(--ease), border-color var(--dur) var(--ease),
  background var(--dur) var(--ease);
}
/* 4px each way = half the row gap: targets meet, never overlap */
.chip::before { width: calc(100% + 2px); }
.chip .n { font-family: var(--font-mono); font-size: 11px; color: var(--text-quiet); }
@media (hover: hover) {
  .chip:hover { color: var(--text); border-color: var(--border-strong); }
}
.chip[aria-pressed="true"] {
  color: var(--accent-ink-wash);
  border-color: color-mix(in srgb, var(--accent) 45%, transparent);
  background: var(--accent-wash);
}
.chip[aria-pressed="true"] .n { color: var(--accent-ink-wash); }

.statusline {
  display: flex; align-items: center; gap: var(--space-3); margin-left: auto; min-height: 20px;
  font-size: var(--fs-meta); color: var(--text-muted); white-space: nowrap;
}
.checked { color: var(--text-quiet); }
.checked:empty { display: none; }

/* 6. grid + cards */

/* auto-FILL: one result keeps its column width. min() stops 360px overflow. */
.grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(min(17rem, 100%), 1fr));
  gap: var(--space-4); padding-bottom: var(--space-8); align-content: start;
}

.cell { position: relative; display: flex; min-width: 0; transition: transform var(--dur) var(--ease); }
.cell > .card { flex: 1 1 auto; min-width: 0; }

.card {
  position: relative; display: flex; flex-direction: column; min-height: var(--card-min);
  padding: var(--space-4); background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r-card); overflow: hidden;
  transition: border-color var(--dur) var(--ease), background var(--dur) var(--ease);
}

/* a single accent hairline draws itself along the top edge on hover/focus */
.card::after {
  content: ""; position: absolute; inset: 0 0 auto 0; height: 1px; background: var(--accent);
  transform: scaleX(0); transform-origin: left; transition: transform 220ms var(--ease);
}

@media (hover: hover) {
  .cell.is-link:hover { transform: translateY(-3px); }
  .cell.is-link:hover > a.card { background: var(--raised-hover); border-color: var(--border-strong); }
  .cell.is-link:hover > a.card::after { transform: scaleX(1); }
}
a.card:focus-visible { outline-offset: 3px; }   /* clears the 12px card radius */
a.card:focus-visible::after { transform: scaleX(1); }

.card-repo {
  position: absolute; top: 9px; right: 9px; z-index: 2; display: inline-flex;
  align-items: center; justify-content: center; width: 34px; height: 34px;
  border: 1px solid transparent; border-radius: var(--r-sm); color: var(--text-quiet);
  transition: color var(--dur) var(--ease), border-color var(--dur) var(--ease),
  background var(--dur) var(--ease);
}
/* 34px tile, 44px target — it sits above the card link, so the overlay is safe */
.card-repo::before { width: var(--tap); }
@media (hover: hover) {
  .card-repo:hover { color: var(--accent-ink); border-color: var(--border-strong); background: var(--bg-sunken); }
}
.cell.has-repo .card-top { padding-inline-end: 32px; }

.card-top { display: flex; align-items: flex-start; gap: var(--space-3); margin-bottom: var(--space-3); }

.card-icon {
  flex: 0 0 auto; display: flex; align-items: center; justify-content: center; width: 32px;
  height: 32px; border: 1px solid var(--border); border-radius: var(--r-sm); font-size: 17px;
  line-height: 1; overflow: hidden;
}
.card-icon.is-monogram {
  background: var(--accent-wash); border-color: transparent; color: var(--accent-ink-wash);
  font-family: var(--font-mono); font-size: 12px; font-weight: 500; letter-spacing: .02em;
}

.card-head {
  flex: 1 1 auto; min-width: 0; display: flex; flex-wrap: wrap; align-items: center;
  gap: var(--space-1) var(--space-2); padding-top: 3px;
}

.card-title {
  font-size: var(--fs-card); font-weight: 500; letter-spacing: -0.01em; line-height: 1.3;
  text-wrap: balance; overflow-wrap: anywhere;
}

.stage {
  font-family: var(--font-mono); font-size: 10px; text-transform: uppercase;
  letter-spacing: .08em; color: var(--text-muted); border: 1px solid var(--border);
  border-radius: 4px; padding: 2px 5px; line-height: 1; max-width: 12ch; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap;
}
/* unknown stage: verbatim, dashed, never coloured or sorted as if up */
.stage.is-unknown {
  border-style: dashed; border-color: var(--border-dashed); text-transform: none;
  letter-spacing: .04em;
}

.badge-new {
  font-family: var(--font-mono); font-size: 10px; font-weight: 500; letter-spacing: .08em;
  color: var(--accent-ink-wash); background: var(--accent-wash); border-radius: 4px;
  padding: 3px 6px; line-height: 1;
}

/* "Enter opens this one" — only while a query is active */
.enter-hint {
  display: inline-flex; align-items: center; justify-content: center; min-width: 18px;
  height: 18px; padding: 0 4px; border: 1px solid var(--border-strong); border-radius: 4px;
  font-family: var(--font-mono); font-size: 10px; line-height: 1; color: var(--text-quiet);
}

.card-desc {
  display: -webkit-box; -webkit-line-clamp: 3; line-clamp: 3; -webkit-box-orient: vertical;
  overflow: hidden; min-height: 4.95em; font-size: var(--fs-desc); line-height: 1.65;
  color: var(--text-muted); word-break: keep-all;
}

.card-note {
  display: -webkit-box; -webkit-line-clamp: 1; line-clamp: 1; -webkit-box-orient: vertical;
  overflow: hidden; margin-top: var(--space-2); min-height: 1.5em; font-size: 11.5px;
  line-height: 1.5; color: var(--text-quiet); word-break: keep-all;
}

.card-foot {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-3);
  margin-top: auto; padding-top: var(--space-4); min-height: 20px;
}

.card-tags { display: flex; flex-wrap: wrap; gap: var(--space-1) 6px; min-width: 0; }
.tag {
  font-size: 11px; line-height: 1.45; color: var(--text-quiet); border: 1px solid var(--border);
  border-radius: var(--r-pill); padding: 1px 8px; white-space: nowrap;
}

.card.is-muted { background: transparent; border-style: dashed; border-color: var(--border-dashed); }
.card.is-muted .card-title { color: var(--text-muted); font-weight: 400; }
.card.is-muted .card-icon { filter: grayscale(1); }
.card.is-muted .card-icon.is-monogram { background: var(--bg-sunken); color: var(--text-muted); filter: none; }
@media (hover: hover) {
  .cell.is-link:hover > a.card.is-muted { background: transparent; border-color: var(--border-strong); }
}

/* 7. health */

.health {
  flex: 0 0 auto; display: inline-flex; align-items: center; gap: 6px; font-size: 11.5px;
  color: var(--text-muted); white-space: nowrap;
}
.dot { width: 8px; height: 8px; border-radius: 50%; background: var(--muted-dot); flex: 0 0 auto; }
.h-ok .dot { background: var(--ok); }
.h-warn .dot { background: var(--warn); }
.h-down .dot { background: var(--down); }
.h-num {
  font-family: var(--font-mono);
  font-size: 11px;
  font-variant-numeric: tabular-nums;
  color: var(--text-quiet);   /* was opacity:.85 → 3.85:1 — a response time, not decor */
}

/* 8. skeletons */

.is-skeleton { pointer-events: none; }
.is-skeleton span:not(.card-top) {
  display: block; background: var(--skeleton); border-radius: var(--r-pill);
  background-image: linear-gradient(90deg, transparent, var(--skeleton-hi), transparent);
  background-size: 220% 100%; background-repeat: no-repeat;
  animation: shimmer 1.6s var(--ease) infinite;
}
.is-skeleton .card-top > :first-child {
  flex: 0 0 auto; width: 32px; height: 32px; border-radius: var(--r-sm);
}
.is-skeleton .card-top > :last-child { flex: 1 1 auto; max-width: 44%; height: .8em; }
.is-skeleton > :nth-child(2) { height: .65em; }
.is-skeleton > :nth-child(3) { width: 72%; height: .65em; margin-top: 10px; }
.is-skeleton > :nth-child(4) { width: 54px; height: 14px; margin-top: auto; }
.is-skeleton:nth-child(2n) .card-top > :last-child { max-width: 58%; }
@keyframes shimmer {
  from { background-position: 140% 0; }
  to   { background-position: -60% 0; }
}

/* ---------- 9. Empty / error / no-JS states --------------- */

.state {
  display: flex; flex-direction: column; align-items: center; text-align: center;
  gap: var(--space-3); padding-block: var(--space-8) var(--space-9);
}
.state-mark {
  font-family: var(--font-mono);
  font-size: 1.5rem;
  letter-spacing: -0.02em;
  color: var(--text-faint);   /* was --text-muted at opacity:.45 → 1.86:1 */
  margin-bottom: var(--space-2);
}

.state-title {
  font-size: 1.125rem; font-weight: 500; word-break: keep-all; overflow-wrap: anywhere;
  text-wrap: balance; max-width: 32ch;
}
.state-sub { font-size: var(--fs-meta); color: var(--text-muted); word-break: keep-all; max-width: 40ch; }
.state-btn {
  margin-top: var(--space-2); height: var(--tap); padding: 0 20px; background: transparent;
  border: 1px solid var(--border-strong); border-radius: var(--r-pill);
  font-size: var(--fs-meta); color: var(--text); cursor: pointer;
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease),
  color var(--dur) var(--ease);
}
@media (hover: hover) {
  .state-btn:hover { background: var(--ghost-hover); border-color: var(--accent); color: var(--accent-ink); }
}

.noscript-note {
  max-width: 46ch; margin-inline: auto; padding-block: var(--space-8) var(--space-9);
  color: var(--text-muted); font-size: var(--fs-meta); line-height: 1.7; text-align: center;
  word-break: keep-all;
}
.noscript-note a { border-bottom: 1px solid var(--border-strong); }
.noscript-note .en { display: block; margin-top: var(--space-2); color: var(--text-quiet); }

/* 10. footer */

.foot { border-top: 1px solid var(--border); }
.foot-inner {
  display: flex; flex-wrap: wrap; align-items: baseline; justify-content: center;
  gap: var(--space-2) var(--space-4); padding-block: var(--space-5) var(--space-6);
}
.foot-line { font-size: var(--fs-meta); color: var(--text-muted); word-break: keep-all; }

/* 10b. maintenance card + notice */
.card.is-down { cursor: default; }
.card.is-down .card-title { color: var(--text-muted); }
.card.is-down .card-icon { filter: grayscale(.6); }
.card.is-down:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.notice { position: fixed; inset: 0; z-index: 60; display: grid; place-items: center; padding: var(--space-5); background: rgba(36, 25, 15, .45); backdrop-filter: blur(2px); }
.notice-card { width: min(100%, 380px); padding: var(--space-6) var(--space-5) var(--space-5); text-align: center; background: var(--surface); border: 1px solid var(--border); border-radius: 16px; box-shadow: 0 24px 60px rgba(0, 0, 0, .25); }
.notice-mark { font-size: 2rem; line-height: 1; margin-bottom: var(--space-3); }
.notice-title { font-size: 1.125rem; font-weight: 600; word-break: keep-all; }
.notice-text { margin-top: var(--space-2); color: var(--text-muted); line-height: 1.7; word-break: keep-all; }
.notice-btn { margin-top: var(--space-5); height: var(--tap); padding: 0 24px; border: 0; border-radius: var(--r-pill); background: var(--accent); color: #fff; font-weight: 600; cursor: pointer; }
.notice-btn:hover { background: var(--accent-ink); }

/* 11. motion */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important; animation-iteration-count: 1 !important;
    transition-duration: .01ms !important; scroll-behavior: auto !important;
  }
  @media (hover: hover) {
    .cell.is-link:hover { transform: none; }
  }
  .card::after { transition: none; }
  .searchwrap.is-struck .keycap-slash { transform: none; }
  .is-skeleton span:not(.card-top) { background-image: none; animation: none; }
}
