You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@training.apache.org by rb...@apache.org on 2026/05/24 17:13:44 UTC

(training) 01/01: Add Perl starter presentation

This is an automated email from the ASF dual-hosted git repository.

rbowen pushed a commit to branch perl-starter-presentation
in repository https://gitbox.apache.org/repos/asf/training.git

commit 8fdaf1c1f8c646eec4c0d26496c339e4d70c1565
Author: Rich Bowen <rb...@rcbowen.com>
AuthorDate: Sun May 24 13:11:58 2026 -0400

    Add Perl starter presentation
    
    Generated training module for Apache Perl.
    Content researched from perl.apache.org.
    Requires human review before publishing.
---
 content/Apache/Perl/metadata.yaml                  |  28 ++
 content/Apache/Perl/pom.xml                        |  39 ++
 .../Apache/Perl/src/main/asciidoc/_settings.adoc   |  36 ++
 .../Perl/src/main/asciidoc/images/project-logo.png | Bin 0 -> 14808 bytes
 content/Apache/Perl/src/main/asciidoc/index.adoc   | 388 +++++++++++++++++
 content/Apache/Perl/src/main/theme/apache.css      | 457 +++++++++++++++++++++
 6 files changed, 948 insertions(+)

diff --git a/content/Apache/Perl/metadata.yaml b/content/Apache/Perl/metadata.yaml
new file mode 100644
index 0000000..8806db5
--- /dev/null
+++ b/content/Apache/Perl/metadata.yaml
@@ -0,0 +1,28 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+title: "Apache mod_perl"
+project_id: perl
+description: "Embedding the full power of Perl in the Apache HTTP Server"
+tags:
+  - web
+  - intro
+  - developer
+  - operator
+duration: "45-60 min"
+level: beginner
+language: perl
+slides: 25
+updated: "2026-05-24"
diff --git a/content/Apache/Perl/pom.xml b/content/Apache/Perl/pom.xml
new file mode 100644
index 0000000..4a11ab8
--- /dev/null
+++ b/content/Apache/Perl/pom.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.training</groupId>
+    <artifactId>content-parent-pom</artifactId>
+    <version>1.5.0-SNAPSHOT</version>
+    <relativePath>../../../tools/content-parent-pom/pom.xml</relativePath>
+  </parent>
+
+  <groupId>org.apache.training.content</groupId>
+  <artifactId>training-content-apache-perl</artifactId>
+  <version>1.0.0-SNAPSHOT</version>
+  <packaging>war</packaging>
+
+  <name>Training: Content: Apache: mod_perl</name>
+  <description>Apache Training module covering mod_perl — embedding Perl in the Apache HTTP Server</description>
+
+</project>
diff --git a/content/Apache/Perl/src/main/asciidoc/_settings.adoc b/content/Apache/Perl/src/main/asciidoc/_settings.adoc
new file mode 100644
index 0000000..9a16917
--- /dev/null
+++ b/content/Apache/Perl/src/main/asciidoc/_settings.adoc
@@ -0,0 +1,36 @@
+////
+
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+////
+
+:goto:
+:menu:
+:navigation:
+:status:
+:arrows:
+:revealjs_theme: black
+:revealjs_progress: true
+:revealjs_slidenumber: true
+:revealjs_center: false
+:revealjs_history: true
+:customcss: reveal.js-5.2.1/dist/theme/apache.css
+:favicon: https://apache.org/favicon.ico
+:icons: font
+:imagesdir: images
+:sourcedir: ../java
+:idprefix:
+:idseparator: -
diff --git a/content/Apache/Perl/src/main/asciidoc/images/project-logo.png b/content/Apache/Perl/src/main/asciidoc/images/project-logo.png
new file mode 100644
index 0000000..ac9face
Binary files /dev/null and b/content/Apache/Perl/src/main/asciidoc/images/project-logo.png differ
diff --git a/content/Apache/Perl/src/main/asciidoc/index.adoc b/content/Apache/Perl/src/main/asciidoc/index.adoc
new file mode 100644
index 0000000..68b3be2
--- /dev/null
+++ b/content/Apache/Perl/src/main/asciidoc/index.adoc
@@ -0,0 +1,388 @@
+////
+
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+////
+
+include::_settings.adoc[]
+== Apache mod_perl
+
+image::project-logo.png[Apache mod_perl, 500]
+
+The full power of Perl embedded in the Apache HTTP Server
+
+[.notes]
+--
+mod_perl brings together the full power of the Perl programming language and the Apache HTTP server. It is an Apache Software Foundation project, established in March 2000, licensed under the Apache Software License.
+--
+
+== What We'll Cover
+
+* *Part I* — What Is mod_perl?
+* *Part II* — Getting Started
+* *Part III* — Community & Resources
+
+[.notes]
+--
+This presentation introduces mod_perl — what it does, how to get started, and where to find the community. It targets newcomers as well as experienced developers looking to understand the project's current state.
+--
+
+== A Persistent Perl Interpreter
+
+* Embeds a persistent Perl interpreter inside httpd
+* Eliminates startup overhead of external CGI processes
+* Gives Perl code direct access to the Apache C API
+* Your existing CGI scripts still work — just faster
+
+[.notes]
+--
+mod_perl gives you a persistent Perl interpreter embedded in your web server. This lets you avoid the overhead of starting an external interpreter and avoids the penalty of Perl start-up time, giving you super-fast dynamic content.
+--
+
+== More Than CGI on Steroids
+
+* Manage Apache configuration from Perl
+* Create custom authentication systems
+* Build smart proxies and filters
+* Implement stateful session management
+* Customize every phase of the request lifecycle
+
+[.notes]
+--
+As the project homepage says: "mod_perl is more than CGI scripting on steroids. It is a whole new way to create dynamic content by utilizing the full power of the Apache web server to create stateful sessions, customized user authentication systems, smart proxies and much more."
+--
+
+== How It Works
+
+[source,text]
+----
+Client Request
+     |
+     v
+Apache HTTP Server (httpd)
+     |
+     v
+mod_perl (embedded Perl interpreter)
+     |
+     v
+Your Perl Handler Module
+     |
+     v
+Response
+----
+
+[.notes]
+--
+A request comes in to Apache. Instead of forking an external Perl process (as traditional CGI does), mod_perl has a persistent Perl interpreter already loaded inside the server process. Your handler code runs in-process, with full access to the Apache API.
+--
+
+== Two Generations
+
+[cols="1,1"]
+|===
+| mod_perl 1.0 | mod_perl 2.0
+
+| For Apache 1.3.x
+| For Apache 2.0.x / 2.2.x / 2.4.x
+
+| Version 1.31 (May 2009)
+| Version 2.0.13 (October 2023)
+
+| Stable, legacy
+| Current recommended version
+|===
+
+[.notes]
+--
+mod_perl 1.0 targets the legacy Apache 1.3.x series. mod_perl 2.0 is the current active line, supporting the modern Apache 2.x series. The latest release is version 2.0.13, released in October 2023.
+--
+
+== Key Benefits
+
+* *Performance* — no fork/exec overhead per request
+* *Full API access* — hook into every Apache phase
+* *Rich ecosystem* — hundreds of Apache::* / Apache2::* modules
+* *Backward compatible* — CGI scripts run unmodified
+
+[.notes]
+--
+The performance gain is the most immediate benefit, but the real power lies in accessing all phases of Apache's request processing: URI translation, authentication, authorization, content generation, logging, and more.
+--
+
+== Who Uses mod_perl?
+
+* Proven at massive scale on high-traffic sites
+* Used for dynamic content delivery and templating
+* Powers custom authentication and authorization layers
+* Drives content management and publishing pipelines
+
+[.notes]
+--
+Web sites like Slashdot and Wired Magazine have historically used mod_perl. The project's success stories page documents many high-traffic deployments.
+--
+
+== Prerequisites
+
+* Apache HTTP Server (2.0.x, 2.2.x, or 2.4.x) — built and installed
+* Perl (5.x) — with development headers
+* `apxs` — the Apache extension tool (usually in httpd's `bin/` directory)
+* C compiler (gcc or equivalent)
+
+[.notes]
+--
+Before installing mod_perl, you need the prerequisites: Apache httpd already installed with development headers, and a working Perl installation. The apxs tool is essential — it tells mod_perl how Apache was built.
+--
+
+== Download
+
+* Current release: **mod_perl 2.0.13** (October 2023)
+* Source: https://perl.apache.org/download/index.html
+* Always verify integrity with PGP, SHA256, or SHA512 signatures
+* Binary distributions also available for some platforms
+
+[.notes]
+--
+The download page at perl.apache.org provides source tarballs with cryptographic signatures. Always verify your download. Some OS package managers also ship mod_perl as a binary package.
+--
+
+== Building mod_perl
+
+[source,bash]
+----
+tar -xvzf mod_perl-2.0.13.tar.gz
+cd modperl-2.0
+perl Makefile.PL MP_APXS=/path/to/bin/apxs
+make && make test && make install
+----
+
+[.notes]
+--
+The build process is straightforward. The key parameter is MP_APXS, which should point to the apxs executable in your Apache installation. The test suite validates that everything works before installing.
+--
+
+== Enabling mod_perl in httpd
+
+[source,apache]
+----
+# In httpd.conf:
+LoadModule perl_module modules/mod_perl.so
+----
+
+* Restart Apache after enabling the module
+* Check `error_log` for the mod_perl version string
+
+[.notes]
+--
+Once installed, you enable mod_perl by adding the LoadModule directive to httpd.conf. On restart, the error log will confirm the loaded version, showing something like "mod_perl/2.0.13 Perl/v5.x.x configured".
+--
+
+== Your First Registry Script
+
+[source,apache]
+----
+Alias /perl/ /home/httpd/perl/
+<Location /perl/>
+    SetHandler perl-script
+    PerlResponseHandler ModPerl::Registry
+    PerlOptions +ParseHeaders
+    Options +ExecCGI
+</Location>
+----
+
+[.notes]
+--
+ModPerl::Registry lets your existing CGI scripts run under mod_perl with minimal changes. The Alias maps a URL path to a filesystem directory, and the Location block tells Apache to handle requests there through mod_perl's Registry handler.
+--
+
+== A Simple Registry Script
+
+[source,perl]
+----
+#!/usr/bin/perl
+print "Content-type: text/plain\n\n";
+print "mod_perl 2.0 rocks!\n";
+----
+
+* Save as `/home/httpd/perl/rock.pl`
+* Make executable: `chmod a+rx rock.pl`
+* Access: `http://localhost/perl/rock.pl`
+
+[.notes]
+--
+This is the simplest possible registry script — it looks exactly like a CGI script. The difference is that under mod_perl, the Perl interpreter stays loaded between requests, eliminating startup time.
+--
+
+== Writing a Handler Module
+
+[source,perl]
+----
+package MyApache2::Rocks;
+use strict;
+use warnings;
+
+use Apache2::RequestRec ();
+use Apache2::RequestIO ();
+use Apache2::Const -compile => qw(OK);
+
+sub handler {
+    my $r = shift;
+    $r->content_type('text/plain');
+    print "mod_perl 2.0 rocks!\n";
+    return Apache2::Const::OK;
+}
+1;
+----
+
+[.notes]
+--
+A handler module is the idiomatic mod_perl approach. The handler subroutine receives the request object ($r) which provides full access to the Apache API. This is where mod_perl really shines — you have access to every detail of the request and response.
+--
+
+== Configuring a Handler
+
+[source,apache]
+----
+PerlRequire /home/httpd/perl/startup.pl
+
+<Location /rocks>
+    SetHandler perl-script
+    PerlResponseHandler MyApache2::Rocks
+</Location>
+----
+
+The startup file sets up `@INC`:
+
+[source,perl]
+----
+use lib qw(/home/httpd/perl);
+1;
+----
+
+[.notes]
+--
+PerlRequire loads a startup script at server start that sets up library paths. Then the Location block maps a URL to your handler module. Apache routes matching requests to your handler subroutine.
+--
+
+== Apache Request Phases
+
+* URI Translation (`PerlTransHandler`)
+* Authentication (`PerlAuthenHandler`)
+* Authorization (`PerlAuthzHandler`)
+* Content Generation (`PerlResponseHandler`)
+* Logging (`PerlLogHandler`)
+
+[.notes]
+--
+mod_perl lets you hook into every phase of Apache's request processing lifecycle. Most people start with PerlResponseHandler for content generation, but you can customize authentication, URL mapping, logging, and more — all in Perl.
+--
+
+== Migration: 1.0 to 2.0
+
+* Enable the compatibility layer: `PerlModule Apache2::compat`
+* Namespace changed: `Apache::` → `Apache2::`
+* Constants moved: `use Apache2::Const`
+* Full migration guide in the documentation
+
+[.notes]
+--
+If you have existing mod_perl 1.0 code, the compatibility layer helps during transition. The main changes are namespace updates from Apache:: to Apache2:: and a new constants system. The project provides a comprehensive migration guide.
+--
+
+== Project Governance
+
+* Apache Software Foundation project since *March 2000*
+* PMC with *11 members*
+* Licensed under the Apache License 2.0
+* Reports to the ASF Board on a regular cycle
+
+[.notes]
+--
+mod_perl has been an ASF project since March 2000, making it one of the older Apache projects. The PMC currently has 11 members who oversee the project's direction, releases, and community health.
+--
+
+== Documentation
+
+* Comprehensive docs for both mod_perl 1.0 and 2.0
+* Getting started guide — "Getting Your Feet Wet"
+* API reference for all Apache2::* modules
+* Tutorials covering related topics for mod_perl programmers
+* https://perl.apache.org/docs/
+
+[.notes]
+--
+The project features extensive documentation at perl.apache.org/docs/. The "Getting Your Feet Wet" quickstart guide gets you up and running with the minimum information needed. Deeper documentation covers every API and configuration option.
+--
+
+== Mailing Lists
+
+* *modperl@perl.apache.org* — users and developers list
+** Subscribe: `modperl-subscribe@perl.apache.org`
+** Digest available: `modperl-subscribe-digest@perl.apache.org`
+* Archives available on multiple sites
+* Help: `modperl-help@perl.apache.org`
+
+[.notes]
+--
+The modperl mailing list is the primary community channel for questions, discussion, and announcements. Both users and developers participate. Send an empty email to the subscribe address to join.
+--
+
+== Source Repository
+
+* SVN repository: https://svn.apache.org/repos/asf/perl/
+* Bug reports via the project's Bugzilla
+* Contributions welcome: documentation, code, or testing
+
+[.notes]
+--
+The source code lives in the ASF Subversion repository. The project accepts contributions in many forms — code patches, documentation improvements, and testing help. See the Contribute page on perl.apache.org for details.
+--
+
+== Contributing
+
+* Help others on the mailing list
+* Improve or add documentation
+* Submit bug reports with reproducible test cases
+* Contribute code via SVN patches
+* Read the mod_perl 2.0 Developer's Guide
+
+[.notes]
+--
+There are many ways to contribute to mod_perl. The project's contribute page outlines three main paths: helping on the mailing list, contributing documentation, and sharing code. The Developer's Guide is recommended reading for code contributors.
+--
+
+== Related Ecosystem
+
+* *ModPerl::Registry* — run CGI scripts under mod_perl
+* *Apache2::Request* (libapreq2) — parse request data
+* *Template Toolkit*, *Mason*, *HTML::Template* — templating
+* Hundreds of CPAN modules for mod_perl
+
+[.notes]
+--
+The Perl community has built a rich ecosystem around mod_perl. The Products page on perl.apache.org lists software ready to run with mod_perl or assist with your development projects. CPAN is the primary source for add-on modules.
+--
+
+* https://perl.apache.org/docs/
+== Thank You!
+
+* Questions?
+* https://perl.apache.org/
+* modperl@perl.apache.org
+
+[.notes]
+--
+Thank you for attending. The best next step is to download mod_perl, try the quickstart guide, and join the mailing list if you have questions.
+--
diff --git a/content/Apache/Perl/src/main/theme/apache.css b/content/Apache/Perl/src/main/theme/apache.css
new file mode 100644
index 0000000..d8f2a14
--- /dev/null
+++ b/content/Apache/Perl/src/main/theme/apache.css
@@ -0,0 +1,457 @@
+/*
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+    https://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+*/
+
+/*********************************************
+ * APACHE TRAINING DARK THEME
+ * White text on black, large fonts for
+ * conference room visibility.
+ *********************************************/
+
+/*********************************************
+ * GLOBAL STYLES
+ *********************************************/
+body {
+  background-color: #1a1a1a;
+  background-image: none;
+}
+
+.reveal-viewport {
+  background-color: #1a1a1a;
+  color: #f0f0f0;
+  background-image: none !important;
+}
+
+.reveal {
+  font-family: "Segoe UI", Helvetica, Arial, sans-serif;
+  font-size: 32px;
+  font-weight: normal;
+  color: #f0f0f0;
+}
+
+/*********************************************
+ * SLIDE OVERFLOW — allow scrolling if content
+ * exceeds slide height
+ *********************************************/
+.reveal .slides section {
+  height: auto !important;
+  overflow-y: auto !important;
+}
+
+::selection {
+  color: #fff;
+  background: #42affa;
+  text-shadow: none;
+}
+
+.reveal .slides > section, .reveal .slides > section > section {
+  line-height: 1.4;
+  font-weight: inherit;
+}
+
+/*********************************************
+ * HEADERS — smaller than default
+ *********************************************/
+.reveal h1, .reveal h2, .reveal h3, .reveal h4, .reveal h5, .reveal h6 {
+  margin: 0 0 20px 0;
+  color: #ffffff;
+  font-family: "Segoe UI", Helvetica, Arial, sans-serif;
+  font-weight: 600;
+  line-height: 1.2;
+  letter-spacing: normal;
+  text-transform: none;
+  text-shadow: none;
+  word-wrap: break-word;
+}
+
+.reveal h1 {
+  font-size: 1.4em;
+}
+
+.reveal h2 {
+  font-size: 1.0em;
+}
+
+.reveal h3 {
+  font-size: 0.9em;
+}
+
+.reveal h4 {
+  font-size: 0.8em;
+}
+
+/*********************************************
+ * BODY TEXT — large for back-of-room
+ *********************************************/
+.reveal p {
+  margin: 20px 0;
+  line-height: 1.4;
+  font-size: 1em;
+}
+
+.reveal li {
+  font-size: 0.95em;
+  margin-bottom: 0.3em;
+}
+
+/* Ensure certain elements are never larger than the slide itself */
+.reveal img, .reveal video, .reveal iframe {
+  max-width: 95%;
+  max-height: 85%;
+}
+
+.reveal strong, .reveal b {
+  font-weight: bold;
+  color: #ffffff;
+}
+
+.reveal em {
+  font-style: italic;
+}
+
+.reveal ol, .reveal dl, .reveal ul {
+  display: inline-block;
+  text-align: left;
+  margin: 0 0 0 1em;
+}
+
+.reveal ol {
+  list-style-type: decimal;
+}
+
+.reveal ul {
+  list-style-type: disc;
+}
+
+.reveal ul ul {
+  list-style-type: square;
+}
+
+.reveal ul ul ul {
+  list-style-type: circle;
+}
+
+.reveal ul ul, .reveal ul ol, .reveal ol ol, .reveal ol ul {
+  display: block;
+  margin-left: 40px;
+}
+
+.reveal dt {
+  font-weight: bold;
+}
+
+.reveal dd {
+  margin-left: 40px;
+}
+
+.reveal q, .reveal blockquote {
+  quotes: none;
+}
+
+.reveal blockquote {
+  display: block;
+  position: relative;
+  width: 70%;
+  margin: 20px auto;
+  padding: 5px;
+  font-style: italic;
+  background: rgba(255, 255, 255, 0.05);
+  box-shadow: 0 0 2px rgba(255, 255, 255, 0.2);
+  color: #ccc;
+}
+
+.reveal blockquote p:first-child, .reveal blockquote p:last-child {
+  display: inline-block;
+}
+
+.reveal q {
+  font-style: italic;
+}
+
+/*********************************************
+ * CODE
+ *********************************************/
+.reveal pre {
+  display: block;
+  position: relative;
+  width: 90%;
+  margin: 20px auto;
+  text-align: left;
+  font-size: 0.55em;
+  font-family: "Fira Code", "Consolas", monospace;
+  line-height: 1.3em;
+  word-wrap: break-word;
+  box-shadow: 0 0 6px rgba(0, 0, 0, 0.3);
+}
+
+.reveal code {
+  font-family: "Fira Code", "Consolas", monospace;
+}
+
+.reveal pre code {
+  display: block;
+  padding: 10px;
+  overflow: auto;
+  max-height: 450px;
+  word-wrap: normal;
+  background: #2d2d2d;
+  color: #e0e0e0;
+  border-radius: 4px;
+}
+
+/*********************************************
+ * TABLES
+ *********************************************/
+.reveal table {
+  margin: auto;
+  border-collapse: collapse;
+  border-spacing: 0;
+}
+
+.reveal table th {
+  font-weight: bold;
+  color: #ffffff;
+}
+
+.reveal table th, .reveal table td {
+  text-align: left;
+  padding: 0.3em 0.6em;
+  border-bottom: 1px solid #555;
+  color: #e0e0e0;
+}
+
+.reveal table th[align="center"], .reveal table td[align="center"] {
+  text-align: center;
+}
+
+.reveal table th[align="right"], .reveal table td[align="right"] {
+  text-align: right;
+}
+
+.reveal table tr:last-child td {
+  border-bottom: none;
+}
+
+.reveal sup {
+  vertical-align: super;
+}
+
+.reveal sub {
+  vertical-align: sub;
+}
+
+.reveal small {
+  display: inline-block;
+  font-size: 0.6em;
+  line-height: 1.2em;
+  vertical-align: top;
+}
+
+.reveal small * {
+  vertical-align: top;
+}
+
+/*********************************************
+ * LINKS
+ *********************************************/
+.reveal a {
+  color: #42affa;
+  text-decoration: none;
+  -webkit-transition: color 0.15s ease;
+  -moz-transition: color 0.15s ease;
+  transition: color 0.15s ease;
+}
+
+.reveal a:hover {
+  color: #8dcffc;
+  text-shadow: none;
+  border: none;
+}
+
+.reveal .roll span:after {
+  color: #fff;
+  background: #068ee9;
+}
+
+/*********************************************
+ * IMAGES
+ *********************************************/
+.reveal section img {
+  margin: 15px 0;
+}
+
+.reveal a img {
+  -webkit-transition: all 0.15s linear;
+  -moz-transition: all 0.15s linear;
+  transition: all 0.15s linear;
+}
+
+.reveal a:hover img {
+  background: rgba(255, 255, 255, 0.2);
+  border-color: #42affa;
+  box-shadow: 0 0 20px rgba(0, 0, 0, 0.55);
+}
+
+/*********************************************
+ * NAVIGATION CONTROLS
+ *********************************************/
+.reveal .controls div.navigate-left, .reveal .controls div.navigate-left.enabled {
+  border-right-color: #42affa;
+}
+
+.reveal .controls div.navigate-right, .reveal .controls div.navigate-right.enabled {
+  border-left-color: #42affa;
+}
+
+.reveal .controls div.navigate-up, .reveal .controls div.navigate-up.enabled {
+  border-bottom-color: #42affa;
+}
+
+.reveal .controls div.navigate-down, .reveal .controls div.navigate-down.enabled {
+  border-top-color: #42affa;
+}
+
+.reveal .controls div.navigate-left.enabled:hover {
+  border-right-color: #8dcffc;
+}
+
+.reveal .controls div.navigate-right.enabled:hover {
+  border-left-color: #8dcffc;
+}
+
+.reveal .controls div.navigate-up.enabled:hover {
+  border-bottom-color: #8dcffc;
+}
+
+.reveal .controls div.navigate-down.enabled:hover {
+  border-top-color: #8dcffc;
+}
+
+/*********************************************
+ * PROGRESS BAR
+ *********************************************/
+.reveal .progress {
+  background: rgba(255, 255, 255, 0.2);
+}
+
+.reveal .progress span {
+  background: #42affa;
+  -webkit-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985);
+  -moz-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985);
+  transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985);
+}
+
+/*********************************************
+ * SLIDE NUMBER
+ *********************************************/
+.reveal .slide-number {
+  color: #888;
+  background-color: rgba(0, 0, 0, 0);
+}
+
+/*********************************************
+ * GENERAL PURPOSE COLORS
+ *********************************************/
+.reveal .red {
+  color: #ff4444;
+}
+
+.reveal .orange {
+  color: #ffaa44;
+}
+
+.reveal .yellow {
+  color: #ffff44;
+}
+
+.reveal .green {
+  color: #44ff44;
+}
+
+/*********************************************
+ * HIDE THE PERSISTENT HEADER/FOOTER from
+ * document.html.slim template
+ *********************************************/
+.header,
+.footer {
+  display: none !important;
+}
+
+/*********************************************
+ * PROJECT LOGO — small, top left of every slide
+ * Each module should place a project-logo.png
+ * in src/main/asciidoc/images/ OR override
+ * this rule in a local customcss with the
+ * project's logo URL.
+ *********************************************/
+.reveal::before {
+  content: "";
+  position: fixed;
+  top: 16px;
+  left: 16px;
+  width: 120px;
+  height: 36px;
+  background-image: url("../../../images/project-logo.png");
+  background-size: contain;
+  background-repeat: no-repeat;
+  opacity: 0.7;
+  z-index: 100;
+  pointer-events: none;
+}
+
+/*********************************************
+ * APACHE OAK LEAF — bottom right of every slide
+ *********************************************/
+.reveal::after {
+  content: "";
+  position: fixed;
+  bottom: 16px;
+  left: 16px;
+  width: 36px;
+  height: 36px;
+  background-image: url("../../../images/logo-apache.png");
+  background-size: contain;
+  background-repeat: no-repeat;
+  opacity: 0.6;
+  z-index: 100;
+  pointer-events: none;
+}
+
+/*********************************************
+ * C3JS Charts (dark mode)
+ *********************************************/
+.c3 {
+  fill: white;
+}
+
+.c3 line, .c3 path {
+  stroke: white !important;
+}
+
+/*********************************************
+ * Column layout
+ *********************************************/
+.reveal .west {
+  position: fixed;
+  left: 5%;
+}
+
+.reveal .east {
+  position: fixed;
+  right: 5%;
+}