- Install highlight.js via npm with 8 language definitions - SourceViewer hook applies syntax highlighting on mount/update - Atom One Dark theme for dark mode, Atom One Light for light mode - Add hooks directory, package.json, and package-lock.json - Add demo document and screenshots - Add rodney-docker.md documentation - Ignore .rodney/ chrome data directory
410 lines
12 KiB
CSS
410 lines
12 KiB
CSS
/* See the Tailwind configuration guide for advanced usage
|
|
https://tailwindcss.com/docs/configuration */
|
|
|
|
@import "tailwindcss" source(none);
|
|
@source "../css";
|
|
@source "../js";
|
|
@source "../../lib/firehose_web";
|
|
|
|
/* A Tailwind plugin that makes "hero-#{ICON}" classes available.
|
|
The heroicons installation itself is managed by your mix.exs */
|
|
@plugin "../vendor/heroicons";
|
|
|
|
/* daisyUI Tailwind Plugin. You can update this file by fetching the latest version with:
|
|
curl -sLO https://github.com/saadeghi/daisyui/releases/latest/download/daisyui.js
|
|
Make sure to look at the daisyUI changelog: https://daisyui.com/docs/changelog/ */
|
|
@plugin "../vendor/daisyui" {
|
|
themes: false;
|
|
}
|
|
|
|
/* Warm light theme — amber/terracotta + cream */
|
|
@plugin "../vendor/daisyui-theme" {
|
|
name: "light";
|
|
default: true;
|
|
prefersdark: false;
|
|
color-scheme: "light";
|
|
--color-base-100: oklch(97% 0.008 75);
|
|
--color-base-200: oklch(94% 0.012 75);
|
|
--color-base-300: oklch(90% 0.016 75);
|
|
--color-base-content: oklch(25% 0.015 50);
|
|
--color-primary: oklch(58% 0.16 45);
|
|
--color-primary-content: oklch(98% 0.01 75);
|
|
--color-secondary: oklch(55% 0.12 30);
|
|
--color-secondary-content: oklch(98% 0.008 30);
|
|
--color-accent: oklch(62% 0.19 55);
|
|
--color-accent-content: oklch(98% 0.01 55);
|
|
--color-neutral: oklch(40% 0.02 50);
|
|
--color-neutral-content: oklch(97% 0.005 75);
|
|
--color-info: oklch(62% 0.17 245);
|
|
--color-info-content: oklch(97% 0.01 245);
|
|
--color-success: oklch(65% 0.15 155);
|
|
--color-success-content: oklch(98% 0.01 155);
|
|
--color-warning: oklch(72% 0.16 70);
|
|
--color-warning-content: oklch(25% 0.02 70);
|
|
--color-error: oklch(58% 0.22 25);
|
|
--color-error-content: oklch(97% 0.01 25);
|
|
--radius-selector: 0.375rem;
|
|
--radius-field: 0.375rem;
|
|
--radius-box: 0.75rem;
|
|
--size-selector: 0.25rem;
|
|
--size-field: 0.25rem;
|
|
--border: 1px;
|
|
--depth: 1;
|
|
--noise: 0;
|
|
}
|
|
|
|
/* Warm dark theme */
|
|
@plugin "../vendor/daisyui-theme" {
|
|
name: "dark";
|
|
default: false;
|
|
prefersdark: true;
|
|
color-scheme: "dark";
|
|
--color-base-100: oklch(24% 0.015 50);
|
|
--color-base-200: oklch(20% 0.012 50);
|
|
--color-base-300: oklch(16% 0.01 50);
|
|
--color-base-content: oklch(92% 0.015 75);
|
|
--color-primary: oklch(68% 0.16 45);
|
|
--color-primary-content: oklch(18% 0.02 45);
|
|
--color-secondary: oklch(62% 0.12 30);
|
|
--color-secondary-content: oklch(18% 0.01 30);
|
|
--color-accent: oklch(70% 0.17 55);
|
|
--color-accent-content: oklch(18% 0.01 55);
|
|
--color-neutral: oklch(32% 0.02 50);
|
|
--color-neutral-content: oklch(92% 0.008 75);
|
|
--color-info: oklch(62% 0.17 245);
|
|
--color-info-content: oklch(97% 0.01 245);
|
|
--color-success: oklch(65% 0.15 155);
|
|
--color-success-content: oklch(98% 0.01 155);
|
|
--color-warning: oklch(72% 0.16 70);
|
|
--color-warning-content: oklch(25% 0.02 70);
|
|
--color-error: oklch(58% 0.22 25);
|
|
--color-error-content: oklch(97% 0.01 25);
|
|
--radius-selector: 0.375rem;
|
|
--radius-field: 0.375rem;
|
|
--radius-box: 0.75rem;
|
|
--size-selector: 0.25rem;
|
|
--size-field: 0.25rem;
|
|
--border: 1px;
|
|
--depth: 1;
|
|
--noise: 0;
|
|
}
|
|
|
|
/* Add variants based on LiveView classes */
|
|
@custom-variant phx-click-loading (.phx-click-loading&, .phx-click-loading &);
|
|
@custom-variant phx-submit-loading (.phx-submit-loading&, .phx-submit-loading &);
|
|
@custom-variant phx-change-loading (.phx-change-loading&, .phx-change-loading &);
|
|
|
|
/* Use the data attribute for dark mode */
|
|
@custom-variant dark (&:where([data-theme=dark], [data-theme=dark] *));
|
|
|
|
/* Make LiveView wrapper divs transparent for layout */
|
|
[data-phx-session], [data-phx-teleported-src] { display: contents }
|
|
|
|
/* Self-hosted fonts — no external requests */
|
|
@font-face {
|
|
font-family: 'Fraunces';
|
|
font-style: normal;
|
|
font-weight: 300 900;
|
|
font-display: swap;
|
|
src: url(/fonts/fraunces.woff2) format('woff2');
|
|
}
|
|
@font-face {
|
|
font-family: 'Fraunces';
|
|
font-style: italic;
|
|
font-weight: 300 900;
|
|
font-display: swap;
|
|
src: url(/fonts/fraunces-italic.woff2) format('woff2');
|
|
}
|
|
@font-face {
|
|
font-family: 'Source Sans 3';
|
|
font-style: normal;
|
|
font-weight: 300 900;
|
|
font-display: swap;
|
|
src: url(/fonts/sourcesans3.woff2) format('woff2');
|
|
}
|
|
@font-face {
|
|
font-family: 'Source Sans 3';
|
|
font-style: italic;
|
|
font-weight: 300 900;
|
|
font-display: swap;
|
|
src: url(/fonts/sourcesans3-italic.woff2) format('woff2');
|
|
}
|
|
|
|
/* Typography */
|
|
.font-display { font-family: 'Fraunces', serif; }
|
|
body { font-family: 'Source Sans 3', sans-serif; }
|
|
|
|
/* Blogex component styling */
|
|
.blogex-post-index { display: flex; flex-direction: column; gap: 1.5rem; }
|
|
|
|
.blogex-post-preview header h2 {
|
|
font-family: 'Fraunces', serif;
|
|
font-size: 1.25rem;
|
|
font-weight: 600;
|
|
}
|
|
|
|
.blogex-post-preview header h2 a {
|
|
color: oklch(var(--color-base-content));
|
|
text-decoration: none;
|
|
}
|
|
|
|
.blogex-post-preview header h2 a:hover {
|
|
color: oklch(var(--color-primary));
|
|
}
|
|
|
|
.blogex-post-description {
|
|
margin-top: 0.25rem;
|
|
opacity: 0.7;
|
|
}
|
|
|
|
.blogex-post-meta {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
align-items: center;
|
|
gap: 0.5rem;
|
|
font-size: 0.875rem;
|
|
opacity: 0.6;
|
|
margin-top: 0.25rem;
|
|
}
|
|
|
|
.blogex-tag {
|
|
display: inline-block;
|
|
padding: 0.125rem 0.5rem;
|
|
border-radius: 9999px;
|
|
font-size: 0.75rem;
|
|
background: oklch(var(--color-base-200));
|
|
}
|
|
|
|
.blogex-post-header h1 {
|
|
font-family: 'Fraunces', serif;
|
|
font-size: 2rem;
|
|
font-weight: 700;
|
|
line-height: 1.2;
|
|
}
|
|
|
|
.blogex-post-body {
|
|
margin-top: 2rem;
|
|
line-height: 1.75;
|
|
}
|
|
|
|
.blogex-post-body h1 { font-family: 'Fraunces', serif; font-size: 1.75rem; font-weight: 700; margin-top: 2.5rem; margin-bottom: 0.5rem; }
|
|
.blogex-post-body h2 { font-family: 'Fraunces', serif; font-size: 1.5rem; font-weight: 600; margin-top: 2rem; margin-bottom: 0.5rem; }
|
|
.blogex-post-body h3 { font-family: 'Fraunces', serif; font-size: 1.25rem; font-weight: 600; margin-top: 1.5rem; margin-bottom: 0.5rem; }
|
|
.blogex-post-body p { margin-top: 1rem; }
|
|
.blogex-post-body ul { list-style: disc; padding-left: 1.5rem; margin-top: 0.5rem; }
|
|
.blogex-post-body ol { list-style: decimal; padding-left: 1.5rem; margin-top: 0.5rem; }
|
|
.blogex-post-body pre { background: oklch(var(--color-base-200)); padding: 1rem; border-radius: 0.5rem; overflow-x: auto; margin-top: 1rem; }
|
|
.blogex-post-body code { font-size: 0.875em; }
|
|
.blogex-post-body a { color: oklch(var(--color-primary)); text-decoration: underline; }
|
|
.blogex-post-body blockquote { border-left: 3px solid oklch(var(--color-primary)); padding-left: 1rem; margin-top: 1rem; margin-bottom: 1rem; font-style: italic; opacity: 0.85; }
|
|
|
|
.blogex-tag-list {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 0.5rem;
|
|
}
|
|
|
|
.blogex-tag-link {
|
|
display: inline-block;
|
|
padding: 0.25rem 0.75rem;
|
|
border-radius: 9999px;
|
|
font-size: 0.875rem;
|
|
background: oklch(var(--color-base-200));
|
|
text-decoration: none;
|
|
}
|
|
|
|
.blogex-tag-link:hover, .blogex-tag-active {
|
|
background: oklch(var(--color-primary));
|
|
color: oklch(var(--color-primary-content));
|
|
}
|
|
|
|
.blogex-pagination {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
gap: 1rem;
|
|
padding-top: 1rem;
|
|
font-size: 0.875rem;
|
|
}
|
|
|
|
.blogex-pagination a {
|
|
color: oklch(var(--color-primary));
|
|
text-decoration: none;
|
|
}
|
|
|
|
.blogex-pagination a:hover {
|
|
text-decoration: underline;
|
|
}
|
|
|
|
/* Source Viewer — line-numbered code display */
|
|
.source-viewer {
|
|
--sv-bg: oklch(20.15% 0.012 254.09);
|
|
--sv-text: oklch(90% 0.01 240);
|
|
--sv-line-num: oklch(55% 0.02 240);
|
|
--sv-highlight: oklch(30% 0.02 240);
|
|
}
|
|
|
|
[data-theme="dark"] .source-viewer {
|
|
--sv-bg: oklch(16% 0.01 254);
|
|
--sv-text: oklch(88% 0.01 240);
|
|
--sv-line-num: oklch(50% 0.02 240);
|
|
--sv-highlight: oklch(25% 0.02 240);
|
|
}
|
|
|
|
.sv-lines {
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
|
|
.sv-line {
|
|
display: flex;
|
|
align-items: baseline;
|
|
min-height: 1.25rem;
|
|
padding: 0 0.25rem;
|
|
transition: background-color 0.2s ease;
|
|
}
|
|
|
|
.sv-line-highlighted {
|
|
background-color: var(--sv-highlight);
|
|
}
|
|
|
|
.sv-line-number {
|
|
display: inline-block;
|
|
width: 2.5rem;
|
|
text-align: right;
|
|
padding-right: 0.75rem;
|
|
color: var(--sv-line-num);
|
|
user-select: none;
|
|
opacity: 0.6;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.sv-line-content {
|
|
white-space: pre;
|
|
flex: 1;
|
|
min-width: 0;
|
|
}
|
|
|
|
/* highlight.js — Atom One Dark (dark theme) */
|
|
.source-viewer code.hljs {
|
|
color: #abb2bf;
|
|
background: transparent;
|
|
padding: 0;
|
|
}
|
|
.source-viewer code.hljs .hljs-comment,
|
|
.source-viewer code.hljs .hljs-quote {
|
|
color: #5c6370;
|
|
font-style: italic;
|
|
}
|
|
.source-viewer code.hljs .hljs-doctag,
|
|
.source-viewer code.hljs .hljs-keyword,
|
|
.source-viewer code.hljs .hljs-formula {
|
|
color: #c678dd;
|
|
}
|
|
.source-viewer code.hljs .hljs-section,
|
|
.source-viewer code.hljs .hljs-name,
|
|
.source-viewer code.hljs .hljs-selector-tag,
|
|
.source-viewer code.hljs .hljs-deletion,
|
|
.source-viewer code.hljs .hljs-subst {
|
|
color: #e06c75;
|
|
}
|
|
.source-viewer code.hljs .hljs-literal {
|
|
color: #56b6c2;
|
|
}
|
|
.source-viewer code.hljs .hljs-string,
|
|
.source-viewer code.hljs .hljs-regexp,
|
|
.source-viewer code.hljs .hljs-addition,
|
|
.source-viewer code.hljs .hljs-attribute,
|
|
.source-viewer code.hljs .hljs-meta .hljs-string {
|
|
color: #98c379;
|
|
}
|
|
.source-viewer code.hljs .hljs-attr,
|
|
.source-viewer code.hljs .hljs-variable,
|
|
.source-viewer code.hljs .hljs-template-variable,
|
|
.source-viewer code.hljs .hljs-type,
|
|
.source-viewer code.hljs .hljs-selector-class,
|
|
.source-viewer code.hljs .hljs-selector-attr,
|
|
.source-viewer code.hljs .hljs-selector-pseudo,
|
|
.source-viewer code.hljs .hljs-number {
|
|
color: #d19a66;
|
|
}
|
|
.source-viewer code.hljs .hljs-symbol,
|
|
.source-viewer code.hljs .hljs-link,
|
|
.source-viewer code.hljs .hljs-meta,
|
|
.source-viewer code.hljs .hljs-selector-id,
|
|
.source-viewer code.hljs .hljs-title {
|
|
color: #61aeee;
|
|
}
|
|
.source-viewer code.hljs .hljs-built_in,
|
|
.source-viewer code.hljs .hljs-title.class_,
|
|
.source-viewer code.hljs .hljs-class .hljs-title {
|
|
color: #e6c07b;
|
|
}
|
|
.source-viewer code.hljs .hljs-emphasis {
|
|
font-style: italic;
|
|
}
|
|
.source-viewer code.hljs .hljs-strong {
|
|
font-weight: bold;
|
|
}
|
|
|
|
/* highlight.js — Atom One Light (light theme) */
|
|
[data-theme="light"] .source-viewer code.hljs {
|
|
color: #383a42;
|
|
background: transparent;
|
|
}
|
|
[data-theme="light"] .source-viewer code.hljs .hljs-comment,
|
|
[data-theme="light"] .source-viewer code.hljs .hljs-quote {
|
|
color: #a0a1a7;
|
|
font-style: italic;
|
|
}
|
|
[data-theme="light"] .source-viewer code.hljs .hljs-doctag,
|
|
[data-theme="light"] .source-viewer code.hljs .hljs-keyword,
|
|
[data-theme="light"] .source-viewer code.hljs .hljs-formula {
|
|
color: #a626a4;
|
|
}
|
|
[data-theme="light"] .source-viewer code.hljs .hljs-section,
|
|
[data-theme="light"] .source-viewer code.hljs .hljs-name,
|
|
[data-theme="light"] .source-viewer code.hljs .hljs-selector-tag,
|
|
[data-theme="light"] .source-viewer code.hljs .hljs-deletion,
|
|
[data-theme="light"] .source-viewer code.hljs .hljs-subst {
|
|
color: #e45649;
|
|
}
|
|
[data-theme="light"] .source-viewer code.hljs .hljs-literal {
|
|
color: #0184bc;
|
|
}
|
|
[data-theme="light"] .source-viewer code.hljs .hljs-string,
|
|
[data-theme="light"] .source-viewer code.hljs .hljs-regexp,
|
|
[data-theme="light"] .source-viewer code.hljs .hljs-addition,
|
|
[data-theme="light"] .source-viewer code.hljs .hljs-attribute,
|
|
[data-theme="light"] .source-viewer code.hljs .hljs-meta .hljs-string {
|
|
color: #50a14f;
|
|
}
|
|
[data-theme="light"] .source-viewer code.hljs .hljs-attr,
|
|
[data-theme="light"] .source-viewer code.hljs .hljs-variable,
|
|
[data-theme="light"] .source-viewer code.hljs .hljs-template-variable,
|
|
[data-theme="light"] .source-viewer code.hljs .hljs-type,
|
|
[data-theme="light"] .source-viewer code.hljs .hljs-selector-class,
|
|
[data-theme="light"] .source-viewer code.hljs .hljs-selector-attr,
|
|
[data-theme="light"] .source-viewer code.hljs .hljs-selector-pseudo,
|
|
[data-theme="light"] .source-viewer code.hljs .hljs-number {
|
|
color: #986801;
|
|
}
|
|
[data-theme="light"] .source-viewer code.hljs .hljs-symbol,
|
|
[data-theme="light"] .source-viewer code.hljs .hljs-link,
|
|
[data-theme="light"] .source-viewer code.hljs .hljs-meta,
|
|
[data-theme="light"] .source-viewer code.hljs .hljs-selector-id,
|
|
[data-theme="light"] .source-viewer code.hljs .hljs-title {
|
|
color: #4078f2;
|
|
}
|
|
[data-theme="light"] .source-viewer code.hljs .hljs-built_in,
|
|
[data-theme="light"] .source-viewer code.hljs .hljs-title.class_,
|
|
[data-theme="light"] .source-viewer code.hljs .hljs-class .hljs-title {
|
|
color: #c18401;
|
|
}
|
|
[data-theme="light"] .source-viewer code.hljs .hljs-emphasis {
|
|
font-style: italic;
|
|
}
|
|
[data-theme="light"] .source-viewer code.hljs .hljs-strong {
|
|
font-weight: bold;
|
|
}
|