/*
 * The ONE SSR topbar's stylesheet (templates/fragments/site-topbar.html), linked by every
 * Thymeleaf page — blog, templates, events, read — at /site-assets/site-topbar.css (WebConfig serves
 * classpath:/site-chrome/, the same directory the shared footer's sheet is packed into). The
 * React public pages draw LandingTopBar from the same item list (shared/chrome/site-topbar.json);
 * the styling is each renderer's own.
 *
 * ONE palette, shared with the SPA: every --st-* value equals the matching --color-* token in
 * frontend/src/index.css (`:root` = the light `@theme` block, `html.dark` = the `.dark` block).
 * DesignTokenParityTest reads this file and compares each value against index.css, so a
 * hand-tuned colour here is a red run. The theme itself is picked by the anti-flash script each
 * page carries in <head> (localStorage["litmemo-theme"] → OS preference → dark).
 */

:root {
  color-scheme: light;
  --st-bg: #faf8f5;          /* background */
  --st-fg: #1a1a1a;          /* foreground */
  --st-muted: #6b6159;       /* muted-foreground */
  --st-primary: #7d6340;     /* primary */
  --st-primary-fg: #ffffff;  /* primary-foreground */
  --st-border: #9e8e7e;      /* border */
  --st-card: #ffffff;        /* card — the bar's translucent surface, the dropdowns */
  --st-font: "Swei Spring Sugar", "Noto Sans TC", "PingFang TC", "Microsoft JhengHei", system-ui, sans-serif;
}

html.dark {
  color-scheme: dark;
  --st-bg: #0f0d0a;
  --st-fg: #e8e0d4;
  --st-muted: #978b7b;
  --st-primary: #c4a574;
  --st-primary-fg: #0f0d0a;
  --st-border: #504536;
  --st-card: #1a1610;
}

/* The bar's face follows the INTERFACE language, the one the page's brand font stylesheet was fetched for
   (PublicAppFonts.addTo prints it as the bar's own lang, appFontLang). Not <html lang>: on a work's page in the
   serial reader that is the WORK's language, so a Japanese serial read with the zh-TW interface asked for
   "Swei Spring Sugar JP" while only the TC sheet was loaded, and the logo fell back to Hiragino / Noto Sans JP.
   :lang() still matches an inherited <html lang> on a host that prints no lang on the bar. */
.st-topbar:lang(ja) { --st-font: "Swei Spring Sugar JP", "Hiragino Maru Gothic ProN", "Hiragino Sans", "Noto Sans JP", "Yu Gothic UI", system-ui, sans-serif; }
/* English: the Latin punctuation face (U+2018-201F, U+2022, U+2026; linked on English pages only) ahead of Swei. */
.st-topbar:lang(en) { --st-font: "LM Latin Punctuation", "Swei Spring Sugar", "Noto Sans TC", "PingFang TC", "Microsoft JhengHei", system-ui, sans-serif; }
.st-topbar:lang(zh-Hans) { --st-font: "Swei Spring Sugar SC", "Noto Sans SC", "PingFang SC", "Microsoft YaHei", system-ui, sans-serif; }

/* ---- The bar: sticky, translucent card surface so the page shows through the blur ---- */
.st-topbar {
  position: sticky; top: 0; z-index: 50;
  font-family: var(--st-font);
  border-bottom: 1px solid var(--st-border);
  background: var(--st-card);
  background: color-mix(in srgb, var(--st-card) 85%, transparent);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}
/* Logo on the LEFT, every action in ONE group on the RIGHT. Not space-between: with three
   children that strands the lone CTA midway on a phone; the auto margin on .st-nav parks all
   the leftover between the logo and the actions instead. */
.st-inner { display: flex; align-items: center; gap: 0.75rem; height: 3.5rem; max-width: 72rem; margin: 0 auto; padding: 0 1.25rem; }
.st-logo {
  display: flex; align-items: center; gap: 0.375rem; min-width: 0;
  font-size: 1.25rem; font-weight: 700; letter-spacing: 0.02em; color: var(--st-primary); text-decoration: none;
  white-space: nowrap;
}
.st-logo:hover { opacity: 0.85; }
.st-logo-img { height: 1.5rem; width: auto; }

.st-nav { display: flex; align-items: center; gap: 1.25rem; }
.st-link {
  font: inherit; font-size: 0.875rem; color: var(--st-muted); text-decoration: none;
  background: none; border: none; padding: 0; margin: 0; cursor: pointer; transition: color 0.15s;
}
.st-link:hover, .st-link.is-active { color: var(--st-primary); }
.st-nav .st-link, .st-signin { white-space: nowrap; }
.st-cta {
  display: inline-block; padding: 0.375rem 1rem; border-radius: 0.375rem; white-space: nowrap;
  font-size: 0.875rem; font-weight: 500; text-decoration: none;
  background: var(--st-primary); color: var(--st-primary-fg);
}
/* Hover darkens whatever primary is (brown in light, tan in dark) instead of a second hex. */
.st-cta:hover { filter: brightness(0.9); }
.st-link:focus-visible, .st-cta:focus-visible, .st-burger:focus-visible, .st-lang > summary:focus-visible { outline: 2px solid var(--st-primary); outline-offset: 2px; }

/* ---- Hamburger (phones only) ---- */
.st-burger {
  display: none; align-items: center; justify-content: center; width: 2.25rem; height: 2.25rem;
  background: none; border: none; padding: 0; cursor: pointer; color: var(--st-muted);
}
.st-burger:hover { color: var(--st-primary); }
.st-burger svg { width: 1.375rem; height: 1.375rem; }

/* ---- The phone menu: a column under the bar, opened by the burger (data-topbar-menu.is-open) ---- */
.st-menu {
  display: none; flex-direction: column; gap: 0.25rem; padding: 0.75rem 1.25rem 1rem;
  border-top: 1px solid var(--st-border);
  background: var(--st-card);
  background: color-mix(in srgb, var(--st-card) 95%, transparent);
}
.st-menu .st-link { display: block; padding: 0.5rem 0; text-align: start; width: 100%; }
.st-menu .st-cta { display: block; text-align: center; margin-top: 0.375rem; }

/* ---- Language switcher: a pure-CSS <details>. Desktop = globe + chevron with an absolute
   dropdown; in the phone menu = an inline accordion. ---- */
.st-lang > summary {
  list-style: none; cursor: pointer; display: inline-flex; align-items: center; gap: 0.3rem;
  font-size: 0.875rem; color: var(--st-muted); transition: color 0.15s;
}
.st-lang > summary::-webkit-details-marker { display: none; }
.st-lang > summary::marker { content: ""; }
.st-lang > summary:hover { color: var(--st-primary); }
.st-lang-globe { width: 1.05rem; height: 1.05rem; flex-shrink: 0; }
.st-lang-chevron { width: 0.8rem; height: 0.8rem; flex-shrink: 0; transition: transform 0.2s; }
.st-lang[open] .st-lang-chevron { transform: rotate(180deg); }
.st-lang-menu a { display: block; font-size: 0.875rem; color: var(--st-muted); text-decoration: none; transition: color 0.15s; }
.st-lang-menu a:hover { color: var(--st-primary); }
.st-lang-menu a[aria-current="true"] { color: var(--st-primary); font-weight: 600; }
.st-actions .st-lang { position: relative; display: inline-flex; align-items: center; }
.st-actions .st-lang-current { display: none; }
.st-actions .st-lang-menu {
  position: absolute; top: calc(100% + 0.6rem); inset-inline-end: 0; min-width: 9rem; padding: 0.35rem 0;
  display: flex; flex-direction: column;
  background: var(--st-card); border: 1px solid var(--st-border); border-radius: 0.5rem;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.14);
}
.st-actions .st-lang-menu a { padding: 0.5rem 1rem; }
.st-menu .st-lang { display: block; }
.st-menu .st-lang > summary { padding: 0.5rem 0; }
.st-menu .st-lang-menu { display: flex; flex-direction: column; gap: 0.1rem; padding-inline-start: 1.5rem; margin-top: 0.1rem; }
.st-menu .st-lang-menu a { padding: 0.4rem 0; }

/* ---- Light / dark toggle. Both glyphs are in the markup; html.dark decides which shows (the
   one for the theme a click switches TO), so the icon is right before any script runs. ---- */
.st-theme-toggle { display: inline-flex; align-items: center; gap: 0.35rem; text-align: start; }
.st-theme-toggle svg { width: 1.05rem; height: 1.05rem; flex-shrink: 0; }
.st-theme-sun { display: none; }
html.dark .st-theme-sun { display: inline-block; }
html.dark .st-theme-moon { display: none; }
.st-actions .st-theme-label { display: none; }
.st-menu .st-theme-toggle { display: flex; }

/* ---- The cross link to the other side (docs/product/site-navigation-design.md §二): drawn exactly like the
   bar's other items (.st-link's colour, no underline). It is never marked is-active, so it never reads as
   "the page you are on"; its place in the bar (the row's end / beside 登入) says it goes elsewhere. ---- */
.st-cross { white-space: nowrap; }

/* The mode's items sit right after the logo; the actions take the leftover on the right. Every control
   the script hides carries [hidden]; the display rules here would win over the UA's [hidden] without this. */
.st-nav { margin-inline-start: 0.5rem; }
.st-actions { display: flex; align-items: center; gap: 1rem; margin-inline-start: auto; flex-shrink: 0; }
.st-topbar [hidden] { display: none !important; }

/* ---- 類型▾: a pure-CSS <details> dropdown of the genres (a two-column grid in the row, a list in the menu) ---- */
.st-genres > summary { list-style: none; display: inline-flex; align-items: center; }
.st-genres > summary::-webkit-details-marker { display: none; }
.st-genres > summary::marker { content: ""; }
/* A down chevron drawn from two physical borders: logical borders would swap sides in RTL and turn it sideways. */
.st-genres > summary::after { content: ""; display: inline-block; flex-shrink: 0; margin-inline-start: 0.35rem; width: 0.35rem; height: 0.35rem; border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor; transform: translateY(-2px) rotate(45deg); }
.st-genre-menu a { display: block; font-size: 0.875rem; color: var(--st-muted); text-decoration: none; }
.st-genre-menu a:hover { color: var(--st-primary); }
/* A genre with no work yet: the same box as a row, greyed, no pointer (it is a <span>, not a link). */
.st-genre-menu .st-genre-empty { display: block; font-size: 0.875rem; color: var(--st-muted); opacity: 0.45; cursor: default; }
/* A flex box: as a block, details keeps the 16px body line box as a strut, and its inline-flex summary
   sits ~1.4px below the sibling links (measured 2026-10-10). */
.st-nav .st-genres { position: relative; display: flex; align-items: center; }
.st-nav .st-genre-menu {
  position: absolute; top: calc(100% + 0.6rem); inset-inline-start: -0.75rem; z-index: 5; min-width: 15rem; padding: 0.5rem;
  display: grid; grid-template-columns: 1fr 1fr; gap: 0.1rem 0.5rem;
  background: var(--st-card); border: 1px solid var(--st-border); border-radius: 0.5rem; box-shadow: 0 8px 24px rgba(0, 0, 0, 0.14);
}
.st-nav .st-genre-menu a, .st-nav .st-genre-menu .st-genre-empty { padding: 0.4rem 0.5rem; white-space: nowrap; }
.st-menu .st-genres > summary { padding: 0.5rem 0; }
.st-menu .st-genre-menu { display: grid; grid-template-columns: 1fr 1fr; gap: 0.1rem 0.75rem; padding-inline-start: 1rem; }
.st-menu .st-genre-menu a, .st-menu .st-genre-menu .st-genre-empty { padding: 0.4rem 0; }

/* ---- 搜尋 (閱讀 only) ---- */
.st-search { margin: 0; }
.st-search input {
  font: inherit; font-size: 0.8125rem; width: 10rem; padding: 0.35rem 0.7rem; border-radius: 999px;
  border: 1px solid var(--st-border); background: transparent; color: var(--st-fg);
}
.st-search input::placeholder { color: var(--st-muted); }
.st-search input:focus { outline: 2px solid var(--st-primary); outline-offset: 1px; }
.st-menu .st-search { margin-bottom: 0.25rem; }
.st-menu .st-search input { width: 100%; box-sizing: border-box; font-size: 1rem; padding: 0.5rem 0.85rem; }

/* ---- Signed in: the bell and the account menu (drawn by the bar's script) ---- */
.st-account { display: flex; align-items: center; gap: 0.5rem; }
/* Flex, so each wrapper is exactly its button's box. As plain blocks they set the inline-flex button on a text
   line box: an image avatar's baseline is its bottom edge, so the line's descent hung below it, .st-acc grew
   past 32px, and centring that taller wrapper lifted the avatar 3–4px above the bell, theme and language icons. */
.st-bell, .st-acc { position: relative; display: flex; }
.st-icon-btn, .st-avatar-btn { display: inline-flex; align-items: center; justify-content: center; background: none; border: none; padding: 0; cursor: pointer; color: var(--st-muted); }
.st-icon-btn { position: relative; width: 2.25rem; height: 2.25rem; border-radius: 999px; }
.st-icon-btn:hover { color: var(--st-primary); }
.st-icon-btn svg { width: 1.25rem; height: 1.25rem; }
.st-badge {
  position: absolute; top: 0.1rem; inset-inline-end: 0.05rem; min-width: 1rem; height: 1rem; padding: 0 0.25rem; border-radius: 999px;
  font-size: 0.625rem; font-weight: 600; line-height: 1rem; text-align: center; background: var(--st-primary); color: var(--st-primary-fg);
}
.st-avatar {
  width: 2rem; height: 2rem; border-radius: 999px; display: inline-flex; align-items: center; justify-content: center;
  font-size: 0.875rem; font-weight: 600; color: var(--st-primary); background: color-mix(in srgb, var(--st-primary) 18%, transparent);
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--st-primary) 35%, transparent);
}
.st-avatar-img { object-fit: cover; }
.st-icon-btn:focus-visible, .st-avatar-btn:focus-visible { outline: 2px solid var(--st-primary); outline-offset: 2px; border-radius: 999px; }
.st-pop {
  position: absolute; inset-inline-end: 0; top: calc(100% + 0.5rem); z-index: 60; width: 15rem; max-width: calc(100vw - 1.5rem);
  padding: 0.25rem 0; background: var(--st-card); border: 1px solid var(--st-border); border-radius: 0.75rem;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.18); color: var(--st-fg);
}
.st-bell-panel { width: 20rem; }
.st-pop-head, .st-acc-head { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; padding: 0.6rem 0.85rem; border-bottom: 1px solid var(--st-border); }
.st-pop-title, .st-acc-name { font-size: 0.875rem; font-weight: 600; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.st-acc-plan { flex-shrink: 0; font-size: 0.625rem; font-weight: 600; padding: 0.15rem 0.45rem; border-radius: 999px; color: var(--st-primary); background: color-mix(in srgb, var(--st-primary) 18%, transparent); }
.st-pop-action { font: inherit; font-size: 0.75rem; color: var(--st-primary); background: none; border: none; padding: 0; cursor: pointer; }
.st-bell-list { max-height: min(60vh, 24rem); overflow-y: auto; }
.st-bell-row { display: block; padding: 0.6rem 0.85rem; font-size: 0.8125rem; line-height: 1.5; color: var(--st-fg); text-decoration: none; }
.st-bell-row.is-unread { background: color-mix(in srgb, var(--st-primary) 10%, transparent); }
.st-bell-row:hover { background: color-mix(in srgb, var(--st-primary) 16%, transparent); }
.st-bell-empty { margin: 0; padding: 1rem 0.85rem; font-size: 0.8125rem; color: var(--st-muted); }
.st-pop-foot { display: block; padding: 0.6rem 0.85rem; border-top: 1px solid var(--st-border); font-size: 0.8125rem; color: var(--st-primary); text-decoration: none; }
.st-acc-item {
  display: block; width: 100%; box-sizing: border-box; text-align: start; font: inherit; font-size: 0.875rem; padding: 0.5rem 0.85rem;
  color: var(--st-fg); background: none; border: none; text-decoration: none; cursor: pointer;
}
.st-acc-item:hover { background: color-mix(in srgb, var(--st-primary) 12%, transparent); }
.st-acc-logout { border-top: 1px solid var(--st-border); margin-top: 0.25rem; color: var(--st-muted); }

/* ---- Below 1024px: the row keeps the logo, the account corner (or the main button) and the burger; the
   items, the cross link, search, language, theme and 登入 move into the menu (search first, design §二). ---- */
@media (max-width: 1023px) {
  .st-nav, .st-actions .st-search, .st-actions .st-lang, .st-actions .st-theme-toggle, .st-actions .st-signin, .st-actions .st-cross { display: none; }
  .st-actions { gap: 0.5rem; }
  .st-burger { display: flex; flex-shrink: 0; }
  .st-menu.is-open { display: flex; }
  /* The bell and the avatar sit mid-row here, so their popups anchor to the bar's right edge (the header is
     the positioned ancestor) instead of to their own button — anchored to the bell, its panel ran off the left. */
  .st-bell, .st-acc { position: static; }
  .st-pop { top: 100%; inset-inline-end: 0.75rem; }
}
/* Phones: tighter padding and a smaller main button. */
@media (max-width: 520px) {
  .st-inner { gap: 0.5rem; padding: 0 0.75rem; }
  .st-cta { font-size: 0.8125rem; padding: 0.3rem 0.65rem; }
}
/* ≤360px: the main button gives up a little more width so the logo and the account corner keep their room. */
@media (max-width: 360px) {
  .st-cta { font-size: 0.75rem; padding: 0.25rem 0.5rem; }
}
@media (prefers-reduced-motion: reduce) {
  .st-link, .st-lang > summary, .st-lang-menu a, .st-lang-chevron { transition: none; }
}

/* ---- Event banner: the creator-challenge bar right under the topbar on blog / templates pages
   (templates/fragments/event-banner.html). Lives in this sheet because every page that can show it already
   loads it — no extra request. Not sticky: it scrolls away with the page, the topbar stays. Same palette as
   the bar; the accent (--st-primary) tints the strip and fills only the badge and the button — the strip has to read
   as an announcement against the page, not as part of the topbar. The face is the page's own (inherit), since
   the bar sits outside .st-topbar. One line on desktop (the text ellipses), up to two on phones. ---- */
.evb { border-bottom: 2px solid var(--st-primary); background: color-mix(in srgb, var(--st-primary) 14%, var(--st-bg)); color: var(--st-fg); font-family: inherit; }
.evb[hidden] { display: none; }
.evb-inner { display: flex; align-items: center; gap: 0.75rem; max-width: 72rem; margin: 0 auto; padding: 0.65rem 1.25rem; box-sizing: border-box; }
.evb-text {
  flex: 1 1 auto; min-width: 0; margin: 0; font-size: 0.875rem; line-height: 1.5;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* The phase as a solid badge: the one word a skimming eye catches first. */
.evb-label {
  display: inline-block; vertical-align: 0.1em; margin-inline-end: 0.625rem; padding: 0.1rem 0.65rem; border-radius: 999px;
  background: var(--st-primary); color: var(--st-primary-fg); font-size: 0.75rem; font-weight: 700; line-height: 1.4;
}
.evb-title { font-size: 1rem; font-weight: 700; margin-inline-end: 0.5rem; }
.evb-meta { color: var(--st-muted); }
/* The date never breaks across lines (a wrapped「2026/11/10 | 24:00」reads as two values). */
.evb-date { unicode-bidi: isolate; white-space: nowrap; }
.evb-cta {
  flex-shrink: 0; display: inline-flex; align-items: center; font-size: 0.875rem; font-weight: 600; line-height: 1.25rem;
  padding: 0.35rem 1rem; border-radius: 999px; background: var(--st-primary); color: var(--st-primary-fg); text-decoration: none; white-space: nowrap;
}
.evb-cta:hover { opacity: 0.9; }
.evb-close {
  flex-shrink: 0; display: inline-flex; align-items: center; justify-content: center; width: 1.75rem; height: 1.75rem; padding: 0;
  margin-inline-start: -0.25rem; border: none; border-radius: 999px; background: none; color: var(--st-muted); cursor: pointer;
}
.evb-close svg { width: 1rem; height: 1rem; }
.evb-close:hover { color: var(--st-fg); background: color-mix(in srgb, var(--st-fg) 8%, transparent); }
.evb-cta:focus-visible, .evb-close:focus-visible { outline: 2px solid var(--st-primary); outline-offset: 2px; }
@media (max-width: 640px) {
  .evb-inner { gap: 0.5rem; padding: 0.55rem 0.75rem; }
  /* Two lines at most: the title may be long and the button must keep its room. */
  .evb-text { white-space: normal; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; font-size: 0.875rem; line-height: 1.5; }
  .evb-label { font-size: 0.6875rem; margin-inline-end: 0.4rem; }
  .evb-title { font-size: 0.9375rem; }
  .evb-cta { font-size: 0.8125rem; padding: 0.3rem 0.8rem; }
}
