@danieldeusing/design 0.1.3 → 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- /*! danieldeusing-design v0.1.3 | MIT | https://github.com/danieldeusing/danieldeusing-design */
1
+ /*! danieldeusing-design v0.1.5 | MIT | https://github.com/danieldeusing/danieldeusing-design */
2
2
  /* ===== reset.css ===== */
3
3
  /*
4
4
  * danieldeusing-design — minimal reset.
@@ -618,3 +618,145 @@ html.anim-off .cursor-block {
618
618
  transform: translateY(0.12em);
619
619
  }
620
620
  }
621
+
622
+ /* ===== chrome.css ===== */
623
+ /*
624
+ * chrome.css — the app chrome kit: sticky header bar, fixed status footer,
625
+ * and the responsive site navigation (desktop `ls -l` dropdown, mobile
626
+ * burger with the footer folded in). Extracted from danieldeusing.de and
627
+ * the cockpit portal so every app ships the same chrome without rebuilding it.
628
+ *
629
+ * Markup contract (see templates/documentation.html for the full example):
630
+ *
631
+ * <a href="#top" class="skip-link">skip to content</a>
632
+ * <header class="bar">
633
+ * <a href="/" class="brand"><span class="glow">name</span><span class="cursor-block"></span></a>
634
+ * <button class="nav-burger" data-nav-toggle aria-controls="site-nav" aria-expanded="false">…☰ svg…</button>
635
+ * <nav aria-label="site" id="site-nav" class="site-nav">
636
+ * <details class="dropdown" id="nav">…ls-panel with .ls-row items…</details>
637
+ * <ul class="mobile-nav">…same links as .mobile-item ls-rows…</ul>
638
+ * <div class="mobile-footer">…footer controls folded in…</div>
639
+ * </nav>
640
+ * </header>
641
+ * …
642
+ * <footer class="status">…status-left + status-right…</footer>
643
+ *
644
+ * Behaviour: pair with `initBurgerNav()` from the runtime (adds the toggle +
645
+ * outside-click close). Breakpoint: 48rem.
646
+ */
647
+
648
+ /* ── a11y helpers ── */
649
+ .skip-link {
650
+ position: absolute; left: -999px; top: 0; z-index: 100;
651
+ background: var(--card); border: 1px solid var(--primary);
652
+ padding: 0.5rem 1rem; color: var(--primary);
653
+ }
654
+ .skip-link:focus { left: 0.5rem; top: 0.5rem; }
655
+ .visually-hidden {
656
+ position: absolute; width: 1px; height: 1px; overflow: hidden;
657
+ clip: rect(0 0 0 0); white-space: nowrap;
658
+ }
659
+
660
+ /* ── header bar (sticky) ── */
661
+ header.bar {
662
+ position: sticky; top: 0; z-index: 30;
663
+ display: flex; align-items: center; justify-content: space-between; gap: 1rem;
664
+ padding: 0.6rem 1.25rem; border-bottom: 1px solid var(--border); background: var(--card);
665
+ }
666
+ header.bar .brand { display: inline-flex; align-items: center; font-weight: 700; font-size: 1rem; }
667
+ header.bar .brand, header.bar .brand a { color: inherit; text-decoration: none; }
668
+ header.bar .dropdown summary { padding: 0.6rem 0.4rem; }
669
+ .bar-right { display: flex; align-items: center; gap: 1rem; flex-shrink: 0; }
670
+
671
+ /* ── status footer (fixed; hidden on mobile — folded into the burger) ── */
672
+ footer.status {
673
+ position: fixed; inset-inline: 0; bottom: 0; z-index: 50; min-height: 2rem;
674
+ display: flex; align-items: center; justify-content: space-between; gap: 1rem;
675
+ padding: 0.35rem 1.25rem; border-top: 1px solid var(--border); background: var(--card);
676
+ font-size: 0.7rem;
677
+ }
678
+ footer.status .dropdown summary, footer.status .anim-toggle { padding: 0.55rem 0.4rem; }
679
+ .status-left { color: var(--muted-foreground); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
680
+ .status-right { display: flex; align-items: center; gap: 1rem; flex-shrink: 0; }
681
+ .sep { width: 1px; height: 0.9rem; background: var(--border); }
682
+ .doc-link { color: var(--muted-foreground); text-decoration: none; transition: color 0.15s ease; }
683
+ .doc-link:hover { color: var(--primary); }
684
+
685
+ /* ── ls-listing rows (shared by the desktop dropdown + mobile menu) ── */
686
+ .ls-row { display: flex; align-items: baseline; gap: 0.9rem; }
687
+ .ls-perm { color: var(--muted-foreground); font-size: 0.72rem; letter-spacing: 0; }
688
+ .ls-row--sub .ls-name { padding-left: 1rem; }
689
+ .ls-panel { min-width: 17rem; left: auto !important; right: 0; }
690
+ #nav { position: relative; }
691
+
692
+ /* ── burger + mobile menu ── */
693
+ .nav-burger {
694
+ display: none; background: none; border: 0; color: var(--muted-foreground);
695
+ cursor: pointer; padding: 0.55rem; margin: -0.3rem -0.3rem -0.3rem 0;
696
+ }
697
+ .nav-burger:hover { color: var(--primary); }
698
+ .mobile-nav { display: none; list-style: none; margin: 0; padding: 0; }
699
+ .mobile-footer { display: none; }
700
+
701
+ @media (max-width: 48rem) {
702
+ .nav-burger { display: inline-flex; align-items: center; }
703
+
704
+ /* the nav becomes a full-width column under the sticky header */
705
+ .site-nav {
706
+ display: none; position: absolute; top: 100%; left: 0; right: 0; z-index: 40;
707
+ background: var(--card); border-bottom: 1px solid var(--border);
708
+ padding: 0.4rem 1.25rem 0.9rem; max-height: calc(100vh - 6rem); overflow-y: auto;
709
+ }
710
+ .site-nav.open { display: block; }
711
+ .site-nav > .dropdown { display: none; } /* desktop ls-dropdown replaced by the flat list */
712
+
713
+ .mobile-nav { display: flex; flex-direction: column; }
714
+ .mobile-nav .mobile-item {
715
+ display: flex; align-items: baseline; gap: 0.9rem; padding: 0.65rem 0;
716
+ text-decoration: none; color: var(--foreground); font-size: 0.9rem;
717
+ border-bottom: 1px solid var(--border);
718
+ }
719
+ .mobile-nav li:last-child .mobile-item { border-bottom: 0; }
720
+ .mobile-nav .mobile-item:active .ls-name,
721
+ .mobile-nav .mobile-item:hover .ls-name { color: var(--primary); }
722
+
723
+ /* footer content folded into the burger; the fixed footer disappears */
724
+ footer.status { display: none; }
725
+ .mobile-footer {
726
+ display: flex; flex-direction: column; gap: 0.55rem;
727
+ margin-top: 0.8rem; border-top: 1px solid var(--border); padding-top: 0.8rem;
728
+ font-size: 0.85rem;
729
+ }
730
+ .mobile-footer .doc-link { padding: 0.2rem 0; }
731
+ .mobile-footer .mobile-theme summary {
732
+ list-style: none; display: flex; align-items: center; gap: 0.5rem;
733
+ color: var(--muted-foreground); cursor: pointer; padding: 0.2rem 0;
734
+ }
735
+ .mobile-footer .mobile-theme summary::-webkit-details-marker { display: none; }
736
+ .mobile-footer .mf-chev { margin-left: auto; opacity: 0.7; }
737
+ .mobile-footer .mf-panel { display: flex; flex-direction: column; margin-top: 0.3rem; }
738
+ .mobile-footer .mf-panel .dropdown-item { text-align: left; padding: 0.4rem 0.6rem; }
739
+ .mobile-footer .anim-toggle {
740
+ display: inline-flex; gap: 0.5rem; align-items: center;
741
+ background: none; border: 0; padding: 0.2rem 0; color: var(--muted-foreground);
742
+ font: inherit; cursor: pointer;
743
+ }
744
+ }
745
+
746
+ /* ===== tooltip.css ===== */
747
+ /*
748
+ * tooltip.css — styles for the [data-tip] tooltip system (runtime/tooltip.js).
749
+ * The panel is a body-level singleton with position:fixed — it can never be
750
+ * clipped by overflow containers and always sits on top.
751
+ */
752
+ [data-tip] { cursor: help; }
753
+ span[data-tip], th[data-tip] { border-bottom: 1px dotted var(--muted-foreground); }
754
+
755
+ #ddtip {
756
+ position: fixed; z-index: 9999; display: none; max-width: 340px;
757
+ background: var(--background); color: var(--foreground);
758
+ border: 1px solid var(--muted-foreground); border-radius: 4px;
759
+ padding: 7px 10px; font-size: 0.72rem; line-height: 1.45; font-weight: 400;
760
+ text-align: left; white-space: normal; pointer-events: none;
761
+ box-shadow: 0 4px 14px rgba(0, 0, 0, 0.25);
762
+ }
@@ -1,2 +1,2 @@
1
- /*! danieldeusing-design v0.1.3 | MIT | https://github.com/danieldeusing/danieldeusing-design */
2
- *,*::before,*::after{box-sizing: border-box}*{margin: 0}html{-webkit-text-size-adjust: 100%;text-size-adjust: 100%;tab-size: 4}body{min-height: 100vh;min-height: 100dvh;line-height: 1.5}img,picture,video,canvas,svg{display: block;max-width: 100%}input,button,textarea,select{font: inherit;color: inherit}p,h1,h2,h3,h4,h5,h6{overflow-wrap: break-word}ul,ol{list-style: none;padding: 0}a{color: inherit;text-decoration: none}table{border-collapse: collapse}:root{--background: #f5efe2;--foreground: #43352a;--card: #efe7d4;--card-foreground: #43352a;--popover: #efe7d4;--popover-foreground: #43352a;--primary: #8a4516;--primary-foreground: #f8f3e8;--secondary: #ece3cf;--secondary-foreground: #43352a;--muted: #ece3cf;--muted-foreground: #71614e;--accent: #8a4516;--accent-foreground: #f8f3e8;--destructive: #a02c2c;--border: #d9cdb6;--input: #d9cdb6;--ring: #8a4516;--glow: rgba(160,82,45,0.1);--glow-soft: rgba(160,82,45,0.05);--scanline-opacity: 0.15;--radius: 0rem;--font-mono: "JetBrains Mono Variable","JetBrains Mono","Menlo",monospace}html[data-theme="green"]{--background: #020604;--foreground: #4fdd7d;--card: #04110a;--card-foreground: #4fdd7d;--popover: #04110a;--popover-foreground: #4fdd7d;--primary: #33ff66;--primary-foreground: #02160a;--secondary: #071509;--secondary-foreground: #4fdd7d;--muted: #071509;--muted-foreground: #3da45e;--accent: #33ff66;--accent-foreground: #02160a;--destructive: #ff5c5c;--border: #1c4a2c;--input: #1c4a2c;--ring: #33ff66;--glow: rgba(51,255,102,0.35);--glow-soft: rgba(51,255,102,0.12);--scanline-opacity: 0.5}html[data-theme="mono"]{--background: #050505;--foreground: #d4d4d4;--card: #0d0d0d;--card-foreground: #d4d4d4;--popover: #0d0d0d;--popover-foreground: #d4d4d4;--primary: #ffffff;--primary-foreground: #050505;--secondary: #111111;--secondary-foreground: #d4d4d4;--muted: #111111;--muted-foreground: #8a8a8a;--accent: #ffffff;--accent-foreground: #050505;--destructive: #ff5c5c;--border: #333333;--input: #333333;--ring: #ffffff;--glow: rgba(255,255,255,0.25);--glow-soft: rgba(255,255,255,0.08);--scanline-opacity: 0.45}html[data-theme="paper"]{--background: #fafafa;--foreground: #1f1f1f;--card: #f1f1f1;--card-foreground: #1f1f1f;--popover: #f1f1f1;--popover-foreground: #1f1f1f;--primary: #000000;--primary-foreground: #fafafa;--secondary: #efefef;--secondary-foreground: #1f1f1f;--muted: #efefef;--muted-foreground: #595959;--accent: #000000;--accent-foreground: #fafafa;--destructive: #b3261e;--border: #d4d4d4;--input: #d4d4d4;--ring: #000000;--glow: rgba(0,0,0,0.06);--glow-soft: rgba(0,0,0,0.04);--scanline-opacity: 0.12}html{scroll-behavior: smooth}*,*::before,*::after{border-color: var(--border)}:focus-visible{outline: 2px solid var(--ring);outline-offset: 2px}body{background: var(--background);color: var(--foreground);font-family: var(--font-mono);font-size: 0.75rem;line-height: 1.5;overflow-x: hidden;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale}button:not(:disabled),summary,[role="button"]{cursor: pointer}body::after{content: "";position: fixed;inset: 0;z-index: 40;pointer-events: none;background: repeating-linear-gradient( 0deg,rgba(0,0,0,0.25) 0px,rgba(0,0,0,0.25) 1px,transparent 1px,transparent 3px );opacity: var(--scanline-opacity)}::selection{background: var(--primary);color: var(--primary-foreground)}.glow{color: var(--primary);text-shadow: 0 0 8px var(--glow)}.glow-lg{color: var(--primary);text-shadow: 0 0 12px var(--glow)}.prompt{font-size: 0.75rem;font-weight: 700;color: var(--muted-foreground)}.prompt::before{content: "$ ";color: var(--primary)}.comment::before{content: "# ";color: var(--border)}.cursor-block{display: inline-block;width: 0.55em;height: 1em;margin-left: 8px;background: var(--primary);vertical-align: baseline;transform: translateY(0.12em);animation: ddd-blink 1.1s step-end infinite}@keyframes ddd-blink{50%{opacity: 0}}.btn-terminal{display: inline-block;background: var(--primary);color: var(--primary-foreground);font-weight: 700;padding: 12px 24px;box-shadow: 0 0 16px var(--glow);transition: box-shadow 0.15s ease,transform 0.15s ease}.btn-terminal::before{content: "> "}.btn-terminal:hover{box-shadow: 0 0 28px var(--glow);transform: translateY(-2px)}.link-quiet{color: var(--muted-foreground);text-decoration: underline;text-underline-offset: 4px;transition: color 0.15s ease}.link-quiet:hover{color: var(--primary)}.anim-toggle{display: inline-flex;align-items: center;gap: 6px;font: inherit;color: var(--muted-foreground);background: none;border: 0;cursor: pointer;transition: color 0.15s ease}.anim-toggle:hover{color: var(--primary)}.anim-toggle[aria-pressed="true"] [data-anim-box]{color: var(--primary)}.dd-dot{display: inline-block;width: 11px;height: 11px;flex: none;border-radius: 50%;background: currentColor}.dd-flag{display: inline-block;width: 15px;height: 10px;flex: none;border: 1px solid var(--border);background-size: cover;background-repeat: no-repeat}.dd-flag-de{background-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 18 12'><rect width='18' height='4' fill='%23262626'/><rect y='4' width='18' height='4' fill='%23c83232'/><rect y='8' width='18' height='4' fill='%23e8be32'/></svg>")}.dd-flag-en{background-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 18 12'><rect width='18' height='12' fill='%23b22234'/><rect y='4' width='18' height='4' fill='%23ececec'/><rect width='8' height='6' fill='%233c3b6e'/></svg>")}.dd-flag-pt{background-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 18 12'><rect width='18' height='12' fill='%231c9148'/><polygon points='9,1.5 15.5,6 9,10.5 2.5,6' fill='%23e8c832'/><rect x='8' y='5' width='2' height='2' fill='%232c3f87'/></svg>")}.dd-flag-es{background-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 18 12'><rect width='6' height='12' fill='%2315734c'/><rect x='6' width='6' height='12' fill='%23ececec'/><rect x='12' width='6' height='12' fill='%23bf2233'/><rect x='8' y='5' width='2' height='2' fill='%237a5c3a'/></svg>")}.ascii-rule{margin: 1rem 0;border: 0;color: var(--border);line-height: 1;white-space: nowrap;overflow: hidden;user-select: none}.ascii-rule::before{content: "────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────"}.card-terminal{background: var(--card);border: 1px solid var(--border);transition: border-color 0.15s ease,box-shadow 0.15s ease}.card-terminal:hover{border-color: var(--primary);box-shadow: 0 0 20px var(--glow-soft)}.dropdown{position: relative}.dropdown>summary{display: inline-flex;align-items: center;gap: 6px;cursor: pointer;user-select: none;list-style: none;color: var(--muted-foreground);transition: color 0.15s ease}.dropdown>summary::-webkit-details-marker{display: none}.dropdown>summary:hover,.dropdown[open]>summary{color: var(--primary)}.dropdown-panel{position: absolute;right: 0;bottom: calc(100% + 12px);z-index: 50;min-width: 128px;margin: 0;padding: 4px 0;list-style: none;background: var(--card);border: 1px solid var(--border);border-radius: 0;box-shadow: 0 0 20px var(--glow-soft)}.dropdown-panel--down{top: calc(100% + 8px);bottom: auto;left: 0;right: auto}.dropdown-item{display: flex;align-items: center;gap: 8px;width: 100%;padding: 5px 14px;text-align: left;font: inherit;line-height: 1.5;background: none;border: 0;color: var(--muted-foreground);cursor: pointer;white-space: nowrap;transition: color 0.15s ease}.dropdown-item:hover{color: var(--primary);background: var(--muted)}.dropdown-item[aria-current="true"],html:not([data-theme]) .dropdown-item[data-theme-value="warm"],html[data-theme="green"] .dropdown-item[data-theme-value="green"],html[data-theme="mono"] .dropdown-item[data-theme-value="mono"],html[data-theme="paper"] .dropdown-item[data-theme-value="paper"],html[data-theme="warm"] .dropdown-item[data-theme-value="warm"]{color: var(--primary);text-shadow: 0 0 8px var(--glow)}.eli5{margin: 1.25em 0;padding: 0.7em 1em;color: var(--foreground);background: color-mix(in srgb,var(--primary) 7%,var(--card));border: 1px solid var(--border);border-left: 3px solid var(--primary);border-radius: var(--radius);font-size: 0.92em;line-height: 1.6}.eli5::before{content: "ELI5";display: inline-flex;align-items: center;justify-content: center;margin-right: 0.6em;vertical-align: 0.08em;font-family: var(--font-mono);font-size: 0.72em;font-weight: 700;line-height: 1;letter-spacing: 0.04em;padding: 0.34em 0.6em;border-radius: 5px;background: #b42318;color: #fff}.eli5-term{font-weight: 700;color: var(--primary)}html.anim-off *,html.anim-off *::before,html.anim-off *::after{animation: none !important}html.anim-off .cursor-block{display: none}@media (prefers-reduced-motion: no-preference){html.term-anim [data-term] .prompt:not(.term-live),html.term-anim [data-term] .prompt:not(.term-live)::before{color: transparent}html.term-anim [data-term] [data-term-out]:not(.term-show){visibility: hidden}html.term-anim [data-term] [data-term-out].term-show{animation: ddd-term-output 0.2s steps(3,end) both}@keyframes ddd-term-output{from{opacity: 0}}html.term-anim [data-term] [data-term-out].term-show>*{animation: ddd-term-output 0.25s steps(3,end) both}html.term-anim [data-term] [data-term-out].term-show>*:nth-child(2){animation-delay: 0.09s}html.term-anim [data-term] [data-term-out].term-show>*:nth-child(3){animation-delay: 0.18s}html.term-anim [data-term] [data-term-out].term-show>*:nth-child(4){animation-delay: 0.27s}html.term-anim [data-term] [data-term-out].term-show>*:nth-child(5){animation-delay: 0.36s}html.term-anim [data-term] [data-term-out].term-show>*:nth-child(6){animation-delay: 0.45s}html.term-anim [data-term] [data-term-out].term-show>*:nth-child(7){animation-delay: 0.54s}html.term-anim [data-term] [data-term-out].term-show>*:nth-child(8){animation-delay: 0.63s}html.term-anim [data-term] [data-term-out].term-show>*:nth-child(9){animation-delay: 0.72s}html.term-anim [data-term] [data-term-out].term-show>*:nth-child(10){animation-delay: 0.81s}html.term-anim [data-term] [data-term-out].term-show>*:nth-child(n + 11){animation-delay: 0.9s}.term-caret{display: inline-block;width: 0.55em;height: 1em;margin-left: 2px;background: var(--primary);vertical-align: baseline;transform: translateY(0.12em)}}
1
+ /*! danieldeusing-design v0.1.5 | MIT | https://github.com/danieldeusing/danieldeusing-design */
2
+ *,*::before,*::after{box-sizing: border-box}*{margin: 0}html{-webkit-text-size-adjust: 100%;text-size-adjust: 100%;tab-size: 4}body{min-height: 100vh;min-height: 100dvh;line-height: 1.5}img,picture,video,canvas,svg{display: block;max-width: 100%}input,button,textarea,select{font: inherit;color: inherit}p,h1,h2,h3,h4,h5,h6{overflow-wrap: break-word}ul,ol{list-style: none;padding: 0}a{color: inherit;text-decoration: none}table{border-collapse: collapse}:root{--background: #f5efe2;--foreground: #43352a;--card: #efe7d4;--card-foreground: #43352a;--popover: #efe7d4;--popover-foreground: #43352a;--primary: #8a4516;--primary-foreground: #f8f3e8;--secondary: #ece3cf;--secondary-foreground: #43352a;--muted: #ece3cf;--muted-foreground: #71614e;--accent: #8a4516;--accent-foreground: #f8f3e8;--destructive: #a02c2c;--border: #d9cdb6;--input: #d9cdb6;--ring: #8a4516;--glow: rgba(160,82,45,0.1);--glow-soft: rgba(160,82,45,0.05);--scanline-opacity: 0.15;--radius: 0rem;--font-mono: "JetBrains Mono Variable","JetBrains Mono","Menlo",monospace}html[data-theme="green"]{--background: #020604;--foreground: #4fdd7d;--card: #04110a;--card-foreground: #4fdd7d;--popover: #04110a;--popover-foreground: #4fdd7d;--primary: #33ff66;--primary-foreground: #02160a;--secondary: #071509;--secondary-foreground: #4fdd7d;--muted: #071509;--muted-foreground: #3da45e;--accent: #33ff66;--accent-foreground: #02160a;--destructive: #ff5c5c;--border: #1c4a2c;--input: #1c4a2c;--ring: #33ff66;--glow: rgba(51,255,102,0.35);--glow-soft: rgba(51,255,102,0.12);--scanline-opacity: 0.5}html[data-theme="mono"]{--background: #050505;--foreground: #d4d4d4;--card: #0d0d0d;--card-foreground: #d4d4d4;--popover: #0d0d0d;--popover-foreground: #d4d4d4;--primary: #ffffff;--primary-foreground: #050505;--secondary: #111111;--secondary-foreground: #d4d4d4;--muted: #111111;--muted-foreground: #8a8a8a;--accent: #ffffff;--accent-foreground: #050505;--destructive: #ff5c5c;--border: #333333;--input: #333333;--ring: #ffffff;--glow: rgba(255,255,255,0.25);--glow-soft: rgba(255,255,255,0.08);--scanline-opacity: 0.45}html[data-theme="paper"]{--background: #fafafa;--foreground: #1f1f1f;--card: #f1f1f1;--card-foreground: #1f1f1f;--popover: #f1f1f1;--popover-foreground: #1f1f1f;--primary: #000000;--primary-foreground: #fafafa;--secondary: #efefef;--secondary-foreground: #1f1f1f;--muted: #efefef;--muted-foreground: #595959;--accent: #000000;--accent-foreground: #fafafa;--destructive: #b3261e;--border: #d4d4d4;--input: #d4d4d4;--ring: #000000;--glow: rgba(0,0,0,0.06);--glow-soft: rgba(0,0,0,0.04);--scanline-opacity: 0.12}html{scroll-behavior: smooth}*,*::before,*::after{border-color: var(--border)}:focus-visible{outline: 2px solid var(--ring);outline-offset: 2px}body{background: var(--background);color: var(--foreground);font-family: var(--font-mono);font-size: 0.75rem;line-height: 1.5;overflow-x: hidden;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale}button:not(:disabled),summary,[role="button"]{cursor: pointer}body::after{content: "";position: fixed;inset: 0;z-index: 40;pointer-events: none;background: repeating-linear-gradient( 0deg,rgba(0,0,0,0.25) 0px,rgba(0,0,0,0.25) 1px,transparent 1px,transparent 3px );opacity: var(--scanline-opacity)}::selection{background: var(--primary);color: var(--primary-foreground)}.glow{color: var(--primary);text-shadow: 0 0 8px var(--glow)}.glow-lg{color: var(--primary);text-shadow: 0 0 12px var(--glow)}.prompt{font-size: 0.75rem;font-weight: 700;color: var(--muted-foreground)}.prompt::before{content: "$ ";color: var(--primary)}.comment::before{content: "# ";color: var(--border)}.cursor-block{display: inline-block;width: 0.55em;height: 1em;margin-left: 8px;background: var(--primary);vertical-align: baseline;transform: translateY(0.12em);animation: ddd-blink 1.1s step-end infinite}@keyframes ddd-blink{50%{opacity: 0}}.btn-terminal{display: inline-block;background: var(--primary);color: var(--primary-foreground);font-weight: 700;padding: 12px 24px;box-shadow: 0 0 16px var(--glow);transition: box-shadow 0.15s ease,transform 0.15s ease}.btn-terminal::before{content: "> "}.btn-terminal:hover{box-shadow: 0 0 28px var(--glow);transform: translateY(-2px)}.link-quiet{color: var(--muted-foreground);text-decoration: underline;text-underline-offset: 4px;transition: color 0.15s ease}.link-quiet:hover{color: var(--primary)}.anim-toggle{display: inline-flex;align-items: center;gap: 6px;font: inherit;color: var(--muted-foreground);background: none;border: 0;cursor: pointer;transition: color 0.15s ease}.anim-toggle:hover{color: var(--primary)}.anim-toggle[aria-pressed="true"] [data-anim-box]{color: var(--primary)}.dd-dot{display: inline-block;width: 11px;height: 11px;flex: none;border-radius: 50%;background: currentColor}.dd-flag{display: inline-block;width: 15px;height: 10px;flex: none;border: 1px solid var(--border);background-size: cover;background-repeat: no-repeat}.dd-flag-de{background-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 18 12'><rect width='18' height='4' fill='%23262626'/><rect y='4' width='18' height='4' fill='%23c83232'/><rect y='8' width='18' height='4' fill='%23e8be32'/></svg>")}.dd-flag-en{background-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 18 12'><rect width='18' height='12' fill='%23b22234'/><rect y='4' width='18' height='4' fill='%23ececec'/><rect width='8' height='6' fill='%233c3b6e'/></svg>")}.dd-flag-pt{background-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 18 12'><rect width='18' height='12' fill='%231c9148'/><polygon points='9,1.5 15.5,6 9,10.5 2.5,6' fill='%23e8c832'/><rect x='8' y='5' width='2' height='2' fill='%232c3f87'/></svg>")}.dd-flag-es{background-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 18 12'><rect width='6' height='12' fill='%2315734c'/><rect x='6' width='6' height='12' fill='%23ececec'/><rect x='12' width='6' height='12' fill='%23bf2233'/><rect x='8' y='5' width='2' height='2' fill='%237a5c3a'/></svg>")}.ascii-rule{margin: 1rem 0;border: 0;color: var(--border);line-height: 1;white-space: nowrap;overflow: hidden;user-select: none}.ascii-rule::before{content: "────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────"}.card-terminal{background: var(--card);border: 1px solid var(--border);transition: border-color 0.15s ease,box-shadow 0.15s ease}.card-terminal:hover{border-color: var(--primary);box-shadow: 0 0 20px var(--glow-soft)}.dropdown{position: relative}.dropdown>summary{display: inline-flex;align-items: center;gap: 6px;cursor: pointer;user-select: none;list-style: none;color: var(--muted-foreground);transition: color 0.15s ease}.dropdown>summary::-webkit-details-marker{display: none}.dropdown>summary:hover,.dropdown[open]>summary{color: var(--primary)}.dropdown-panel{position: absolute;right: 0;bottom: calc(100% + 12px);z-index: 50;min-width: 128px;margin: 0;padding: 4px 0;list-style: none;background: var(--card);border: 1px solid var(--border);border-radius: 0;box-shadow: 0 0 20px var(--glow-soft)}.dropdown-panel--down{top: calc(100% + 8px);bottom: auto;left: 0;right: auto}.dropdown-item{display: flex;align-items: center;gap: 8px;width: 100%;padding: 5px 14px;text-align: left;font: inherit;line-height: 1.5;background: none;border: 0;color: var(--muted-foreground);cursor: pointer;white-space: nowrap;transition: color 0.15s ease}.dropdown-item:hover{color: var(--primary);background: var(--muted)}.dropdown-item[aria-current="true"],html:not([data-theme]) .dropdown-item[data-theme-value="warm"],html[data-theme="green"] .dropdown-item[data-theme-value="green"],html[data-theme="mono"] .dropdown-item[data-theme-value="mono"],html[data-theme="paper"] .dropdown-item[data-theme-value="paper"],html[data-theme="warm"] .dropdown-item[data-theme-value="warm"]{color: var(--primary);text-shadow: 0 0 8px var(--glow)}.eli5{margin: 1.25em 0;padding: 0.7em 1em;color: var(--foreground);background: color-mix(in srgb,var(--primary) 7%,var(--card));border: 1px solid var(--border);border-left: 3px solid var(--primary);border-radius: var(--radius);font-size: 0.92em;line-height: 1.6}.eli5::before{content: "ELI5";display: inline-flex;align-items: center;justify-content: center;margin-right: 0.6em;vertical-align: 0.08em;font-family: var(--font-mono);font-size: 0.72em;font-weight: 700;line-height: 1;letter-spacing: 0.04em;padding: 0.34em 0.6em;border-radius: 5px;background: #b42318;color: #fff}.eli5-term{font-weight: 700;color: var(--primary)}html.anim-off *,html.anim-off *::before,html.anim-off *::after{animation: none !important}html.anim-off .cursor-block{display: none}@media (prefers-reduced-motion: no-preference){html.term-anim [data-term] .prompt:not(.term-live),html.term-anim [data-term] .prompt:not(.term-live)::before{color: transparent}html.term-anim [data-term] [data-term-out]:not(.term-show){visibility: hidden}html.term-anim [data-term] [data-term-out].term-show{animation: ddd-term-output 0.2s steps(3,end) both}@keyframes ddd-term-output{from{opacity: 0}}html.term-anim [data-term] [data-term-out].term-show>*{animation: ddd-term-output 0.25s steps(3,end) both}html.term-anim [data-term] [data-term-out].term-show>*:nth-child(2){animation-delay: 0.09s}html.term-anim [data-term] [data-term-out].term-show>*:nth-child(3){animation-delay: 0.18s}html.term-anim [data-term] [data-term-out].term-show>*:nth-child(4){animation-delay: 0.27s}html.term-anim [data-term] [data-term-out].term-show>*:nth-child(5){animation-delay: 0.36s}html.term-anim [data-term] [data-term-out].term-show>*:nth-child(6){animation-delay: 0.45s}html.term-anim [data-term] [data-term-out].term-show>*:nth-child(7){animation-delay: 0.54s}html.term-anim [data-term] [data-term-out].term-show>*:nth-child(8){animation-delay: 0.63s}html.term-anim [data-term] [data-term-out].term-show>*:nth-child(9){animation-delay: 0.72s}html.term-anim [data-term] [data-term-out].term-show>*:nth-child(10){animation-delay: 0.81s}html.term-anim [data-term] [data-term-out].term-show>*:nth-child(n + 11){animation-delay: 0.9s}.term-caret{display: inline-block;width: 0.55em;height: 1em;margin-left: 2px;background: var(--primary);vertical-align: baseline;transform: translateY(0.12em)}}.skip-link{position: absolute;left: -999px;top: 0;z-index: 100;background: var(--card);border: 1px solid var(--primary);padding: 0.5rem 1rem;color: var(--primary)}.skip-link:focus{left: 0.5rem;top: 0.5rem}.visually-hidden{position: absolute;width: 1px;height: 1px;overflow: hidden;clip: rect(0 0 0 0);white-space: nowrap}header.bar{position: sticky;top: 0;z-index: 30;display: flex;align-items: center;justify-content: space-between;gap: 1rem;padding: 0.6rem 1.25rem;border-bottom: 1px solid var(--border);background: var(--card)}header.bar .brand{display: inline-flex;align-items: center;font-weight: 700;font-size: 1rem}header.bar .brand,header.bar .brand a{color: inherit;text-decoration: none}header.bar .dropdown summary{padding: 0.6rem 0.4rem}.bar-right{display: flex;align-items: center;gap: 1rem;flex-shrink: 0}footer.status{position: fixed;inset-inline: 0;bottom: 0;z-index: 50;min-height: 2rem;display: flex;align-items: center;justify-content: space-between;gap: 1rem;padding: 0.35rem 1.25rem;border-top: 1px solid var(--border);background: var(--card);font-size: 0.7rem}footer.status .dropdown summary,footer.status .anim-toggle{padding: 0.55rem 0.4rem}.status-left{color: var(--muted-foreground);min-width: 0;overflow: hidden;text-overflow: ellipsis;white-space: nowrap}.status-right{display: flex;align-items: center;gap: 1rem;flex-shrink: 0}.sep{width: 1px;height: 0.9rem;background: var(--border)}.doc-link{color: var(--muted-foreground);text-decoration: none;transition: color 0.15s ease}.doc-link:hover{color: var(--primary)}.ls-row{display: flex;align-items: baseline;gap: 0.9rem}.ls-perm{color: var(--muted-foreground);font-size: 0.72rem;letter-spacing: 0}.ls-row--sub .ls-name{padding-left: 1rem}.ls-panel{min-width: 17rem;left: auto !important;right: 0}#nav{position: relative}.nav-burger{display: none;background: none;border: 0;color: var(--muted-foreground);cursor: pointer;padding: 0.55rem;margin: -0.3rem -0.3rem -0.3rem 0}.nav-burger:hover{color: var(--primary)}.mobile-nav{display: none;list-style: none;margin: 0;padding: 0}.mobile-footer{display: none}@media (max-width: 48rem){.nav-burger{display: inline-flex;align-items: center}.site-nav{display: none;position: absolute;top: 100%;left: 0;right: 0;z-index: 40;background: var(--card);border-bottom: 1px solid var(--border);padding: 0.4rem 1.25rem 0.9rem;max-height: calc(100vh - 6rem);overflow-y: auto}.site-nav.open{display: block}.site-nav>.dropdown{display: none}.mobile-nav{display: flex;flex-direction: column}.mobile-nav .mobile-item{display: flex;align-items: baseline;gap: 0.9rem;padding: 0.65rem 0;text-decoration: none;color: var(--foreground);font-size: 0.9rem;border-bottom: 1px solid var(--border)}.mobile-nav li:last-child .mobile-item{border-bottom: 0}.mobile-nav .mobile-item:active .ls-name,.mobile-nav .mobile-item:hover .ls-name{color: var(--primary)}footer.status{display: none}.mobile-footer{display: flex;flex-direction: column;gap: 0.55rem;margin-top: 0.8rem;border-top: 1px solid var(--border);padding-top: 0.8rem;font-size: 0.85rem}.mobile-footer .doc-link{padding: 0.2rem 0}.mobile-footer .mobile-theme summary{list-style: none;display: flex;align-items: center;gap: 0.5rem;color: var(--muted-foreground);cursor: pointer;padding: 0.2rem 0}.mobile-footer .mobile-theme summary::-webkit-details-marker{display: none}.mobile-footer .mf-chev{margin-left: auto;opacity: 0.7}.mobile-footer .mf-panel{display: flex;flex-direction: column;margin-top: 0.3rem}.mobile-footer .mf-panel .dropdown-item{text-align: left;padding: 0.4rem 0.6rem}.mobile-footer .anim-toggle{display: inline-flex;gap: 0.5rem;align-items: center;background: none;border: 0;padding: 0.2rem 0;color: var(--muted-foreground);font: inherit;cursor: pointer}}[data-tip]{cursor: help}span[data-tip],th[data-tip]{border-bottom: 1px dotted var(--muted-foreground)}#ddtip{position: fixed;z-index: 9999;display: none;max-width: 340px;background: var(--background);color: var(--foreground);border: 1px solid var(--muted-foreground);border-radius: 4px;padding: 7px 10px;font-size: 0.72rem;line-height: 1.45;font-weight: 400;text-align: left;white-space: normal;pointer-events: none;box-shadow: 0 4px 14px rgba(0,0,0,0.25)}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@danieldeusing/design",
3
- "version": "0.1.3",
4
- "description": "The danieldeusing terminal design system framework-agnostic CSS tokens, components, and a vanilla-JS runtime for the CRT/JetBrains-Mono look used across danieldeusing.de, seedr, and briefs.",
3
+ "version": "0.1.5",
4
+ "description": "The danieldeusing terminal design system \u2014 framework-agnostic CSS tokens, components, and a vanilla-JS runtime for the CRT/JetBrains-Mono look used across danieldeusing.de, seedr, and briefs.",
5
5
  "type": "module",
6
6
  "license": "MIT",
7
7
  "author": "Daniel Deusing",
package/runtime/index.js CHANGED
@@ -15,3 +15,5 @@ export * from "./zoom.js";
15
15
  export * from "./dropdown.js";
16
16
  export * from "./anim.js";
17
17
  export * from "./terminal.js";
18
+ export * from "./nav.js";
19
+ export * from "./tooltip.js";
package/runtime/nav.js ADDED
@@ -0,0 +1,35 @@
1
+ /*
2
+ * nav.js — mobile burger navigation for the chrome kit (src/chrome.css).
3
+ *
4
+ * Markup contract:
5
+ * <button class="nav-burger" data-nav-toggle aria-controls="site-nav" aria-expanded="false">…</button>
6
+ * <nav id="site-nav" class="site-nav">…</nav>
7
+ *
8
+ * Toggles `.open` on the nav, keeps aria-expanded in sync, and closes on
9
+ * outside click. Desktop is untouched (the burger is display:none above the
10
+ * 48rem breakpoint).
11
+ */
12
+ export function initBurgerNav() {
13
+ const burger = document.querySelector("[data-nav-toggle]");
14
+ const nav = document.getElementById("site-nav");
15
+ if (!burger || !nav) return;
16
+
17
+ burger.addEventListener("click", () => {
18
+ const open = nav.classList.toggle("open");
19
+ burger.setAttribute("aria-expanded", String(open));
20
+ });
21
+
22
+ document.addEventListener("click", (event) => {
23
+ if (!nav.classList.contains("open")) return;
24
+ if (event.target.closest("#site-nav") || event.target.closest("[data-nav-toggle]")) return;
25
+ nav.classList.remove("open");
26
+ burger.setAttribute("aria-expanded", "false");
27
+ });
28
+
29
+ document.addEventListener("keydown", (event) => {
30
+ if (event.key !== "Escape" || !nav.classList.contains("open")) return;
31
+ nav.classList.remove("open");
32
+ burger.setAttribute("aria-expanded", "false");
33
+ burger.focus();
34
+ });
35
+ }
@@ -0,0 +1,54 @@
1
+ /*
2
+ * tooltip.js — viewport-clamped hover/focus tooltips for `[data-tip]`.
3
+ *
4
+ * Markup contract:
5
+ * <span data-tip="Explanation shown on hover">metric</span>
6
+ *
7
+ * One singleton panel (`#ddtip`, styled in src/tooltip.css) is appended to
8
+ * <body> and positioned with `position: fixed`, so it escapes every overflow/
9
+ * clip context and always renders on top. Placement prefers below the anchor,
10
+ * flips above when there is no room, and clamps horizontally to the viewport —
11
+ * a tooltip must never be cut off. Event delegation means dynamically rendered
12
+ * [data-tip] nodes just work.
13
+ */
14
+ export function initTooltips() {
15
+ if (document.getElementById("ddtip")) return;
16
+ const tip = document.createElement("div");
17
+ tip.id = "ddtip";
18
+ tip.setAttribute("role", "tooltip");
19
+ document.body.appendChild(tip);
20
+
21
+ let anchor = null;
22
+ function show(el) {
23
+ anchor = el;
24
+ tip.textContent = el.getAttribute("data-tip");
25
+ tip.style.display = "block";
26
+ tip.style.left = "0px";
27
+ tip.style.top = "0px";
28
+ const margin = 8;
29
+ const r = el.getBoundingClientRect();
30
+ const t = tip.getBoundingClientRect();
31
+ const x = Math.min(Math.max(r.left, margin), window.innerWidth - t.width - margin);
32
+ let y = r.bottom + 6;
33
+ if (y + t.height > window.innerHeight - margin) y = r.top - t.height - 6;
34
+ if (y < margin) y = margin;
35
+ tip.style.left = x + "px";
36
+ tip.style.top = y + "px";
37
+ }
38
+ function hide() {
39
+ anchor = null;
40
+ tip.style.display = "none";
41
+ }
42
+
43
+ document.addEventListener("mouseover", (event) => {
44
+ const el = event.target.closest("[data-tip]");
45
+ if (el) show(el);
46
+ else if (anchor) hide();
47
+ });
48
+ document.addEventListener("focusin", (event) => {
49
+ const el = event.target.closest("[data-tip]");
50
+ if (el) show(el);
51
+ });
52
+ document.addEventListener("focusout", hide);
53
+ document.addEventListener("scroll", () => anchor && show(anchor), true);
54
+ }
package/src/chrome.css ADDED
@@ -0,0 +1,122 @@
1
+ /*
2
+ * chrome.css — the app chrome kit: sticky header bar, fixed status footer,
3
+ * and the responsive site navigation (desktop `ls -l` dropdown, mobile
4
+ * burger with the footer folded in). Extracted from danieldeusing.de and
5
+ * the cockpit portal so every app ships the same chrome without rebuilding it.
6
+ *
7
+ * Markup contract (see templates/documentation.html for the full example):
8
+ *
9
+ * <a href="#top" class="skip-link">skip to content</a>
10
+ * <header class="bar">
11
+ * <a href="/" class="brand"><span class="glow">name</span><span class="cursor-block"></span></a>
12
+ * <button class="nav-burger" data-nav-toggle aria-controls="site-nav" aria-expanded="false">…☰ svg…</button>
13
+ * <nav aria-label="site" id="site-nav" class="site-nav">
14
+ * <details class="dropdown" id="nav">…ls-panel with .ls-row items…</details>
15
+ * <ul class="mobile-nav">…same links as .mobile-item ls-rows…</ul>
16
+ * <div class="mobile-footer">…footer controls folded in…</div>
17
+ * </nav>
18
+ * </header>
19
+ * …
20
+ * <footer class="status">…status-left + status-right…</footer>
21
+ *
22
+ * Behaviour: pair with `initBurgerNav()` from the runtime (adds the toggle +
23
+ * outside-click close). Breakpoint: 48rem.
24
+ */
25
+
26
+ /* ── a11y helpers ── */
27
+ .skip-link {
28
+ position: absolute; left: -999px; top: 0; z-index: 100;
29
+ background: var(--card); border: 1px solid var(--primary);
30
+ padding: 0.5rem 1rem; color: var(--primary);
31
+ }
32
+ .skip-link:focus { left: 0.5rem; top: 0.5rem; }
33
+ .visually-hidden {
34
+ position: absolute; width: 1px; height: 1px; overflow: hidden;
35
+ clip: rect(0 0 0 0); white-space: nowrap;
36
+ }
37
+
38
+ /* ── header bar (sticky) ── */
39
+ header.bar {
40
+ position: sticky; top: 0; z-index: 30;
41
+ display: flex; align-items: center; justify-content: space-between; gap: 1rem;
42
+ padding: 0.6rem 1.25rem; border-bottom: 1px solid var(--border); background: var(--card);
43
+ }
44
+ header.bar .brand { display: inline-flex; align-items: center; font-weight: 700; font-size: 1rem; }
45
+ header.bar .brand, header.bar .brand a { color: inherit; text-decoration: none; }
46
+ header.bar .dropdown summary { padding: 0.6rem 0.4rem; }
47
+ .bar-right { display: flex; align-items: center; gap: 1rem; flex-shrink: 0; }
48
+
49
+ /* ── status footer (fixed; hidden on mobile — folded into the burger) ── */
50
+ footer.status {
51
+ position: fixed; inset-inline: 0; bottom: 0; z-index: 50; min-height: 2rem;
52
+ display: flex; align-items: center; justify-content: space-between; gap: 1rem;
53
+ padding: 0.35rem 1.25rem; border-top: 1px solid var(--border); background: var(--card);
54
+ font-size: 0.7rem;
55
+ }
56
+ footer.status .dropdown summary, footer.status .anim-toggle { padding: 0.55rem 0.4rem; }
57
+ .status-left { color: var(--muted-foreground); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
58
+ .status-right { display: flex; align-items: center; gap: 1rem; flex-shrink: 0; }
59
+ .sep { width: 1px; height: 0.9rem; background: var(--border); }
60
+ .doc-link { color: var(--muted-foreground); text-decoration: none; transition: color 0.15s ease; }
61
+ .doc-link:hover { color: var(--primary); }
62
+
63
+ /* ── ls-listing rows (shared by the desktop dropdown + mobile menu) ── */
64
+ .ls-row { display: flex; align-items: baseline; gap: 0.9rem; }
65
+ .ls-perm { color: var(--muted-foreground); font-size: 0.72rem; letter-spacing: 0; }
66
+ .ls-row--sub .ls-name { padding-left: 1rem; }
67
+ .ls-panel { min-width: 17rem; left: auto !important; right: 0; }
68
+ #nav { position: relative; }
69
+
70
+ /* ── burger + mobile menu ── */
71
+ .nav-burger {
72
+ display: none; background: none; border: 0; color: var(--muted-foreground);
73
+ cursor: pointer; padding: 0.55rem; margin: -0.3rem -0.3rem -0.3rem 0;
74
+ }
75
+ .nav-burger:hover { color: var(--primary); }
76
+ .mobile-nav { display: none; list-style: none; margin: 0; padding: 0; }
77
+ .mobile-footer { display: none; }
78
+
79
+ @media (max-width: 48rem) {
80
+ .nav-burger { display: inline-flex; align-items: center; }
81
+
82
+ /* the nav becomes a full-width column under the sticky header */
83
+ .site-nav {
84
+ display: none; position: absolute; top: 100%; left: 0; right: 0; z-index: 40;
85
+ background: var(--card); border-bottom: 1px solid var(--border);
86
+ padding: 0.4rem 1.25rem 0.9rem; max-height: calc(100vh - 6rem); overflow-y: auto;
87
+ }
88
+ .site-nav.open { display: block; }
89
+ .site-nav > .dropdown { display: none; } /* desktop ls-dropdown replaced by the flat list */
90
+
91
+ .mobile-nav { display: flex; flex-direction: column; }
92
+ .mobile-nav .mobile-item {
93
+ display: flex; align-items: baseline; gap: 0.9rem; padding: 0.65rem 0;
94
+ text-decoration: none; color: var(--foreground); font-size: 0.9rem;
95
+ border-bottom: 1px solid var(--border);
96
+ }
97
+ .mobile-nav li:last-child .mobile-item { border-bottom: 0; }
98
+ .mobile-nav .mobile-item:active .ls-name,
99
+ .mobile-nav .mobile-item:hover .ls-name { color: var(--primary); }
100
+
101
+ /* footer content folded into the burger; the fixed footer disappears */
102
+ footer.status { display: none; }
103
+ .mobile-footer {
104
+ display: flex; flex-direction: column; gap: 0.55rem;
105
+ margin-top: 0.8rem; border-top: 1px solid var(--border); padding-top: 0.8rem;
106
+ font-size: 0.85rem;
107
+ }
108
+ .mobile-footer .doc-link { padding: 0.2rem 0; }
109
+ .mobile-footer .mobile-theme summary {
110
+ list-style: none; display: flex; align-items: center; gap: 0.5rem;
111
+ color: var(--muted-foreground); cursor: pointer; padding: 0.2rem 0;
112
+ }
113
+ .mobile-footer .mobile-theme summary::-webkit-details-marker { display: none; }
114
+ .mobile-footer .mf-chev { margin-left: auto; opacity: 0.7; }
115
+ .mobile-footer .mf-panel { display: flex; flex-direction: column; margin-top: 0.3rem; }
116
+ .mobile-footer .mf-panel .dropdown-item { text-align: left; padding: 0.4rem 0.6rem; }
117
+ .mobile-footer .anim-toggle {
118
+ display: inline-flex; gap: 0.5rem; align-items: center;
119
+ background: none; border: 0; padding: 0.2rem 0; color: var(--muted-foreground);
120
+ font: inherit; cursor: pointer;
121
+ }
122
+ }
package/src/index.css CHANGED
@@ -17,3 +17,5 @@
17
17
  @import "./tokens.css";
18
18
  @import "./base.css";
19
19
  @import "./components.css";
20
+ @import "./chrome.css";
21
+ @import "./tooltip.css";
package/src/tailwind.css CHANGED
@@ -17,6 +17,8 @@
17
17
  @import "./tokens.css";
18
18
  @import "./base.css";
19
19
  @import "./components.css";
20
+ @import "./chrome.css";
21
+ @import "./tooltip.css";
20
22
 
21
23
  @theme inline {
22
24
  --color-background: var(--background);
@@ -0,0 +1,16 @@
1
+ /*
2
+ * tooltip.css — styles for the [data-tip] tooltip system (runtime/tooltip.js).
3
+ * The panel is a body-level singleton with position:fixed — it can never be
4
+ * clipped by overflow containers and always sits on top.
5
+ */
6
+ [data-tip] { cursor: help; }
7
+ span[data-tip], th[data-tip] { border-bottom: 1px dotted var(--muted-foreground); }
8
+
9
+ #ddtip {
10
+ position: fixed; z-index: 9999; display: none; max-width: 340px;
11
+ background: var(--background); color: var(--foreground);
12
+ border: 1px solid var(--muted-foreground); border-radius: 4px;
13
+ padding: 7px 10px; font-size: 0.72rem; line-height: 1.45; font-weight: 400;
14
+ text-align: left; white-space: normal; pointer-events: none;
15
+ box-shadow: 0 4px 14px rgba(0, 0, 0, 0.25);
16
+ }