:root {
  /* ---------- 2020s soft-UI neumorphism, cool-toned, emerald accent.
     --neu-light/--neu-dark are the two shadow tones a raised/recessed
     surface is carved out of --bg with (see the neumorphism pass near the
     end of this file). Dark is the default look; @media
     (prefers-color-scheme: light) below auto-switches for light-OS users,
     and an explicit [data-theme="light"/"dark"] (see js/app.js
     setupThemeToggle) always wins over both when the user picks one. ---------- */
  --bg: #333944;
  --panel: var(--bg);
  --panel-2: #2f343f;
  --elevated: #3a404d;
  --border: #454c59;
  --text: #e5e9ec;
  --muted: #8993a1;
  --accent: #1fb39a;
  --accent-ink: #06231a;
  --fav: #57c2c9;
  --danger: #d9667c;
  --neu-light: #404855;
  --neu-dark: #242831;
  --app-width: 900px;
  --gutter: 4.8rem;
  --cell-size: 58px;
  /* codepoints per grid row; grid.js switches this to 8 on mobile (see the
     max-width:768px media query) via D.setCols(), which also rebuilds the
     row model to match. */
  --cols: 16;
  /* glyph font: default follows the OS; toggled to Noto via [data-font] */
  --font-glyph: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue",
    "Noto Sans", "Noto Sans CJK JP", "Noto Color Emoji", sans-serif;

  /* attribute-group colors: shared by grid cells and the block picker swatch.
     Aurora (glowing teal/green/blue/violet) mixed with earthy tones
     (ochre/tan/umber), brightened from the original mix for readability
     while keeping the same calm, harmonious hue families. */
  --grp-letter: #d9bc8a;
  --grp-mark: #9483b8;
  --grp-number: #63c2a1;
  --grp-punct: #c09b7d;
  --grp-symbol: #63a4c2;
  --grp-emoji: #55c7a1;
  --grp-separator: #c9a17e;
  --grp-control: #7d6753;
  --grp-format: #a4917f;
  --grp-surrogate: #8874b8;
  --grp-private: #dba158;
  --grp-unassigned: #858575;

  /* age-era colors (chronological gradient): shared by grid cells and the
     block picker swatch when color mode = "age". 17 stops now (see ERAS in
     data.js) -- one per major version from 7.0 on. Sepia/earthy at the old
     end, shifting into aurora teal/blue/violet toward the present;
     brightened the same way as the group colors above. */
  --era-e1: #8a7050;
  --era-e2: #987a58;
  --era-e3: #a68061;
  --era-e4: #b8926a;
  --era-e5: #c7a276;
  --era-e6: #c2ac71;
  --era-e7: #a3b476;
  --era-e8: #78ba9c;
  --era-e9: #63b3a8;
  --era-e10: #58a8b9;
  --era-e11: #6091c0;
  --era-e12: #7383c7;
  --era-e13: #8878c6;
  --era-e14: #9673bf;
  --era-e15: #a874b7;
  --era-e16: #63a893;
  --era-e17: #73b3d8;
}

/* Noto stack: lists many script-specific Noto families so the browser falls
   back per glyph. Mostly relies on whichever Noto fonts are installed
   locally, except Symbols/Symbols 2/Math/Music, which are small enough that
   css/fonts-extended.css bundles them for every font mode (not just
   "extended") -- see the comment above that stylesheet's link in index.html. */
:root[data-font="noto"] {
  --font-glyph:
    "Noto Sans", "Noto Sans Symbols", "Noto Sans Symbols 2", "Noto Sans Math",
    "Noto Music", "Noto Sans CJK JP", "Noto Serif CJK JP",
    "Noto Sans Cuneiform", "Noto Sans Egyptian Hieroglyphs",
    "Noto Sans Linear B", "Noto Sans Linear A", "Noto Sans Cypro-Minoan",
    "Noto Sans Gothic", "Noto Sans Old Italic", "Noto Sans Runic",
    "Noto Sans Anatolian Hieroglyphs", "Noto Sans Nushu",
    "Noto Color Emoji", "Noto Sans Historic", sans-serif;
}

/* Extended stack: bundles ~85 script-specific Noto fonts for rare/historic
   scripts (e.g. Tangut [西夏文字], Hentaigana [変体仮名]), plus
   Symbols/Symbols 2/Math/Music for numeral systems (Mayan, Aegean, ...),
   mathematical alphanumeric symbols, and musical notation (Byzantine,
   Western, Ancient Greek) -- all otherwise tofu on most systems. See
   css/fonts-extended.css (generated by tools/fetch_rare_fonts.py) for the
   actual @font-face rules and fonts/*.woff2 for the files.
   CJK Unified Ideograph Extensions (planes 2-3) are NOT covered: verified
   Noto Sans/Serif CJK's cmap has none of Ext B-H even in the full 16MB OTF,
   so bundling it wouldn't help anyway; a non-Noto font (e.g. HanaMin) would
   be needed and is a separate, larger undertaking (see dev.md). CJK
   Unified/emoji stay local-font-only (via the "Noto" tier above) since
   those are each tens of MB on their own. */
:root[data-font="extended"] {
  --font-glyph:
    "Noto Sans", "Noto Serif",
    "Noto Sans Symbols", "Noto Sans Symbols 2", "Noto Sans Math", "Noto Music",
    "Noto Sans CJK JP", "Noto Serif CJK JP",
    "Noto Serif Tangut", "Noto Serif Hentaigana", "Noto Serif Ahom", "Noto Sans Nushu",
    "Noto Sans Cuneiform", "Noto Sans Egyptian Hieroglyphs", "Noto Sans Anatolian Hieroglyphs",
    "Noto Sans Linear A", "Noto Sans Linear B", "Noto Sans Cypriot", "Noto Sans Cypro Minoan",
    "Noto Sans Phoenician", "Noto Sans Lydian", "Noto Sans Lycian", "Noto Sans Carian",
    "Noto Sans Old Italic", "Noto Sans Gothic", "Noto Sans Runic",
    "Noto Sans Old Permic", "Noto Sans Ugaritic", "Noto Sans Old Persian",
    "Noto Sans Deseret", "Noto Sans Shavian", "Noto Sans Osmanya", "Noto Sans Osage",
    "Noto Sans Elbasan", "Noto Sans Caucasian Albanian", "Noto Sans Vithkuqi",
    "Noto Sans Imperial Aramaic", "Noto Sans Palmyrene", "Noto Sans Nabataean", "Noto Sans Hatran",
    "Noto Sans Old North Arabian", "Noto Sans Old South Arabian",
    "Noto Sans Manichaean", "Noto Sans Avestan",
    "Noto Sans Inscriptional Parthian", "Noto Sans Inscriptional Pahlavi", "Noto Sans Psalter Pahlavi",
    "Noto Sans Old Turkic", "Noto Sans Old Hungarian", "Noto Sans Hanifi Rohingya",
    "Noto Sans Old Sogdian", "Noto Sans Sogdian", "Noto Sans Chorasmian", "Noto Sans Elymaic",
    "Noto Sans Brahmi", "Noto Sans Kaithi", "Noto Sans Sora Sompeng", "Noto Sans Chakma",
    "Noto Sans Mahajani", "Noto Sans Sharada", "Noto Sans Khojki", "Noto Sans Multani",
    "Noto Sans Khudawadi", "Noto Sans Grantha", "Noto Sans Newa", "Noto Sans Tirhuta",
    "Noto Sans Siddham", "Noto Sans Modi", "Noto Sans Takri", "Noto Serif Dogra",
    "Noto Sans Warang Citi", "Noto Serif Dives Akuru", "Noto Sans Nandinagari",
    "Noto Sans Zanabazar Square", "Noto Sans Soyombo", "Noto Sans Pau Cin Hau",
    "Noto Sans Bhaiksuki", "Noto Sans Marchen", "Noto Sans Masaram Gondi", "Noto Sans Gunjala Gondi",
    "Noto Serif Makasar", "Noto Sans Mro", "Noto Sans Bassa Vah", "Noto Sans Pahawh Hmong",
    "Noto Sans Medefaidrin", "Noto Sans Miao", "Noto Sans Duployan",
    "Noto Serif Nyiakeng Puachue Hmong", "Noto Sans Wancho", "Noto Sans Mende Kikakui",
    "Noto Sans Adlam", "Noto Sans SignWriting", "Noto Sans Tai Viet",
    "Noto Color Emoji", "Noto Sans Historic", sans-serif;
}

@media (prefers-color-scheme: light) {
  :root {
    --bg: #e9edf0;
    --panel: var(--bg);
    --panel-2: #e1e6ea;
    --elevated: #f5f7f9;
    --border: #d2d9dd;
    --text: #20242a;
    --muted: #626b74;
    --accent: #0f9c8a;
    --accent-ink: #ffffff;
    --fav: #2f96a0;
    --danger: #c14c66;
    --neu-light: #ffffff;
    --neu-dark: #c3cbd0;
  }
}

/* Explicit theme override (js/app.js setupThemeToggle + the pre-paint
   <script> in index.html's <head>). An attribute selector on :root beats
   the media-query-wrapped :root above regardless of source order, so an
   explicit choice always wins over the OS setting; the media query above
   still governs the very first paint before any localStorage choice exists. */
:root[data-theme="dark"] {
  --bg: #333944;
  --panel: var(--bg);
  --panel-2: #2f343f;
  --elevated: #3a404d;
  --border: #454c59;
  --text: #e5e9ec;
  --muted: #8993a1;
  --accent: #1fb39a;
  --accent-ink: #06231a;
  --fav: #57c2c9;
  --danger: #d9667c;
  --neu-light: #404855;
  --neu-dark: #242831;
}

:root[data-theme="light"] {
  --bg: #e9edf0;
  --panel: var(--bg);
  --panel-2: #e1e6ea;
  --elevated: #f5f7f9;
  --border: #d2d9dd;
  --text: #20242a;
  --muted: #626b74;
  --accent: #0f9c8a;
  --accent-ink: #ffffff;
  --fav: #2f96a0;
  --danger: #c14c66;
  --neu-light: #ffffff;
  --neu-dark: #c3cbd0;
}

* {
  box-sizing: border-box;
  /* Disables the browser's own native tap-flash overlay (separate from any
     :active/.pressed CSS we control) -- otherwise, on the virtualized
     符号表 grid, a quick flash can still appear on whatever cell ends up
     under a touch point once scrolling swaps the underlying cells out. */
  -webkit-tap-highlight-color: transparent;
}

[hidden] {
  display: none !important;
}

html,
body {
  height: 100%;
  margin: 0;
  /* Prevents double-tap-to-zoom on mobile (the viewport meta's
     maximum-scale=1 alone doesn't reliably stop it on all browsers) --
     "manipulation" keeps normal scrolling/pinch-zoom, just drops the
     double-tap zoom gesture specifically. */
  touch-action: manipulation;
}

body {
  overflow: hidden;
  background: var(--bg);
  color: var(--text);
  font: 15px/1.5 system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue",
    "Noto Sans", "Noto Sans CJK JP", "Noto Color Emoji", sans-serif;
}

button {
  font: inherit;
  cursor: pointer;
}

