diff --git a/tailwind.config.js b/tailwind.config.js
index eddd1fd..5356b9e 100644
--- a/tailwind.config.js
+++ b/tailwind.config.js
@@ -7,6 +7,22 @@ module.exports = {
],
theme: {
extend: {
+ colors: {
+ 'pt-blue': {
+ 50: '#e8f2f6',
+ 100: '#dde8f0',
+ 200: '#b8d4dc',
+ 300: '#9dbdcb',
+ 400: '#86aab6',
+ 500: '#306f8e',
+ 600: '#1f5a6e',
+ },
+ 'pt-sage': {
+ 400: '#83a1a1',
+ 500: '#6f8f96',
+ },
+ 'pt-navy': '#1e3a5f',
+ },
screens: {
// Adjusted for current hybrid usage (hero changes at sm, header/layout at md)
'sm': '768px', // iPad portrait + when hero layout activates
diff --git a/web/modules/custom/riverside_pt/js/calendar.js b/web/modules/custom/riverside_pt/js/calendar.js
index a32b548..f542489 100644
--- a/web/modules/custom/riverside_pt/js/calendar.js
+++ b/web/modules/custom/riverside_pt/js/calendar.js
@@ -3,6 +3,8 @@
const el = document.getElementById('riverside-calendar');
if (!el) return;
+ requestAnimationFrame(function () {
+
const calendar = new FullCalendar.Calendar(el, {
initialView: 'dayGridMonth',
headerToolbar: { left: 'prev', center: 'title', right: 'next' },
@@ -101,5 +103,7 @@
});
calendar.render();
+
+ }); // end requestAnimationFrame
});
})(drupalSettings);
diff --git a/web/modules/custom/riverside_pt/riverside_pt.routing.yml b/web/modules/custom/riverside_pt/riverside_pt.routing.yml
index 22215b6..ebce8a2 100644
--- a/web/modules/custom/riverside_pt/riverside_pt.routing.yml
+++ b/web/modules/custom/riverside_pt/riverside_pt.routing.yml
@@ -1,3 +1,11 @@
+riverside_pt.palette:
+ path: '/dev/palette'
+ defaults:
+ _controller: '\Drupal\riverside_pt\Controller\PaletteController::page'
+ _title: 'Color Palette'
+ requirements:
+ _permission: 'administer site configuration'
+
riverside_pt.home:
path: '/home'
defaults:
diff --git a/web/modules/custom/riverside_pt/src/Controller/PaletteController.php b/web/modules/custom/riverside_pt/src/Controller/PaletteController.php
new file mode 100644
index 0000000..5da304e
--- /dev/null
+++ b/web/modules/custom/riverside_pt/src/Controller/PaletteController.php
@@ -0,0 +1,97 @@
+parseColors();
+
+ if (!$colors) {
+ return ['#markup' => '
Could not parse tailwind.config.js
'];
+ }
+
+ $html = '';
+
+ foreach ($colors as $group => $shades) {
+ $html .= '
'
+ . htmlspecialchars($group) . '
';
+
+ foreach ($shades as $shade => $hex) {
+ $label = $shade === 'DEFAULT' ? $group : "$group-$shade";
+ $lum = $this->luminance($hex);
+ $textColor = $lum > 140 ? '#333' : '#fff';
+ $border = $lum > 200 ? 'border:1px solid #ccc;' : '';
+
+ $html .= '
'
+ . "
"
+ . "
"
+ . htmlspecialchars("$label — $hex")
+ . '';
+ }
+ }
+
+ $html .= '
';
+
+ return ['#markup' => $html];
+ }
+
+ private function parseColors(): array {
+ $path = dirname(DRUPAL_ROOT) . '/tailwind.config.js';
+ if (!file_exists($path)) {
+ return [];
+ }
+ $content = file_get_contents($path);
+
+ // Find the opening of the colors: { block
+ if (!preg_match('/colors\s*:\s*\{/', $content, $m, PREG_OFFSET_CAPTURE)) {
+ return [];
+ }
+ $start = $m[0][1] + strlen($m[0][0]);
+
+ // Walk forward counting braces to find the closing }
+ $depth = 1;
+ $i = $start;
+ $len = strlen($content);
+ while ($i < $len && $depth > 0) {
+ if ($content[$i] === '{') $depth++;
+ elseif ($content[$i] === '}') $depth--;
+ $i++;
+ }
+ $block = substr($content, $start, $i - $start - 1);
+
+ $colors = [];
+
+ // 'group': { shade: '#hex', ... }
+ preg_match_all("/'([^']+)'\s*:\s*\{([^}]+)\}/", $block, $groups, PREG_SET_ORDER);
+ foreach ($groups as $group) {
+ $name = $group[1];
+ preg_match_all('/(\w+)\s*:\s*\'(#[0-9a-fA-F]{3,6})\'/', $group[2], $shades, PREG_SET_ORDER);
+ foreach ($shades as $shade) {
+ $colors[$name][$shade[1]] = $shade[2];
+ }
+ }
+
+ // 'group': '#hex' (flat single-value entry)
+ preg_match_all("/'([^']+)'\s*:\s*'(#[0-9a-fA-F]{3,6})'/", $block, $singles, PREG_SET_ORDER);
+ foreach ($singles as $single) {
+ if (!isset($colors[$single[1]])) {
+ $colors[$single[1]]['DEFAULT'] = $single[2];
+ }
+ }
+
+ return $colors;
+ }
+
+ private function luminance(string $hex): int {
+ $hex = ltrim($hex, '#');
+ return (int) (
+ 0.299 * hexdec(substr($hex, 0, 2)) +
+ 0.587 * hexdec(substr($hex, 2, 2)) +
+ 0.114 * hexdec(substr($hex, 4, 2))
+ );
+ }
+
+}
diff --git a/web/modules/custom/riverside_pt/templates/riverside-pt-home.html.twig b/web/modules/custom/riverside_pt/templates/riverside-pt-home.html.twig
index 9734cb5..0f0d8a6 100644
--- a/web/modules/custom/riverside_pt/templates/riverside-pt-home.html.twig
+++ b/web/modules/custom/riverside_pt/templates/riverside-pt-home.html.twig
@@ -111,7 +111,7 @@
-