/**
Theme Name: OleloOnline_2026
Author: Kaliko Beamer-Trapp
Author URI: https://oleloonline.com
Description: He mea hou kēia no ʻŌlelo Online ma ka mahina ʻo Iulai ma ka makahiki 2026. Init 2026-07-04. Main Revs
Version: 0.6.8
License: GNU General Public License v2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html
Text Domain: oleloonline_2026
Template: astra
*/

/* Last modified: 2026-08-09 09:28 HST (UTC-10) — rev 38. Bump this line and the
   Version: header above on every edit. HST is UTC-10 year-round; no DST. */

/* rev 38 on 2026-08-09: Section 20.6 (renumbered from a second, duplicate "20.4")
now pins the spacing around the sidebar subtitle in the two custom-HTML widgets,
VIRTUAL CLASSROOM and ONLINE LEARNING. It previously set colour and weight only and
left margins to inherit, on the stated reasoning that pinning them "would fight the
--oo-widget-* rhythm set in 20.1". That reasoning did not hold: inheriting produced
Astra's stock paragraph margins, not 20.1's rhythm, so the pitch line sat 16px below
the purple bar and ~24px above the links and the widget read as three fragments.
Now 8px on each side. The title bar's own 1rem margin-bottom is deliberately NOT
touched — it lives in the shared 20.2 rule that dresses all seven sidebar widgets,
so the subtitle claws its 8px back with a negative top margin instead of moving
every widget on the site. A companion rule zeroes the following link list's top
margin, because tightening only the paragraph would have closed half the gap and
looked like the edit had failed. First change to the stylesheet since the live
cutover; live and the Local copy were both 0.6.7 / rev 37 immediately beforehand. */

/* rev 37 on 2026-08-08: new Section 07.1 gives the bordered pepeke examples on
/0801p1-practice-with-ami-in-basic-pepeke-henua/ 2.4rem of vertical margin and 18px of
bottom padding, so the <part> underline and the sub-aligned label are not pressed against
the .mtbox frame. Companion to functions.php rev 11 (section 11), which is what actually
restored those lines: the 0801 examples are authored in a <label>-only shorthand with no
<part> elements, so there was nothing for section 07's border-bottom to attach to. That was
a content-markup gap, not a stylesheet regression — section 07 is byte-for-byte the 2015
rule set apart from the colour tokens. No CSS selector can reach a bare text node, so this
could not have been fixed here. Scoped to `.pepeke-example.mtbox`; the general `.mtbox`
callout frame is untouched. */

/* Kaliko's important CSS as child of Astra, rev 25 on 2026-08-06 (new Section 29: List Category Posts lesson listings — restores the 2015 two-colour split of purple helu kaʻina + green lesson title, removes the Section 21 underline inside the listing, and corrects two more 62.5%-root rem values left in Section 10) */

/* rev 36 on 2026-08-08: new Section 20.6 raises the sidebar login form's two field
labels ("Username or Email Address", "Password") from PMPro's 500 to 800. "Remember Me"
deliberately left alone. The rule mirrors PMPro's own (2,4,2) selector from variation_1.css
with `#secondary` prefixed, which wins on ID count without !important — three lower-specificity
attempts were tested in the live stylesheet first and none of them moved a pixel. Also adds the
Last modified timestamp line under the theme header, to be bumped with the Version on every edit. */

/* rev 35 on 2026-08-08: comments only, no declarations changed. Section 23's "ACTION REQUIRED IN wp-admin" banner and the 23.1 header were both stale and were instructing a future reader to set PMPro's `contrast` to #222222 — which would undo Kaliko's 2026-08-04 decision to keep the PMPro account/checkout pages' body copy purple. Found during a claude-docs reconciliation, where the project copy of pmpro-pages-audit-section23.md carried the same withdrawn instruction. Both blocks rewritten to record the settled state, measured from the rendered #pmpro_colors block: Accent #0d8700 (4.68:1, AA clear), Contrast #783194 (7.88:1), Base #ffffff. This mattered more than the docs did, because comments inside style.css travel to the VPS. */

/* rev 34 on 2026-08-07: search-results and listing repair. Section 02's bare `.entry-title { text-align: center }` removed — it was centring every heading in every search and archive listing, which 2015 never did; the centring Kaliko wants on single posts and pages moved to Section 22.4's already-scoped selector. New Section 32 un-floats the pagination prev/next, which Astra's own dynamic CSS sets to `float: none` and then immediately overrides with `float: right`. The remaining search-page faults — the centred H1 and the category printed twice per result — are Customizer settings, not CSS, and are listed in claude-docs/search-results-page-section32.md for Kaliko to apply. */

/* rev 33 on 2026-08-07: Section 29.5's lesson rows on /coursework-index-by-category/ raised from 400 to 600. A deliberate departure from 2015, not a repair — live measures Arial 16px/400 there and rev 31 matched it, but Inter 400 is optically lighter than Arial 400, so numeric parity was hiding a real loss of weight. 600 rather than the <dl> variant's 700, and the 16px size left alone; reasoning in full in the 29.5 header. */

/* rev 32 on 2026-08-07: Section 19 (.kuuhawaii) rem values corrected - 17 declarations, the fourth and last instance of the 62.5%-root trap. The song-notes article had been rendering at 25.6px body text with 38.4px headings. The standing "do not touch Section 19" rule was lifted by Kaliko for the rem values only; the colour and token cleanup stays deferred to the rebuild and is now itemised in the section header. */

/* rev 31 on 2026-08-06: new Section 29.5 styles the <ul> variant of the LCP listings (papaheluinoanohie.php), which turned up on /coursework-index-by-category/ running nine blocks. The 2015 look there came entirely from generic .post-content ul/li rules that Astra has no equivalent for, so list geometry, bullet suppression and the purple-code/green-title split all had to be restated. Colours read the 29.1 tokens, so both LCP variants move together. */

/* rev 30 on 2026-08-06: Section 30's colour scheme inverted to match the LCP listings — helu kaʻina now deep purple, lesson title now brand green, both gaining a grey underline on hover/focus/active; the title rule raised to (0,4,1) because the old (0,2,1) had never beaten Astra Pro's own (0,3,1) and the hover was a no-op. Section 20.4's widget subtitle corrected from a mistyped #ab0a65 to var(--oo-purple-dark). Section 31 (clock-table wrapping) committed from mobile-table-overflow-section31.md. */

/* rev 29 on 2026-08-06: RESTORED Section 30 (Related Posts, "curriculum index") from the CSS Kaliko was given earlier the same day as "Section 28" and renumbered to 30.x. It had been lost when style.css reverted to its 2026-08-05 state, taking the earlier Section 29 with it. Includes the mobile-heading addition that related-posts-section30.md had recorded as delivered-but-not-committed. */

/* rev 28 on 2026-08-06: swept 58 ported 2015 rem values in Sections 02-18 to their true px equivalents (1rem meant 10px under the old 62.5% root); repaired the ul.checks/crosses marker lists, which were showing a disc bullet beside the glyph and positioning the glyph against the page rather than the list item; new 20.4 gives the sidebar widget subtitle its own colour and weight. */

/* rev 27 on 2026-08-06: Section 10's .questionAnswerBlock corrected for the 62.5%-root rem trap (third instance — six values, all 60% oversized) and given back the 2015 dt hairline. New --oo-rule-hairline token in Section 01 replaces Section 29's --oo-lcp-rule, since both block classes now use it. */

/* rev 26 on 2026-08-06: Section 29's colour rules rescoped from .definitionListBlock to the new .lcp-lesson-list marker emitted by the LCP templates. .definitionListBlock is hand-authored in lesson content in at least eight places and some of those have links in the <dt>, which rev 25 was turning green. The separator/indent rules in 29.4 deliberately stay generic — they were generic in 2015 too. */

/* =========================================================
   01) THEME TOKENS (NON-BREAKING ADDITION)
========================================================= */
:root {
  /* 2026-08-03: darkened from #0d8c00 to #0d8800 (green channel 140 -> 136).
     White-on-green went 4.40:1 -> 4.63:1, clearing the WCAG AA 4.5:1 floor
     for the tagline and nav links on the header band; green-text-on-white
     improves by the same amount. Visually near-identical. This is now the
     official brand dark green.
     NOTE: two hardcoded #0d8c00 values remain in Section 19 (.kuuhawaii,
     the untouched temporary test block). They are deliberately left alone
     under the standing "do not touch Section 19" rule, but they will now
     drift from this token -- fold them in when Section 19 is rebuilt. */
  --oo-green-dark: #0d8800;
  --oo-green-mid: #6EC53B;
  --oo-green-light: #B4EC92;

  --oo-purple-dark: #4B0A65;
  --oo-purple-mid: #793195;
  --oo-purple-light: #B782CC;

  --oo-orange-dark: #974E08;
  --oo-orange-mid: #E19043;
  --oo-orange-light: #FFB670;

  /* added 2026-07-31: the site's original brand orange from the 2015 theme,
     kept distinct from the --oo-orange-* trio above. Reserved for the
     .help/.info/.error/.success notice-box family once that gets rebuilt
     (not wired up yet -- see project audit notes). */
  --original-orange: #ff9700;

  --oo-text-gray: #6B6476;
  --oo-text-gray-mid: #636363;
  --oo-border-gray: #ddd;
  --oo-icon-gray: #a0a0a0;
  --oo-bg-mint: #f7fcfa;

  /* added 2026-08-03 (Section 22): the two neutral rules the 2015 theme used
     inside content tables. Deliberately NOT folded into --oo-border-gray
     (#ddd) -- these are darker and carry the row/header distinction that
     makes the class timetable readable. */
  --oo-rule-light: #d0d0d0;   /* td bottom rule */
  --oo-rule-dark:  #848484;   /* th bottom rule */

  /* added 2026-08-06 (rev 27): the 2015 definition-list hairline. In the old
     theme this was hardcoded in `.post-content dt { border-bottom: 1px solid
     #999 }`, a generic rule that caught every <dt> in post content. 2026 states
     it per block class instead (Section 10 for .questionAnswerBlock, Section
     29.4 for .definitionListBlock) so it cannot reach dl markup emitted by
     Astra or a plugin — but both should read the same token, which is why it
     lives here rather than in either section.

     Deliberately a third value rather than folded into --oo-rule-light
     (#d0d0d0) or --oo-rule-dark (#848484): it sits between them, and it is a
     text-block separator rather than a table rule. Decorative, so no contrast
     floor applies. */
  --oo-rule-hairline: #999;
}

/* =========================================================
   02) BASIC TEXT + COLOR UTILITIES
========================================================= */

/* REMOVED 2026-08-07 (rev 34): `.entry-title { text-align: center }`.

   Same fault Section 22.4 documents for font-size, in the same class, left
   behind when that one was fixed. `.entry-title` is not the page title --
   Astra reuses it for every heading in a blog, archive or search listing, so
   the bare selector was centring all twelve headings on /?s=grammar and every
   heading on /category/0400-series-pronunciation-prosody/ as well.

   Centred listing headings are not 2015 behaviour. Checked all twenty
   `.entry-title` rules in OleloOnline_2015/style.css: not one sets
   text-align, and `.entry-title-search-results` (the class 2015 gave search
   headings) does not either. Live measures `start` on both.

   The centring Kaliko does want -- single posts and pages -- moved to the
   scoped selector in Section 22.4, which is already this stylesheet's
   authority for that element.

   Related Posts were unaffected either way: Section 30.2 pins
   `.ast-single-related-posts-container .ast-related-post .ast-related-post-title`
   to left at (0,3,0) and was already beating this rule. Verified before
   removal rather than assumed. */

.bluetext { color: blue; }
.redtext {}

.dgreentext { color: #50AA1A; }
.mgreentext { color: var(--oo-green-mid); }
.lgreentext { color: var(--oo-green-light); }

.dpurpletext { color: var(--oo-purple-dark); }
.mpurpletext { color: var(--oo-purple-mid); }
.lpurpletext { color: var(--oo-purple-light); }

.dorangetext { color: var(--oo-orange-dark); }
.morangetext { color: var(--oo-orange-mid); }
.lorangetext { color: var(--oo-orange-light); }

.eleele { color: var(--oo-text-gray-mid); }
.kaele { font-weight: bold; }

.kahalalo { text-decoration: underline; }
.kahawaena { text-decoration: line-through; color: var(--oo-text-gray); }

.importantText { font-weight: bold; }

.centeredtextblock { text-align: center; display: block; }

/* added 2026-07-31: sized a little below normal body text, per request */
.smalltext { font-size: 0.85em; }

/* =========================================================
   03) BACKGROUND + SPACING UTILITIES
========================================================= */
.bg-grey   { background-color: rgba(208, 208, 208, 0.40); }
.bg-green  { background-color: rgba(13, 140, 0, 0.20); }
.bg-purple { background-color: rgba(121, 49, 149, 0.20); }
.bg-orange { background-color: rgba(255, 177, 64, 0.20); }
.bg-pink   { background-color: rgba(255, 204, 204, 0.20); }

.gap_b05 { margin-bottom: .8em; }
.gap_b10 { margin-bottom: 1.6em; }
.gap_b20 { margin-bottom: 2.4em; }

.indenttext1 { text-indent: 10px; }
.indenttext2 { text-indent: 20px; }
.indenttext3 { text-indent: 30px; }
.indenttext4 { text-indent: 40px; }

div.kaulihihema  { text-align: left; }
div.kaulihilike  { text-align: justify; }
div.kaulihiakau  { text-align: right; }

/* =========================================================
   04) POST CONTENT TYPOGRAPHY
========================================================= */
.post-content h3 {
  color: var(--oo-green-dark);
  margin-top: 40px;
}
.post-content h3:first-of-type { margin-top: 0; }
.post-content h4 { color: var(--oo-green-dark); }

.post-content p#payment-methods { text-align: center; }

p.centered, h3.centered {
  text-align: center;
  margin-top: 20px;
}

/* ported from OleloOnline_2015 base theme, 2026-07-31 -- oversized quote
   mark kept intentionally; px-fallback duplicates from the original
   (pre-rem-support era) dropped as no longer needed */
.post-content blockquote {
  font-style: italic;
  line-height: 26px;
  margin: 24px 35px 24px 56px;
}
.post-content blockquote:before {
  font-family: Georgia, serif;
  font-weight: 700;
  content: "\201C";
  font-size: 80px;
  text-indent: -60px;
  margin-top: 12px;
  float: left;
  opacity: .2;
}

/* =========================================================
   05) CONTENT BOXES / CALLOUTS
========================================================= */
div.resourceMain {
  box-sizing: border-box;
  padding: 10px;
  border: 2px solid var(--oo-orange-mid);
  border-radius: 5px;
  margin-top: 10px;
  margin-bottom: 10px;
  background-color: #edf6f2;
}
div.resourceMain:hover { background-color: #ddede6; }

div.resourceAdditional {
  box-sizing: border-box;
  padding: 10px;
  border: 1px solid var(--oo-purple-mid);
  border-radius: 5px;
  margin-top: 10px;
  margin-bottom: 10px;
  background-color: var(--oo-bg-mint);
}

div.resourceMain a,
div.resourceAdditional a { font-weight: bold; }

div.resourceMain h4 { color: black; }
div.resourceAdditional h4 { color: black; }

div.moolelo {
  box-sizing: border-box;
  border-radius: 20px;
  border-left: 3px solid var(--oo-purple-mid);
  padding: 20px 0 10px 15px;
  margin: 40px 0 20px 0;
}
div.moolelo h2 {
  color: var(--oo-purple-mid);
  font-weight: bold;
  font-size: 28px;
  text-transform: uppercase;
}

div.calloutbox {
  box-sizing: border-box;
  border-radius: 20px;
  border-left: 3px solid #c1c1c1;
  padding: 20px 0 10px 15px;
  margin: 40px 0 20px 0;
}
div.calloutbox h2 {
  text-align: left;
  color: #c1c1c1;
  font-weight: bold;
  font-size: 28px;
  text-transform: uppercase;
}
div.calloutbox p.source {
  font-weight: bold;
  margin-bottom: 0;
  text-align: right;
}
div.calloutbox p.extract {
  color: #6f6f6f;
  margin-left: 20px;
  margin-right: 20px;
  padding: 10px 10px 10px 25px;
  font-style: italic;
  background: #fff url("https://oleloonline.com/wp-content/uploads/2016/09/image-quotes-gray-22x19.png") 0 8px no-repeat;
}
div.calloutbox p.translation {
  font-style: normal;
  margin-left: 20px;
  margin-right: 20px;
  padding: 10px;
}

div.disclosure { margin-top: 10px; margin-bottom: 30px; }
.calledout { color: var(--oo-orange-mid); text-decoration: underline; }

/* =========================================================
   06) INLINE SEMANTIC HELPERS
========================================================= */
sup, .superscript {
  font-size: .75em;
  vertical-align: super;
  padding-left: 2px;
}
sub, .subscript {
  font-size: .75em;
  vertical-align: sub;
  padding-left: 2px;
}

/* =========================================================
   07) LANGUAGE/GRAMMAR BLOCKS
========================================================= */
div.laanapepeke {
  font-family: monospace, sans-serif;
  overflow: auto;
  background: #f5f5f5;
  border: 1px solid #f0f0f0;
  border-left: 3px solid #e0e0e0;
  word-wrap: break-word;
  margin: 0 24px 24px 24px;
}
div.laanapepeke p {
  padding: 15px 15px 15px 24px;
  margin-bottom: 0;
}
div.laanapepeke p.laana { font-weight: bold; }
div.laanapepeke p.unuhi {
  font-style: italic;
  border-top: 3px solid #e0e0e0;
}

.pepeke-example part {
  padding-left: .3em;
  border-left: 1px solid var(--oo-green-dark);
  border-bottom: 1px solid var(--oo-green-dark);
}
.pepeke-example part.kuhia {
  padding-left: .3em;
  border-left: 1px solid var(--oo-orange-mid);
  border-bottom: 1px solid var(--oo-orange-mid);
}
.pepeke-example label {
  font-size: .75em;
  vertical-align: sub;
  padding-left: 2px;
  color: var(--oo-green-dark);
  margin-right: .75em;
}
.pepeke-example label.kuhia {
  font-size: .75em;
  vertical-align: sub;
  padding-left: 2px;
  color: var(--oo-orange-mid);
  margin-right: .75em;
}
.pepeke-example meanui { background: yellow; }

/* ---------------------------------------------------------------------------
   07.1  Breathing room for a pepeke example that is also a bordered box
   ---------------------------------------------------------------------------
   Added 2026-08-08 (rev 37), alongside functions.php section 11.

   The practice pages set `class="pepeke-example mtbox bg-orange"`, so the
   example sits inside the generic `.mtbox` frame from section 11 — 10px of
   padding all round and no top margin at all, since Astra's `p` supplies only
   a bottom one. That was survivable while the example was plain text. It is
   not survivable now that section 07 draws a border-bottom under every <part>
   and hangs a `vertical-align: sub` label off the end of each one, because
   both of those live at the very bottom of the line box:

       measured on /0801p1-practice-with-ami-in-basic-pepeke-henua/ before this
       rule — box height 50.7px = 27.2px line-height + 20px padding + 2px
       border, leaving the part underline and the descending label roughly 4px
       clear of the frame's own bottom border. Three lines of green inside 4px.

   So this adds room in the two places it is actually needed and nowhere else:

     - padding-bottom 18px against 12px elsewhere in the box, to separate the
       part underline from the frame border below it. This is the one that
       stops the clutter; the top padding barely matters because nothing
       descends from the top of the line.
     - 2.4rem of vertical margin, replacing 0 above and Astra's 1.6em below, so
       consecutive examples in a set read as separate items rather than a
       stack. Adjacent margins collapse, so a run of these boxes gets 2.4rem
       between them, not 4.8rem.

   SCOPED TO THE COMPOUND SELECTOR, deliberately. `.mtbox` on its own is the
   site's general callout frame and is used for notices that have no pepeke in
   them; widening that would move boxes on pages nobody has looked at in this
   build. Both classes must be present for this to apply.

   NOT APPLIED to `div.laanapepeke` examples (0699, the two 0500-series time
   posts). Those already carry 15px of padding and sit in their own grey frame,
   and they were the reference this page was being matched to — changing them
   would move the target.
   --------------------------------------------------------------------------- */

.pepeke-example.mtbox {
  margin-top: 2.4rem;
  margin-bottom: 2.4rem;
  padding: 10px 12px 18px;
}

/* =========================================================
   08) VOCAB / TABLE FORMATTING
========================================================= */
table td span.tdhaka { margin-right: 10px; }
table.vocabTable { margin-left: 10px; }

.vocabSectionTitle { color: var(--oo-purple-mid); font-weight: bold; }

.vocabBody td {
  border-top: 1px solid var(--oo-border-gray);
  padding: 6px 10px 6px 0;
  white-space: normal; /* fixed from invalid 'wrap' */
}
.vocabBody td.gloss { white-space: nowrap; }

.gloss { color: var(--oo-purple-mid); padding-right: 40px; }
.meaning { color: var(--oo-text-gray); }

.hopuna { color: var(--oo-purple-mid); padding-right: 40px; }
.hopuna strong { color: var(--oo-orange-dark); font-weight: 400; }

.hopuna-meaning { color: var(--oo-text-gray); padding-right: 40px; }
.hopuna-meaning strong { color: var(--oo-orange-dark); font-weight: 400; }

hr.vocab { border-top: 1px solid gray; margin: 4px 0; }

p.footnotesTitle { font-size: 15px; margin: 5px 0 0 0; }
ul.vocabFootnotes {
  font-size: 14px;
  border-bottom: 1px solid grey;
  margin-bottom: 20px;
  list-style-image: none;
  list-style-type: none;
}

/* =========================================================
   09) LIST STYLES
========================================================= */
/* --------------------------------------------------------------------------
   Marker lists — ul.circles / ul.arrows / ul.checks / ul.crosses
   --------------------------------------------------------------------------
   REPAIRED 2026-08-06 (rev 28). The tick marks on
   /0801p1-practice-with-ami-in-basic-pepeke-henua/ were rendering as ordinary
   disc bullets. Two separate faults, both inherited:

   1. The old rule only reset `ul.circles li, ul.arrows li` — `.checks` and
      `.crosses` were never in the list. In 2015 that did not matter, because a
      generic `.post-content ul { list-style: none }` in the parent theme
      removed the marker for every content list. Astra has no such rule, so the
      disc came back on exactly the two classes the reset had forgotten. The
      ::before glyph was drawing correctly the whole time; it was sitting
      alongside a bullet nobody had asked for.

   2. `li` was `position: static`. Every ::before here is `position: absolute`,
      so with no positioned ancestor the glyphs were being placed against the
      page container instead of their own list item. Measured on live: 2015's
      li carried `position: relative; padding-left: 12px` from a generic rule
      that likewise has no Astra equivalent.

   Measured on live 2015 and reproduced exactly below:
       ul   list-style none, padding-left 0, margin-left 20px
       li   list-style none, position relative, padding-left 12px
       ::before  absolute, top 1px, left -10px (-5px for circles),
                 15px, #a0a0a0

   The `> li` child combinator is deliberate: a nested plain <ul> inside one of
   these lists keeps its own normal bullets rather than silently losing them.
   -------------------------------------------------------------------------- */

ul.circles,
ul.arrows,
ul.checks,
ul.crosses {
  list-style-type: none;
  list-style-image: none;
  padding-left: 0;
  margin-left: 20px;
}

/* The 20px indent needs restating at higher specificity inside post content.
   Astra emits `.entry-content[data-ast-blocks-layout] > * { margin-left: auto }`
   at (0,2,0), which outranks the (0,1,1) rule above and was collapsing the
   indent to zero. Measured: my rule matched and declared 20px, computed came
   back 0px. `auto` is what makes this hard to spot — it resolves to a used
   value in px, so getComputedStyle reports a plausible number and nothing
   looks overridden unless you enumerate the matching rules.

   `.entry-content ul { margin-left: revert }` also sits at (0,1,1) and would
   win on order alone, so going to (0,2,1) settles both at once. Specificity,
   not !important — same approach as Section 21. */

.entry-content ul.circles,
.entry-content ul.arrows,
.entry-content ul.checks,
.entry-content ul.crosses {
  padding-left: 0;
  margin-left: 20px;
}

ul.circles > li,
ul.arrows > li,
ul.checks > li,
ul.crosses > li {
  list-style-type: none;
  position: relative;
  padding-left: 12px;
}

ul.circles li::before {
  content: "\25cd";
  position: absolute;
  top: 1px;
  left: -5px;
  color: #a0a0a0;
  font-size: 15px;
}
ul.arrows li::before {
  content: "\279c";
  position: absolute;
  top: 1px;
  left: -10px;
  color: #a0a0a0;
  font-size: 15px;
}
ul.checks li::before {
  content: "\2714";
  position: absolute;
  top: 1px;
  left: -10px;
  color: #a0a0a0;
  font-size: 15px;
}
ul.crosses li::before {
  content: "\2718";
  position: absolute;
  top: 1px;
  left: -10px;
  color: #a0a0a0;
  font-size: 15px;
}

ul.plainlist {
  list-style-image: none;
  list-style-type: none;
}

/* =========================================================
   10) DETAILS / DEFINITION / Q&A BLOCKS
========================================================= */
summary { font-weight: bold; }
details { margin-left: 10px; }

/* CORRECTED 2026-08-06 (rev 25) — same 62.5%-root trap already documented for
   ul.footlings further down this section. The 2015 stylesheet ran under
   `html { font-size: 62.5% }`, so `1.8rem` meant 18px and `2rem` meant 20px.
   Astra runs a normal 16px root, so these were rendering at 28.8px and 32px —
   a 60% oversize that made every lesson title on /coursework-by-series/ read as
   a heading rather than a list item. Restated in px, which is what the 2015
   numbers always were. Kept in px rather than converted to 1.125rem for the
   same reason as footlings: these are literal parity values and must not be
   able to silently rescale again if the root size ever moves.
   Colour, link behaviour and the separator rule live in Section 29. */

.definitionListBlock > dl { margin-bottom: 50px; }
.definitionListBlock > dl > dt {
  font-size: 18px;   /* was 1.8rem — see note above */
  font-style: normal;
  font-weight: bold;
  margin-top: 0;
  color: var(--oo-purple-dark);
}
.definitionListBlock > dl > dd {
  font-size: inherit;
  font-style: normal;
  margin-top: 0;
  color: rgb(107, 100, 118);
  margin-bottom: 40px;
}

/* Fixed dangerous global selector leakage */
.definitionListBlock a,
.definitionListBlock a:visited,
.definitionListBlock a:hover {
  text-decoration: none;
}

.definitionListBlock.LCP { margin-left: 20px; }   /* was 2rem — see note above */
.LCP-series-titles {}

/* CORRECTED 2026-08-06 (rev 27) — the 62.5%-root trap, third instance, after
   ul.footlings (rev 23) and .definitionListBlock (rev 25). Every rem value in
   this block was written against the 2015 stylesheet's `html { font-size:
   62.5% }`, i.e. a 10px root, so each one was rendering 60% larger on Astra's
   16px root.

   Measured on /0801p1-practice-with-ami-in-basic-pepeke-henua/ — the only
   member-facing page using this block — live 2015 vs staging before the fix:

       dt margin-top (2nd onward)   60px  ->  96px     6rem
       dd margin-bottom             20px  ->  32px     2rem
       dd padding-left              10px  ->  16px     1rem
       dd margin-left               20px  ->  32px     2rem
       last dd margin-bottom        60px  ->  96px     6rem
       dd.analysis margin-left      30px  ->  48px     3rem

   Root font-size confirmed by measurement: live 10px, staging 16px. On a page
   with six question sets the inflated 6rem gaps alone added roughly 200px of
   dead vertical space.

   Restated in px, matching the footlings and definitionListBlock corrections:
   these are literal 2015 parity values, and pinning them means they cannot
   silently rescale again if the root size ever moves.

   The dt hairline is also 2015's. On live it came from the generic
   `.post-content dt { border-bottom: 1px solid #999 }`, which caught every
   definition list in post content. It is stated explicitly here rather than
   restored as a generic `dt` rule, so it cannot reach dl markup emitted by
   Astra or a plugin. Section 29.4 does the same job for .definitionListBlock;
   between them the two known block classes are covered.

   OTHER PAGES USING THIS BLOCK: /ka-nani-o-ka-css/ (your private CSS style
   guide, 2 blocks) and /20260619-1829/ (a scratch post, 2 blocks). */

.questionAnswerBlock > dl { margin-bottom: 50px; }
.questionAnswerBlock > dl > dt {
  font-size: inherit;
  font-style: normal;
  font-weight: bold;
  margin-top: 60px;   /* was 6rem */
  color: var(--oo-text-gray);
  border-bottom: 1px solid var(--oo-rule-hairline);   /* 2015's .post-content dt hairline */
}
.questionAnswerBlock > dl > dt:first-child { margin-top: 0; }
.questionAnswerBlock > dl > dd {
  font-size: inherit;
  font-style: normal;
  margin-top: 0;
  color: var(--oo-text-gray);
  margin-bottom: 20px;   /* was 2rem */
  padding-left: 10px;    /* was 1rem */
  margin-left: 20px;     /* was 2rem */
}
.questionAnswerBlock > dl > dd:last-child { margin-bottom: 60px; }   /* was 6rem */
.questionAnswerBlock > dl > dt.question {}
.questionAnswerBlock > dl > dd.answer {}
.questionAnswerBlock > dl > dd.analysis {
  border-left: 3px solid rgba(107, 100, 118, 0.2);
  margin-left: 30px;   /* was 3rem */
}
.questionAnswerBlock > dl > dd.breakdown {}

div.LCPindented { margin-left: 1.6em; }
h3.LCP-series-titles {
  color: var(--oo-purple-dark);
  font-size: 1.6em;
  line-height: 1.3;
}

/* --------------------------------------------------------------------------
   ul.footlings — the List Category Posts template used by the three footer
   menus (list-category-posts/footlings.php).

   CORRECTED 2026-08-05 (rev 23). These five values were ported verbatim from
   the 2015 stylesheet, where they were written against `html { font-size:
   62.5% }` — a 10px root. So 1.4rem meant 14px there. Astra runs a normal 16px
   root, so the same declarations were rendering at 22.4px text on a 38.4px
   line, which is what made the footer menus look wrong. Restated in px, which
   is what the 2015 numbers always were.

   Kept in px rather than converted to 0.875rem on purpose: these are literal
   2015 parity values, and pinning them means they cannot silently rescale a
   second time if the root size ever moves again.

   Colour, layout and the heading bar live in Section 27, scoped to the footer.
   This block is only the intrinsic list metrics, so `ul.footlings` still looks
   right if it is ever used outside the footer.
   -------------------------------------------------------------------------- */

ul.footlings {
  font-size: 14px;
  margin-bottom: 20px;
  list-style-image: none;
  list-style-type: none;
}
ul.footlings li {
  list-style-type: none;
  font-size: 14px;
  padding-left: 0;
  line-height: 24px;
  margin-bottom: 16px;
}

/* =========================================================
   11) NOTICE / MESSAGE UI
========================================================= */
.notice {
  padding: 10px;
  font-size: inherit;
  border: 1px solid #cc3333;
  -moz-border-radius: 5px;
  -webkit-border-radius: 5px;
  margin-top: 10px;
  margin-bottom: 10px;
  text-align: left;
  background-color: #ffcccc;
  margin-right: 5%;
}
.notice-yellow { background-color: #f9fac7; border: 1px solid var(--oo-purple-mid); }
.notice-purple { background-color: rgba(183, 130, 204, 0.32); border: 1px solid var(--oo-purple-mid); }

.mtbox {
  padding: 10px;
  border: 1px solid #999;
  -moz-border-radius: 5px;
  -webkit-border-radius: 5px;
  text-align: left;
}
.mtbox.makaala { border: 2px solid red; }

.sig { font-family: Trattatello, fantasy; color: grey; font-size: 20px; }

/* =========================================================
   12) TOOLTIP / ICON / ACCESSIBILITY
========================================================= */
span.hainatip {
  display: inline;
  position: relative;
  border-bottom: 1px solid var(--oo-orange-mid);
}

/* left unchanged per request */
span.hainatip:active:after {
  background: #333;
  background: rgba(0, 0, 0, .8);
  border-radius: 5px;
  bottom: 26px;
  color: #fff;
  content: attr(data-haina);
  left: 20%;
  padding: 5px 15px;
  position: absolute;
  z-index: 98;
  width: 220px;
}
span.hainatip:active:before {
  border: solid;
  border-color: #333 transparent;
  border-width: 6px 6px 0 6px;
  bottom: 20px;
  content: "";
  left: 50%;
  position: absolute;
  z-index: 99;
}

.svg-icon {
  width: 1em;
  height: 1em;
  margin-bottom: -0.1em;
  fill: currentColor;
}
.visually-hidden {
  position: absolute;
  height: 1px;
  width: 1px;
  overflow: hidden;
  clip: rect(1px 1px 1px 1px);
  clip: rect(1px, 1px, 1px, 1px);
  white-space: nowrap;
}

/* =========================================================
   13) MEDIA / AUDIO / EMBEDS
========================================================= */
audio.fullwidth { width: 90%; margin-right: 5%; }

span.playaudio {}
span.playaudio:hover { text-decoration: underline; }
span.playvideo {}

table.audiofiles td { border-bottom: none; }

embed.reveal, object.reveal, iframe.reveal {
  border-style: solid;
  border-width: thin;
}

div.videoTrackListing { font-weight: normal; }
div.techhelp { font-size: 0.8em; }

ul.xoxo.blogroll { color: grey; }
div.sharedaddy h3.sd-title:before { border-top: none; }

/* =========================================================
   14) GAME / GENERAL INTERACTIVE
========================================================= */
.gameContainer {
  border: 1px solid #aaa;
  padding: 20px;
  margin: 20px;
  font-size: 1.5em;
  background-color: #eee;
}
table.centered { margin-left: auto; margin-right: auto; }
#buttontable {}

h3.setName {
  color: #aaa;
  text-decoration: underline;
  margin-bottom: 10px;
}
span.reveal {
  background-color: #f8f8f0;
  border: 1px solid black;
  border-radius: 8px;
  padding: 1vw;
}
span.reveal:hover {
  background-color: #f8f0f0;
  color: green;
}
#b_nextRandom { color: green; }

.flexi { display: flex; background-color: lightgrey; }

/* =========================================================
   15) SEARCHWP / RELATED CONTENT
========================================================= */
/* ported from OleloOnline_2015 base theme, 2026-07-31 */
mark, .search-term { background: #ff0; }

form#searchform {
  margin-top: 5px;
  border: 1px solid var(--oo-border-gray);
}
form#searchform input#s {
  height: 3em;
  background: #eee;
  margin: 0;
}

div.searchwp-related h4 {
  padding-top: 20px;
  text-align: center;
}
.searchwp-related > ul {
  list-style: none;
  padding: 0;
  display: flex;
  align-items: stretch;
  margin: 0 0 0 -1em;
}
.searchwp-related > ul > li {
  flex: 1;
  padding: 0 0 0 1em;
  display: flex;
  align-items: stretch;
  text-align: center;
}
.searchwp-related > ul > li > a {
  display: block;
  width: 100%;
  text-decoration: none;
  background-color: #f7f7f7;
  border: 1px solid var(--oo-border-gray);
  border-radius: 2px;
}
.searchwp-related > ul > li > a > span { display: block; padding: 1em; }
.searchwp-related > ul > li > a > img {
  display: block;
  max-width: 100%;
  height: auto;
}
.searchwp-related > ul > li > a:hover { border: 1px solid var(--oo-border-gray); }

p.topics-prev-next {
  text-align: center;
  border: 1px solid var(--oo-border-gray);
  border-radius: 2px;
  background-color: #f7f7f7;
  padding: 10px;
}
p.sorry-not-logged-in {
  border: 1px dotted purple;
  padding: 10px;
  font-style: italic;
  color: #ccc; /* unchanged per request */
}

/* =========================================================
   16) TRACK/HEADING + MISC
========================================================= */
span.tracknum {
  color: var(--oo-green-dark);
  font-variant-caps: all-small-caps;
  font-weight: bold;
}
h2.inoapoko { color: var(--oo-purple-mid); }

/* no ka ʻike ʻana i nā mea Watu, e nānā i ka Watu seetings>custom theme */
div.oo-pub-mod-dateblock { margin-top: 10px; }

a.pihilele {
  display: inline-block;
  width: 45%;
  height: 3em;
  line-height: 3em;
  text-align: center;
  color: #fff;
  text-decoration: none;
  border: none;
  font-size: 1.2em;
}

/* =========================================================
   17) PAYMENTS / STRIPE / BOOKINGS / FORMS
========================================================= */
div.joinnow { float: right; }

.joinbutton,
.eo-booking-button,
.eo-booking-form-paynow {
  padding: 10px;
  background-color: rgba(79, 186, 82, 0.40);
  border: 1px solid green;
  border-radius: 4px;
  margin: 10px;
}

/* Fixed dangerous global selector leakage */
.joinbutton a,
.joinbutton a:visited,
.joinbutton a:hover {
  text-decoration: none;
}

div#oo-security-and-payment-info p { margin-bottom: 10px; }

div#oo-security-and-payment-info ul#oo-stripe-cards-accepted { text-align: center; }
div#oo-security-and-payment-info ul#oo-stripe-cards-accepted li {
  float: left;
  display: contents;
}

.widget_listcategorypostswidget { text-align: left; }

button.oo-submit-button {
  padding: 1em;
  background-color: var(--oo-green-dark);
  color: white;
  font-weight: bolder;
}
button.wpforms-page-prev,
button.wpforms-page-next {
  padding: 0.8em;
  background-color: var(--oo-purple-mid);
  color: white;
  font-weight: bolder;
  border-radius: 1em;
}

.oovc-reg-submit {
  background-color: var(--oo-orange-mid);
  border: 1px solid var(--oo-border-gray);
  color: #fff;
  font-size: 1em;
  padding: 1em 2em;
  border-radius: 1em;
}
.oovc-reg-ul li {
  line-height: 40px;
  border: 1px solid green;
  margin-top: 5px;
}
div.wpforms-field-stripe-credit-card-number {
  border: 2px solid green;
  padding: 20px;
}
.wpforms-field-required { border-bottom: 3px solid green; }

.button.mp-hide-pw {
  padding: 0.5em;
  border: none;
}

/* =========================================================
   18) MEDIAELEMENT
=========================================================
   RETIRED 2026-08-03 (v0.2.1): the PMPro half of this section is gone.

   It was the 2015 theme's PMPro styling, carried forward before Sections 20
   and 23 existed. Every rule was verified dead before removal by deleting it
   from the live stylesheet in the browser and re-measuring:

     div.pmpro_login_wrap / _logged_in_welcome_wrap (mint box)
         -- matched nothing outside the sidebar; inside the sidebar it was
            already flattened by 20.3. Removal changed only a border COLOUR on
            an element whose border-width is 0. No visible effect.
     div.pmpro_login_wrap h3 / _logged_in_welcome_wrap h3
         -- the uppercase + 3px-tracking rule that leaked into the sidebar
            welcome heading and was neutralised in 20.2 (v0.1.9). Dead.
     div.pmpro_card (purple border + mint background)
         -- lost to PMPro's own inline #pmpro_colors block, which loads AFTER
            this stylesheet. Measured #e8e8e8 / #ffffff, never the 2015 values.
     h3.pmpro_card_title (margin/padding/weight 100)
     h3.pmpro_font-large (1.8rem, white)
         -- superseded by 20.2 in the sidebar and 23.2 on PMPro pages.
            Removal changed nothing in either place.

   ONE rule was NOT dead and has been moved, not deleted:
     div.pmpro #pmpro_login div.pmpro_card_content { padding: 0 }
   Removing it re-inflated the sidebar login card to 12px 36px 36px, undoing
   the link alignment fixed in v0.1.9. It is a sidebar concern, so it now
   lives in Section 20.3, scoped to #secondary — see the note there.

   The MediaElement audio-player rules below are unrelated and stay.
========================================================= */
div.mejs-audio div.mejs-mediaelement { background-color: white; }
div.mejs-audio div.mejs-controls {
  background-color: rgba(121, 49, 149, 0.68);
  border: 1px solid var(--oo-purple-mid);
  border-radius: 20px;
}
div.mejs-audio div.mejs-controls .mejs-time-rail .mejs-time-current {
  background: var(--oo-purple-mid);
}

/* Kadence form honeypot field — unrelated to both MediaElement and PMPro,
   kept here where it has always lived rather than moved for tidiness. */
div.kt-wpf-hunakele { display: none; }


/* =========================================================
   19) TEMPORARY TEST CSS FOR NEW SONG CLASS NOTES FUNCTIONALITY
   ---------------------------------------------------------
   REM VALUES CORRECTED 2026-08-07 (rev 32) - the fourth and final instance of
   the 62.5%-root trap, after ul.footlings (rev 23), .definitionListBlock
   (rev 25) and .questionAnswerBlock (rev 27). Section 19 was excluded from the
   rev 28 sweep under the standing "do not touch" agreement; Kaliko lifted that
   for the rem values specifically.

   Seventeen declarations were written against the 2015 stylesheet's 10px root
   and were rendering 60% oversized on Astra's 16px root. Measured on
   /20260620-0413/ (post 9530, "Ku'u Hawai'i") before the fix:

       .kuuhawaii body text     25.6px  ->  16px    (was 1.6rem)
       .song-section > h3       38.4px  ->  24px    (was 2.4rem)
       .lyric-line              28.8px  ->  18px    (was 1.8rem)
       .song-section padding    32px 0 16px 24px -> 20px 0 10px 15px
       .line-block margin       32px 0 48px      -> 20px 0 30px 0

   The whole article was reading a full step larger than any other page on the
   site - the song headings were bigger than the page H1.

   Restated in px, matching the other three corrections, so they cannot silently
   rescale again if the root size ever moves.

   HOW THESE LAND ON THE 2026 TYPE SCALE, checked rather than assumed:
     - 16px body matches the Customizer body size exactly.
     - 24px `.song-section > h3` matches the site's Global H3.
     - 18px `.lyric-line` sits one step above body and bold, so the lyric stays
       the most prominent thing inside a line block, which is its whole job.
   The two `em` values (`.analysis h4` at 1.1em, `.source-note` at .9em) were
   deliberately NOT touched: `em` is relative to the element's own font-size, so
   it never had this problem, and both now resolve correctly off the 16px base.

   STILL DEFERRED to the rebuild scheduled for a later session - listed here so
   they are not rediscovered from scratch:
     - Two hardcoded #0d8c00 on `.kuuhawaii h2,h3,h4` and `.analysis h4`. That
       is the pre-2026-08-03 green, so both have drifted from --oo-green-dark
       (#0d8800) and are the last two in the file. One token swap each.
     - `rgba(13,140,0,0.25)` on `.line-block` is the same stale green at 25%.
     - Nine further hardcoded values that already have Section 01 tokens:
       #793195, #4B0A65, #6B6476, #974E08, #636363, #E19043, #f7fcfa.
     - `#b02ac2` on `.terms` is a purple with no token and no obvious relative
       in the palette - decide whether it joins the palette or goes.
     - The block is written in a compact minified style unlike the rest of the
       file. Left alone; it is explicitly temporary.
========================================================= */

.kuuhawaii{max-width:960px;margin:0 auto;font-size:16px;}
.kuuhawaii h2,
.kuuhawaii h3,
.kuuhawaii h4{color:#0d8c00;}
.kuuhawaii h2.inoapoko{color:#793195;text-align:center;}
.kuuhawaii .subtitle{text-align:center;color:#6B6476;font-style:italic;margin-bottom:20px;}
.kuuhawaii .song-section{box-sizing:border-box;border-radius:20px;border-left:3px solid #793195;padding:20px 0 10px 15px;margin:40px 0 20px 0;}
.kuuhawaii .song-section>h3{color:#793195;font-weight:bold;font-size:24px;text-transform:uppercase;margin-top:0;}
.kuuhawaii .section-label{color:#E19043;font-weight:bold;}
.kuuhawaii .line-block{margin:20px 0 30px 0;padding:15px;border-left:3px solid rgba(13,140,0,0.25);background-color:#f7fcfa;border-radius:5px;}
.kuuhawaii .lyric-line{font-size:18px;font-weight:bold;color:#4B0A65;margin-bottom:6px;}
.kuuhawaii .translation{font-size:16px;color:#6B6476;font-style:italic;margin:5px 0 10px 0;}
.kuuhawaii .analysis{margin-top:10px;}
.kuuhawaii .analysis h4{font-size:1.1em;margin:8px 0 4px 0;color:#0d8c00;}
.kuuhawaii dl.word-notes{margin:0;}
.kuuhawaii dl.word-notes dt{font-style:normal;font-weight:bold;color:#974E08;margin-top:7px;}
.kuuhawaii dl.word-notes dd{font-size:16px;font-style:normal;margin:0 0 4px 15px;color:#6B6476;}
.kuuhawaii dl.word-notes dd span.gloss{font-style:italic;}
.kuuhawaii ul{margin-top:3px;}
.kuuhawaii .note{color:#6B6476;margin:4px 0;}
.kuuhawaii .terms{box-sizing:border-box;padding:10px;border:1px solid #b02ac2;border-radius:5px;background-color:#f7fcfa;margin:20px 0;}
.kuuhawaii .terms h3{color:#793195;margin-top:0;}
.kuuhawaii .terms dl{margin-bottom:0;}
.kuuhawaii .terms dt{font-weight:bold;color:#4B0A65;margin-top:6px;}
.kuuhawaii .terms dd{color:#6B6476;margin-left:15px;}
.kuuhawaii .source-note{font-size:.9em;color:#636363;text-align:center;margin-top:20px;}




/* ==========================================================================
   OleloOnline_2026 — SECTIONS 20 & 21
   --------------------------------------------------------------------------
   Target:      style.css v0.1.4
   How to use:  REPLACE the Section 20 block you appended for v0.1.3 with this
                whole file, then bump the `Version:` header to 0.1.4.
                (Section 20 changed; Section 21 is new.)
   Depends on:  --oo-purple-dark (#4B0A65), --oo-purple-mid (#793195),
                --oo-orange-dark (#974E08) from Section 01 (:root).
   No !important is used anywhere, per the v0.1.1 reset.

   CHANGES IN 0.1.4
   - 20.2  Widget title bar background: purple-dark → purple-mid.
   - 20.1  Widget border stays purple-dark. Border and bar are now deliberately
           two different purples; both are now named tokens (20.1) so you can
           re-match them with a one-line edit if the two-tone look wears thin.
   - 21    NEW. Site-wide text links: purple-dark, underlined in every state,
           shifting to purple-mid on hover/focus/active.
   ========================================================================== */


/* ==========================================================================
   SECTION 20 — SIDEBAR WIDGETS
   Scope: the right sidebar only (#secondary), which serves Pages and Posts.
   ========================================================================== */

/* --------------------------------------------------------------------------
   20.1  Widget shell — purple outline, rounded corners, 1rem padding
   --------------------------------------------------------------------------
   Astra's dynamic CSS sets the sidebar widget box with:

       .ast-separate-container.ast-two-container #secondary .widget
       { background-color: var(--ast-global-color-4); padding: 2em; margin-bottom: 2em; }

   That selector is (1 id, 3 classes). To beat it WITHOUT !important we need at
   least equal specificity — the child stylesheet already loads after Astra's
   dynamic CSS, so a tie is enough. `.widget.widget` repeats the class purely to
   reach (1 id, 3 classes). It looks odd, but it is valid CSS, and it avoids
   hard-coding Astra's `.ast-separate-container.ast-two-container` layout
   classes, which would silently stop matching if you change the container
   layout in the Customizer.

   Colours and geometry live in custom properties so 20.2 stays in sync — edit
   them here only.

   NOTE ON `rem` vs `em`: the padding is `1rem`, which is the same 16px you
   asked for as 1em. It has to be `rem`: the title bar in 20.2 cancels this
   padding with a negative margin, and `em` on the title would resolve against
   the TITLE's 20px font-size rather than the widget's 16px, leaving the bar
   overhanging the border by 4px per side.
   -------------------------------------------------------------------------- */

#secondary.widget-area .widget.widget {
	--oo-widget-border-color: var(--oo-purple-dark);   /* 0.1.4: unchanged */
	--oo-widget-title-bg:     var(--oo-purple-mid);    /* 0.1.4: was purple-dark */
	--oo-widget-pad:          1rem;
	--oo-widget-border-width: 2px;
	--oo-widget-radius:       10px;

	padding: var(--oo-widget-pad);
	border: var(--oo-widget-border-width) solid var(--oo-widget-border-color);
	border-radius: var(--oo-widget-radius);
	/* background-color and margin-bottom are left to Astra (white, 2em). */
}

/* --------------------------------------------------------------------------
   20.2  Widget title — full-width purple bar across the top
   --------------------------------------------------------------------------
   The negative margin exactly cancels the widget's padding, so the bar runs
   edge to edge against the inside of the border. The inner radius is
   (outer radius − border width), so the bar's top corners sit flush inside the
   frame instead of showing a white sliver in each corner.

   Contrast check: white on #793195 is 7.8:1 — AAA at this size and weight
   (20px / 600). White on the old #4B0A65 was 13.7:1. Both are comfortably safe;
   the change is purely aesthetic.

   `.pmpro_card_title` is included so the Paid Memberships Pro login widget gets
   the identical bar — see 20.3 for why it needs its own selector.
   -------------------------------------------------------------------------- */

#secondary.widget-area .widget .widget-title,
#secondary.widget-area .widget .pmpro_card_title {
	margin: calc(-1 * var(--oo-widget-pad)) calc(-1 * var(--oo-widget-pad)) 1rem;
	padding: 0.5rem 0.75rem;
	background-color: var(--oo-widget-title-bg);
	border-radius: calc(var(--oo-widget-radius) - var(--oo-widget-border-width))
	               calc(var(--oo-widget-radius) - var(--oo-widget-border-width))
	               0 0;
	color: #fff;

	/* 0.1.8: family pinned here so the sidebar is fully decoupled from
	   Customizer > Global > Typography > H2.

	   Widget titles are marked up as <h2>, so before this line they inherited
	   the global H2 family. Size and weight were already pinned in this rule,
	   which is why the sidebar has been rendering at 20px/600 rather than the
	   H2 setting's size and weight -- only the family was leaking through.

	   Inter Tight is deliberate, not incidental: it is narrower than Inter, so
	   long widget headings ("VIRTUAL CLASSROOM") fit on one line in a 290px
	   column, and the different texture marks the sidebar as a navigation
	   surface rather than reading matter. Content H2s can now be set to
	   Inter 800 in the Customizer without touching the sidebar.

	   Both Inter and Inter Tight carry U+02BB, so Hawaiian widget titles are
	   safe in either. */
	font-family: "Inter Tight", "Inter", -apple-system, sans-serif;
	font-size: 1.25rem;
	font-weight: 600;
	line-height: 1.4;
	text-align: center;
	overflow-wrap: break-word;

	/* 0.1.9: these two are neutralised, not merely omitted.

	   The logged-in PMPro welcome heading is `h3.pmpro_card_title
	   .pmpro_member_display_name` inside `div.pmpro_logged_in_welcome_wrap`.
	   Section 18's legacy 2015 rule --

	       div.pmpro_login_wrap h3,
	       div.pmpro_logged_in_welcome_wrap h3 { text-transform: uppercase;
	                                             letter-spacing: 3px; ... }

	   -- is less specific than this rule, so it loses on colour, size, weight
	   and family. But it still supplied `text-transform` and `letter-spacing`,
	   because this rule did not declare them and there was nothing to override.
	   The result: "WELCOME,  TEST  MONTHLY  USER" in wide-tracked caps while
	   every neighbouring widget title sat in sentence case.

	   Declaring them here makes this rule the complete definition of a widget
	   title rather than a partial one, so no other rule can leak individual
	   properties into the sidebar. */
	text-transform: none;
	letter-spacing: normal;
}

/* Any link inside a widget title must stay white so it does not pick up the
   purple link colour from Section 21 and vanish into the bar. At (1 id, 2
   classes) this comfortably outranks Section 21's (0, 1, 1). */
#secondary.widget-area .widget .widget-title a,
#secondary.widget-area .widget .widget-title a:hover,
#secondary.widget-area .widget .widget-title a:focus,
#secondary.widget-area .widget .widget-title a:visited,
#secondary.widget-area .widget .pmpro_card_title a,
#secondary.widget-area .widget .pmpro_card_title a:hover,
#secondary.widget-area .widget .pmpro_card_title a:focus,
#secondary.widget-area .widget .pmpro_card_title a:visited {
	color: #fff;
	text-decoration: underline;
	text-decoration-color: currentColor;
}

/* 0.1.9: the PMPro welcome heading is "Welcome, <a>Member Name</a>" — only the
   name is a link. Underlining it split the bar into an underlined half and a
   plain half, which read as a styling fault rather than as an affordance.
   Kaliko's call: drop the resting underline, restore it on hover/focus so the
   link is still discoverable and keyboard users still get a cue.

   Placed after the rule above so it wins on order at equal specificity; the
   :hover/:focus pair is one class heavier and wins over this in turn. */
#secondary.widget-area .widget .pmpro_card_title a,
#secondary.widget-area .widget .pmpro_card_title a:visited {
	text-decoration-line: none;
}

#secondary.widget-area .widget .pmpro_card_title a:hover,
#secondary.widget-area .widget .pmpro_card_title a:focus {
	text-decoration-line: underline;
}

/* --------------------------------------------------------------------------
   20.3  Paid Memberships Pro login widget
   --------------------------------------------------------------------------
   This widget does not use Astra's `.widget-title` markup. PMPro emits its own
   card:

       aside.widget_pmpro_member_login
         div.pmpro > section.pmpro_section > div.pmpro_card.pmpro_login_wrap
           h3.pmpro_card_title.pmpro_font-large
           div.pmpro_card_content
           div.pmpro_card_actions

   We flatten PMPro's inner card chrome — it was drawing a second, grey,
   8px-rounded box inside our frame — and let the h3 become the bar.

   BUG FIX INCLUDED: that h3 was rendering purple text on a purple background
   (#793195 on #793195) — the words "Log In" were invisible. 20.2 sets it white.

   `overflow: visible` is load-bearing, not cosmetic: PMPro sets
   `.pmpro_card { display: flex; overflow: hidden; }`, which clips the title
   bar's negative margins and leaves the bar inset with its text sheared off at
   the top. Do not drop that line.

   MAINTENANCE RISK: these are PMPro's own class names. If a future PMPro
   release renames `.pmpro_card` / `.pmpro_card_title`, this block quietly stops
   applying and the login widget reverts to plugin styling. Worth a look after
   any major PMPro update.
   -------------------------------------------------------------------------- */

#secondary.widget-area .widget .pmpro_card {
	margin: 0;
	padding: 0;
	border: 0;
	border-radius: 0;
	background-color: transparent;
	overflow: visible;

	/* 0.2.2: PMPro puts a drop shadow on its cards
	   (rgba(0,0,0,0.07) 2px 2px 7px). The offset is down-and-right only, so
	   inside our frame it read as a grey smudge along the bottom and right
	   edges of the login widget and nowhere else in the sidebar. The card
	   background was already transparent — the shadow was the whole artifact. */
	box-shadow: none;
}

/* PMPro ships a large bottom margin on its sections; inside a widget that is
   just a tall empty gap under the Log In button. */
#secondary.widget-area .widget .pmpro_section {
	margin-bottom: 0;
}

/* 0.1.9: the card's action row — "Log Out" when logged in, "Lost Password?"
   when logged out.

   PMPro styles it as a card footer: `background: rgba(0,0,0,0.04)`, a 1px
   #e8e8e8 top rule, and `padding: 12px 36px`. Inside our frame that read as a
   stray grey inset strip, and the 36px inline padding pushed "Log Out" 36px to
   the right of "Your Profile" and "Membership Account" directly above it
   (measured: x=856 against x=820) — it looked like a mistake rather than a
   footer.

   Flattened to match the content links. The block padding is kept so the row
   still has breathing room; only the inline indent, the fill and the rule go.
   Previously listed as a deferred cosmetic issue — much more visible in the
   logged-in state, so cleared now. */
#secondary.widget-area .widget .pmpro_card_actions {
	padding-inline: 0;
	padding-block: 0.5rem 0;
	border-top: 0;
	background-color: transparent;
}

/* 0.2.1: moved here from the retired PMPro half of Section 18, where it was
   written as the unscoped `div.pmpro #pmpro_login div.pmpro_card_content`.

   It is load-bearing, not decoration. PMPro pads the login card's content
   area with 12px 36px 36px; inside a 290px sidebar that indents "Your
   Profile" / "Membership Account" / "Log Out" away from the widget edge and
   undoes the alignment fixed in v0.1.9. Verified by deleting the old rule
   from the live stylesheet and watching the padding return.

   Now scoped to the sidebar, which is the only place the constraint applies.
   A PMPro login form placed in page content keeps the plugin's own padding,
   which is correct at content width. */
#secondary.widget-area .widget .pmpro_card_content {
	padding: 0;
}


/* --------------------------------------------------------------------------
   20.5  Member widget — green identity + action rows          [added 0.2.3]
   --------------------------------------------------------------------------
   The login/member widget is the only *control* surface in a sidebar of
   informational ones. Once the PMPro drop shadow came off in 0.2.2 it matched
   its neighbours so exactly that it stopped announcing itself, and the bold
   link text that used to do that job disappeared with the Section 18 retirement.

   Two changes, chosen together from mockups (options "C" and "D"):

     - Green frame and title bar instead of purple, tying the widget to the
       colour already used for buttons and actions elsewhere on the site.
     - The links become full-width rows: semibold, a green marker, hairline
       dividers, and a mint hover fill.

   WHY `:has()` RATHER THAN A WIDGET CLASS
   PMPro's markup has moved twice during this build — the widget arrived as a
   classic `widget_pmpro_member_login` and is now a block widget
   (`widget_block` / `wp-block-pmpro-login-form`), and the heading has been
   both h3 and h2. Targeting "the widget that contains PMPro markup" survives
   all of that; targeting a specific widget class would have broken twice
   already. `:has()` is standalone here, not nested inside `:not()`, so the
   Section 21 hazard note does not apply.

   ACCESSIBILITY
   The marker is decorative CSS `content`, not markup, so it does not alter
   the link text. Purple links on the mint hover fill stay above 13:1. The
   rows are ~40px tall, which also gives a comfortable mobile tap target.
   -------------------------------------------------------------------------- */

/* Re-point the two Section 20.1 custom properties for this widget only. The
   title bar and the frame both read from these, so recolouring the widget is
   two declarations rather than a pile of overrides. */
#secondary.widget-area .widget.widget:has(.pmpro) {
	--oo-widget-border-color: var(--oo-green-dark);
	--oo-widget-title-bg:     var(--oo-green-dark);
}

/* Links become rows. Section 21 sets a global underline via a zero-specificity
   :where() list at (0,1,1); these selectors are (1,3,0) and win comfortably,
   so the underline is traded for the row treatment and returns on hover. */
#secondary.widget-area .widget .pmpro_card_content a,
#secondary.widget-area .widget .pmpro_card_actions a {
	display: block;
	position: relative;
	padding: 0.45rem 0 0.45rem 1.15rem;
	font-weight: 600;
	text-decoration-line: none;
}

#secondary.widget-area .widget .pmpro_card_content a::before,
#secondary.widget-area .widget .pmpro_card_actions a::before {
	content: "\25B8";                 /* ▸ */
	position: absolute;
	left: 0;
	color: var(--oo-green-dark);
	font-weight: 700;
}

/* Dividers between the navigation links only. The actions row (Log Out, and
   Lost Password? when logged out) is already separated by 20.3's top padding,
   so a rule under the last item would just float unattached. */
#secondary.widget-area .widget .pmpro_card_content a {
	border-bottom: 1px solid var(--oo-border-gray);
}

#secondary.widget-area .widget .pmpro_card_content a:hover,
#secondary.widget-area .widget .pmpro_card_content a:focus,
#secondary.widget-area .widget .pmpro_card_actions a:hover,
#secondary.widget-area .widget .pmpro_card_actions a:focus {
	background-color: var(--oo-bg-mint);
	text-decoration-line: underline;
}

/* --------------------------------------------------------------------------
   20.6  Login form field labels — weight               [added rev 36, 0.6.6]
   --------------------------------------------------------------------------
   The two labels above the inputs in the logged-out widget — "Username or
   Email Address" and "Password" — were reading as ordinary body copy and did
   not announce themselves as field names. Raised to 800 so the form scans as
   a labelled pair rather than two loose boxes. "Remember Me" stays at PMPro's
   weight; it is a checkbox caption, not a field label.

   WHY THE SELECTOR IS SHAPED LIKE THIS
   PMPro ships the 500 in variation_1.css, written with CSS nesting inside
   `.pmpro`, which flattens to:

       .pmpro_section #loginform label:not(.pmpro_section #loginform .login-remember label)

   That computes to (2,4,2) — `:not()` takes the specificity of its most
   specific argument, so the exclusion for "Remember Me" is also what makes
   the rule hard to beat. Three narrower selectors were injected into the live
   stylesheet and measured before this one was written; none of them moved a
   pixel:

       #secondary.widget-area .widget .login-username label      (1,3,0)  lost
       body #secondary .login-username label                     (1,2,2)  lost
       (inline style, no !important)                                      won

   Taking PMPro's selector verbatim and prefixing `#secondary` lands at
   (3,4,2), which wins on ID count alone. No `!important`, and no reliance on
   load order — though the order is in our favour anyway: PMPro's
   variation_1.css is sheet 10 and this stylesheet is sheet 11.

   Mirroring their selector rather than listing `.login-username` /
   `.login-password` is deliberate. It keeps the two rules coupled: if a
   future PMPro release renames `.pmpro_section` or stops using `#loginform`,
   this rule stops applying in the same breath theirs does, and the labels
   fall back to inheriting body weight — rather than ours half-applying over a
   changed layout. The same applies to browsers too old for a complex
   `:not()` argument: both rules drop out together, and the labels render at
   the inherited 400 they effectively render at today.

   FONT NOTE — 800 IS A REAL FACE HERE
   Inter is served on this site as three static weights only: 400, 600 and
   800. Anything asking for 500 renders as 400 (measured: the label's text
   width is identical at 400 and at 500), and 700 would render as 800. So the
   old 500 was never actually medium, and the new 800 is true Inter ExtraBold
   rather than a synthesised bold. If Inter's loaded weights are ever changed
   in the Customizer, re-check this.

   SCOPE
   Sidebar widget only, per request. The standalone PMPro login page keeps the
   plugin's 500. To cover both, delete the `#secondary ` prefix: the selector
   then ties PMPro's specificity exactly and wins on load order instead.
   -------------------------------------------------------------------------- */

#secondary .pmpro_section #loginform label:not(.pmpro_section #loginform .login-remember label) {
	font-weight: 800;
}

/* --------------------------------------------------------------------------
   20.4  .oo-widget-link-list — reserved hook, intentionally inert
   --------------------------------------------------------------------------
   Replaces the old hard-coded `resourceAdditional` class on the Custom HTML
   widgets ("Virtual Classroom" and "Online Learning"). Confirmed markup:

       div.oo-widget-link-list > ul > li > a

   Nothing applied yet, on purpose. Uncomment when you want it.
   -------------------------------------------------------------------------- */

/*
#secondary.widget-area .oo-widget-link-list ul {
	margin: 0;
	padding: 0;
	list-style: none;
}

#secondary.widget-area .oo-widget-link-list li {
	margin-bottom: 0.4em;
}

#secondary.widget-area .oo-widget-link-list a {
	display: block;
}
*/

/* --------------------------------------------------------------------------
   20.5  Scope note
   --------------------------------------------------------------------------
   Everything above is scoped to #secondary, the sidebar Astra renders on both
   Pages and Posts — one block covers both.

   For the footer widget areas later, extract 20.1/20.2 into a shared selector
   list rather than loosening the scope to a bare `.widget`, which would also
   hit Astra's header and off-canvas widget slots.
   -------------------------------------------------------------------------- */

/* --------------------------------------------------------------------------
   20.7  Widget subtitle — the call-to-action line under a widget title
   --------------------------------------------------------------------------
   Added 2026-08-06 (rev 28), at your request. The two custom-HTML widgets in
   the sidebar open with a one-line pitch immediately under the title bar:

       VIRTUAL CLASSROOM   ->  "Eight-week sessions taught via Zoom"
       ONLINE LEARNING     ->  "Online Hawaiian language lessons"

   These are effectively ad copy shown on every page, and they were rendering
   as ordinary body text (#222, weight 400), indistinguishable from the link
   list underneath.

   SELECTOR SCOPE. Checked all seven sidebar widgets on a lesson page: only the
   two `widget_custom_html` ones have a `.textwidget` wrapper, and in both the
   subtitle is its FIRST element child. The other five open with a form, a
   `<ul class="xoxo">`, or PMPro's card content, so `.textwidget > p:first-child`
   reaches exactly the two intended paragraphs and nothing else. It also stays
   correct if you add a third text widget with the same shape — which is the
   point of matching on structure rather than on widget id.

   `:first-child` rather than `:first-of-type` on purpose: if a future widget
   opens with an image or a heading, the paragraph after it is body copy, not a
   subtitle, and should not be promoted.

   COLOUR: `--oo-purple-dark`, the theme's standard deep purple. Corrected
   2026-08-06 (rev 30) from a literal #ab0a65, which was given in error — the
   near-miss on #4B0A65 was a typo, as suspected when it went in. Now a token,
   so it follows the palette.

   Contrast: 13.7:1 on the widget's white body background — WCAG AAA with room
   to spare.

   SPACING, rev 38 (2026-08-09). The original note here read "the line-height and
   bottom margin are left to inherit ... pinning spacing here would fight the
   --oo-widget-* rhythm set in 20.1." That was the wrong call and is now reversed.
   Inheriting did not produce the 20.1 rhythm; it produced Astra's stock paragraph
   margins, which left the subtitle floating a full 16px below the purple bar and
   a further ~24px above the link list. In a 290px column that reads as three
   disconnected fragments rather than one widget.

   WHY A NEGATIVE TOP MARGIN INSTEAD OF SHRINKING THE TITLE BAR'S MARGIN.
   The `margin-bottom: 1rem` above the subtitle belongs to the shared
   `.widget-title, .pmpro_card_title` rule in 20.2, which dresses ALL SEVEN
   sidebar widgets — search, the three link lists and the PMPro login card
   included. Editing it there would move every widget in order to fix two. The
   subtitle opts out locally instead: 1rem down from the bar, 0.5rem clawed back,
   leaving 8px. The site-wide rhythm is untouched.

   BOTH SIDES OF BOTH GAPS ARE DECLARED. Per the "a partial rule invites leaks"
   rule, this block sets its own top and bottom margin, and the companion rule
   below zeroes the top margin of the link list that follows. Setting only one
   side would leave the result at the mercy of whatever Astra ships for `p` and
   `ul`, which is exactly how the gaps got here.

   TO TUNE: the two margin values below are the only numbers that matter. They
   are symmetric at 8px on purpose — a starting point, not a measured optimum.
   Raise the bottom one if the pitch line crowds the links.
   -------------------------------------------------------------------------- */

#secondary.widget-area .widget .textwidget > p:first-child {
	color: var(--oo-purple-dark);
	font-weight: 600;

	/* 1rem bar margin - 0.5rem = 8px under the purple bar */
	margin-top: -0.5rem;
	/* 8px down to the link list; the rule below removes the list's own top margin */
	margin-bottom: 0.5rem;
}

/* The other half of the second gap. Astra gives `ul` a top margin of its own, so
   tightening the paragraph alone would have closed roughly half the distance and
   looked like the change had not worked. Scoped to a link list that directly
   follows a subtitle, so an ordinary list elsewhere in a text widget keeps normal
   spacing. (1 id, 5 classes) — comfortably above Astra's element defaults, and no
   !important, per the v0.1.1 reset. */
#secondary.widget-area .widget .textwidget > p:first-child + .oo-widget-link-list,
#secondary.widget-area .widget .textwidget > p:first-child + .oo-widget-link-list > ul {
	margin-top: 0;
}

/* --------------------------------------------------------------------------
   NUMBERING NOTE (rev 38, 2026-08-09)
   --------------------------------------------------------------------------
   The 20.x headers in this file are not unique and are not in order. Present
   state, in file order:

       20.1  widget shell
       20.2  widget title bar
       20.3  PMPro login widget
       20.5  member widget, green identity rows        [added 0.2.3]
       20.6  login form field labels                   [added rev 36]
       20.4  .oo-widget-link-list, inert
       20.5  scope note                                <-- duplicate of the above
       20.7  widget subtitle                           [this rev; was a 2nd "20.4"]

   Renumbering the older ones was considered and rejected: `claude/widget-styling-
   v0.1.3.md`, `claude/pmp-logged-in-welcome-fix.md` and `claude/go-live-plan.md`
   all cite 20.3 and 20.5 by number, and moving them would break those references
   to tidy comments that affect nothing. New sub-sections should take the next
   free number — 20.8 — rather than slotting into the apparent gap at 20.4.
   -------------------------------------------------------------------------- */

/* ====================== END SECTION 20 ==================================== */


/* ==========================================================================
   SECTION 21 — SITE-WIDE TEXT LINKS  (new in 0.1.4)
   ========================================================================== */

/* --------------------------------------------------------------------------
   21.1  Link tokens
   --------------------------------------------------------------------------
   Kept separate from the colour tokens in Section 01 so you can experiment
   without touching the palette. You said you were toying with purple-mid or
   orange-dark for the underline — swap the values here and nothing else in the
   file needs to change. Ready-made alternatives are commented on each line.

   When you settle on a combination, consider moving these four lines up into
   the :root block in Section 01 and deleting this one, so the theme has a
   single :root.

   Contrast on white:  #4B0A65 = 13.7:1   #793195 = 7.8:1   #974E08 = 7.4:1
   All three clear WCAG AAA for body text (7:1), so this choice is aesthetic,
   not an accessibility trade-off.
   -------------------------------------------------------------------------- */

:root {
	--oo-link-color:            var(--oo-purple-dark);  /* try: --oo-purple-mid */
	--oo-link-color-hover:      var(--oo-purple-mid);   /* try: --oo-orange-dark */
	--oo-link-underline:        var(--oo-purple-dark);  /* try: --oo-purple-mid, --oo-orange-dark */
	--oo-link-underline-hover:  var(--oo-purple-mid);   /* try: --oo-orange-dark */
}

/* --------------------------------------------------------------------------
   21.2  What is deliberately NOT a "text link"
   --------------------------------------------------------------------------
   You asked for every <a> on the site. Taken literally that also underlines the
   header nav (76 links on the post I checked), the "ʻŌlelo Online" site title,
   the back-to-top arrow, image links, and any <a> a plugin styles as a button —
   which reads as a broken stylesheet rather than a design choice. So the rules
   below apply to every <a> EXCEPT the site chrome, button-shaped links, and
   post titles / meta links enumerated here.

   POST TITLES AND META — HEADS UP: you asked to leave these as they are. Two of
   the five selectors on that line are not what the description implied, so check
   this on staging before the cutover. Measured on the CH1B post:

       .entry-title a            #1e293b  dark slate   ← as described
       .ast-related-post-title a #1e293b  dark slate   ← as described
       .post-navigation a        #334155  dark slate   ← as described
       .entry-meta a             #046bd2  ASTRA BLUE   ← not dark slate
       .ast-taxonomy-container a #046bd2  ASTRA BLUE   ← not dark slate

   So the byline ("By ʻŌlelo Online") and the category/series links under each
   post are the only blue links left on the site now that body links are purple.
   That may read as an oversight rather than a decision. If you want them folded
   into the purple family but still underline-free, delete the `.entry-meta,`
   and `.ast-taxonomy-container,` entries from the four exclusion lists below and
   add this one rule instead:

       .entry-meta a, .entry-meta a:hover, .entry-meta a:focus,
       .ast-taxonomy-container a, .ast-taxonomy-container a:hover,
       .ast-taxonomy-container a:focus {
           color: var(--oo-link-color);
           text-decoration-line: none;
       }

   The exclusion list is wrapped in :where(), which contributes zero
   specificity. That is deliberate: it keeps the selectors at a predictable
   (0,1,1) so they tie with Astra's `a:hover` / `a:focus` / `a:visited` rules and
   win on load order alone, with no !important and no specificity arms race.

   TRAP, LEARNED THE HARD WAY: only ever put CONTAINER classes in the ancestor
   part of this list. My first draft included `.ast-hfb-header`, which sounds
   like a header wrapper but is actually a class Astra puts on <body> when the
   Header Footer Builder is active. `.ast-hfb-header a` therefore matched every
   link on the site and silently excluded all of them — the rules parsed fine
   and simply did nothing. Before adding anything here, confirm it is not a body
   class (`document.body.matches('.the-class')` in the console).

   For the same reason the FluentCart entries below match the <a> itself
   (`a[class*="fluent-cart"]`) rather than an ancestor — a wildcard ancestor
   match is the same trap waiting to happen.

   MAINTENANCE: FluentCommunity, FluentCart, FluentSupport and FluentForms are
   still to come. Each may introduce its own button classes built on <a>. When
   one shows up underlined, add its class to the button line below — that is the
   expected upkeep for the global approach, and the reason the alternative
   (scoping to .entry-content only) was on the table.
   -------------------------------------------------------------------------- */

/* Underline, in every state. (0,0,1) — ties Astra's bare `a`, wins on order. */
a:where(:not(
	:is(.site-header, .main-navigation, .main-header-menu,
	    .ast-mobile-popup-drawer, .ast-mobile-header-wrap,
	    .site-branding, .site-title, .ast-builder-menu) a,
	:is(.entry-title, .ast-related-post-title, .entry-meta,
	    .ast-taxonomy-container, .post-navigation) a,
	.ast-scroll-top,
	.skip-link,
	.ast-button, .ast-custom-button, .ast-outline-button,
	.button, .wp-block-button__link, .wp-element-button,
	.pmpro_btn, .pmpro_btn-submit,
	a[class*="fluent-cart"], a[class*="fluentcart"], a[class*="fc-btn"]
)) {
	text-decoration-line: underline;
	text-decoration-thickness: 1px;
	text-underline-offset: 0.15em;
}

/* Resting colour. (0,1,1) — needed because Astra sets `a:visited` at (0,1,1);
   a bare `a` rule here would lose to it on visited links.
   `:visited` may only set colour properties, which is all we set. */
a:where(:not(
	:is(.site-header, .main-navigation, .main-header-menu,
	    .ast-mobile-popup-drawer, .ast-mobile-header-wrap,
	    .site-branding, .site-title, .ast-builder-menu) a,
	:is(.entry-title, .ast-related-post-title, .entry-meta,
	    .ast-taxonomy-container, .post-navigation) a,
	.ast-scroll-top,
	.skip-link,
	.ast-button, .ast-custom-button, .ast-outline-button,
	.button, .wp-block-button__link, .wp-element-button,
	.pmpro_btn, .pmpro_btn-submit,
	a[class*="fluent-cart"], a[class*="fluentcart"], a[class*="fc-btn"]
)):link,
a:where(:not(
	:is(.site-header, .main-navigation, .main-header-menu,
	    .ast-mobile-popup-drawer, .ast-mobile-header-wrap,
	    .site-branding, .site-title, .ast-builder-menu) a,
	:is(.entry-title, .ast-related-post-title, .entry-meta,
	    .ast-taxonomy-container, .post-navigation) a,
	.ast-scroll-top,
	.skip-link,
	.ast-button, .ast-custom-button, .ast-outline-button,
	.button, .wp-block-button__link, .wp-element-button,
	.pmpro_btn, .pmpro_btn-submit,
	a[class*="fluent-cart"], a[class*="fluentcart"], a[class*="fc-btn"]
)):visited {
	color: var(--oo-link-color);
	text-decoration-color: var(--oo-link-underline);
}

/* Hover / focus / active. (0,1,1) — ties Astra's `a:hover, a:focus` and wins on
   order. text-decoration-line is repeated here because Astra's `a:focus` rule
   sets `text-decoration: none` at this same specificity.

   :focus is included alongside :hover so keyboard users get the same feedback
   as mouse users — worth keeping even if you later change the hover colour. */
a:where(:not(
	:is(.site-header, .main-navigation, .main-header-menu,
	    .ast-mobile-popup-drawer, .ast-mobile-header-wrap,
	    .site-branding, .site-title, .ast-builder-menu) a,
	:is(.entry-title, .ast-related-post-title, .entry-meta,
	    .ast-taxonomy-container, .post-navigation) a,
	.ast-scroll-top,
	.skip-link,
	.ast-button, .ast-custom-button, .ast-outline-button,
	.button, .wp-block-button__link, .wp-element-button,
	.pmpro_btn, .pmpro_btn-submit,
	a[class*="fluent-cart"], a[class*="fluentcart"], a[class*="fc-btn"]
)):is(:hover, :focus, :active) {
	color: var(--oo-link-color-hover);
	text-decoration-line: underline;
	text-decoration-color: var(--oo-link-underline-hover);
}

/* --------------------------------------------------------------------------
   21.3  Links that wrap an image
   --------------------------------------------------------------------------
   An underline drawn under a picture looks like a rendering fault. This is a
   separate rule rather than another entry in the :not() list above on purpose:
   :not() is not a forgiving selector list, so an unsupported :has() inside it
   would invalidate the whole rule and silently drop all link styling. On its
   own, it simply does nothing on a browser without :has() support.
   -------------------------------------------------------------------------- */

a:has(> img),
a:has(> svg),
a:has(> picture),
a:has(> figure) {
	text-decoration-line: none;
}

/* ====================== END SECTION 21 ==================================== */


/* ==========================================================================
   22. 2015 PARITY — HEADER WORDMARK, SUPERSCRIPTS, CONTENT TABLES
   ==========================================================================
   Added 2026-08-03. Derived from a live computed-style diff of
     staging  https://olelo-online.local/calendar/  (Astra + OleloOnline_2026)
     live     https://oleloonline.com/calendar/     (OleloOnline_2015)

   SCOPE NOTE — read before adding to this section.
   Kaliko's decision (2026-08-03) is that global typography, colors, and
   container width are set in the Astra Customizer, not here. This section
   therefore contains ONLY the things the Customizer cannot express. If you
   find yourself about to add a font-size or a font-family here, stop: it
   almost certainly belongs in Customizer > Global > Typography instead.
   Astra emits per-post dynamic CSS whose selectors are more specific than
   plain element selectors, so competing with it from this file means writing
   deliberately over-specific selectors that break on Astra updates.

   The matching Customizer settings are recorded in the project document
   `claude/calendar-page-parity-v0.1.0.md`.
   ========================================================================== */


/* --------------------------------------------------------------------------
   22.1  Site header wordmark
   --------------------------------------------------------------------------
   The 2015 wordmark is "ʻŌlelo|online" with an orange pipe separator and a
   lowercase second word. WordPress stores the site title as plain text, so
   the pipe is wrapped in a span by the `astra_site_title` filter in
   functions.php (section 1) rather than by editing Settings > General --
   that keeps the real site title intact for feeds, email, and SEO.

   ONE SOURCE OF TRUTH, PLEASE. The wordmark is treated here as an owned
   branding lockup, not as "the site title in a font." Its size, weight and
   tracking are set below rather than in Customizer > Header Builder > Site
   Title > Typography, because the lockup needs tracking and a coloured
   separator that the Customizer cannot express, and splitting the treatment
   across two places guarantees they drift apart. Consequence: LEAVE the Site
   Title typography controls at their defaults. If the wordmark ever looks
   wrong, the fix is in this block, not in the Customizer.

   Colour is the exception -- the wordmark inherits its colour from the Site
   Title colour control, so the green-band/white-text pairing stays a
   Customizer decision alongside the header background.
   -------------------------------------------------------------------------- */

/* The green band itself.

   [CUSTOMIZER PREFERRED -- DELETE THIS BLOCK IF YOU MOVE IT]
   Header Builder > Primary Header > Background is the proper home for this.
   It lives here only because it had to be set from outside wp-admin, and
   because leaving the band white made the white wordmark invisible. If you
   set the background in the Customizer, delete this rule rather than having
   the colour declared in two places.

   Caveat while it lives here: Astra Pro's sticky/transparent header variants
   have their own background selectors and are NOT covered by this block. The
   Customizer setting would cover them. */
.ast-primary-header-bar,
.ast-primary-header-bar .site-primary-header-wrap,
#ast-desktop-header .ast-main-header-wrap,
#ast-mobile-header .ast-main-header-wrap {
	background-color: var(--oo-green-dark);
}

.oo-wordmark {
	/* 2015 set Teko 600 at 35px. Inter is a wider face, so it needs more
	   size and weight to carry the same presence, and it is already being
	   loaded for body text -- no third webfont. Scales down on narrow
	   screens so the lockup never collides with the mobile menu toggle. */
	font-family: "Inter", Arial, Helvetica, sans-serif;
	font-size: clamp(1.75rem, 3.4vw, 2.5rem);   /* 28px -> 40px */
	font-weight: 800;
	letter-spacing: -0.02em;
	line-height: 1.15;
	display: inline-block;
}

.oo-wordmark-bar {
	color: var(--oo-orange-light);
	font-weight: inherit;
}

/* The 2015 tagline carried a hairline rule above it. That rule is drawn in
   currentColor so it always matches whatever the Customizer sets the tagline
   colour to -- white on the green band today, correct automatically if the
   band colour ever changes.

   2015 pulled the tagline up into the wordmark's descender space with a
   negative margin; at the larger wordmark size that reads as cramped, so the
   offset is positive here and the rule gets its own breathing room.

   Requires "Display Site Tagline" to be ON in the Customizer. */
.site-header .site-description,
.ast-site-identity .site-description {
	margin-top: 0.5rem;
	padding-top: 0.45rem;
	border-top: 1px solid currentColor;
}


/* --------------------------------------------------------------------------
   22.2  Superscript and subscript
   --------------------------------------------------------------------------
   Astra's normalize layer (main.min.css) sets:
       sub, sup { line-height: 0; position: relative; vertical-align: baseline }
       sup      { top: -0.5em }
   Collapsing the line box to zero lifts the marker clear of its own line and
   inflates the line above it. On /calendar/ this pushed the "th" in
   "June 15th" about 11px too high and forced the "Session 202606" heading to
   wrap onto an extra line. The 2015 theme used the plain vertical-align
   keywords with an inherited line-height.

   Scoped to .entry-content so that plugin and admin UI keep Astra's version.
   -------------------------------------------------------------------------- */

.entry-content sup,
.entry-content sub {
	font-size: 0.75em;
	line-height: inherit;
	position: static;
	top: auto;
}

.entry-content sup { vertical-align: super; }
.entry-content sub { vertical-align: sub; }


/* --------------------------------------------------------------------------
   22.3  Content tables
   --------------------------------------------------------------------------
   2015 drew horizontal rules only: 5px cells, left-aligned, top-aligned,
   a 1px #d0d0d0 rule under each row and a 2px #848484 rule under the header.
   Astra draws a full 1px grid with border-collapse: separate and 0.7em/1em
   padding, and centers th. On the class timetable that reads as a
   spreadsheet rather than a schedule, and adds roughly 6px of height to
   every one of ~60 rows.

   Scoped to .entry-content so Astra's own widget and comment tables, and the
   calendar widget, are untouched.
   -------------------------------------------------------------------------- */

.entry-content table {
	width: 100%;
	margin: 0 0 1.5em;
	border: 0;
	border-collapse: collapse;
	border-spacing: 0;
}

.entry-content table td,
.entry-content table th {
	padding: 5px;
	border: 0;
	text-align: left;
}

.entry-content table td {
	border-bottom: 1px solid var(--oo-rule-light);
	vertical-align: top;
}

.entry-content table th {
	border-bottom: 2px solid var(--oo-rule-dark);
	vertical-align: baseline;
	font-weight: 700;
}

/* --------------------------------------------------------------------------
   22.4  Page and single-post title size
   --------------------------------------------------------------------------
   REPLACES the Customizer > Additional CSS rule `.entry-title { font-size:
   48px !important }`. Delete that rule from Additional CSS -- if both are
   present the !important one still wins and this block does nothing.

   Why the Additional CSS version was a problem:

   1. `.entry-title` is not only the page title. Astra reuses the class for
      every post heading in blog, archive, and search listings. The bare
      selector therefore blew up all twelve search-result headings on
      /?s=hawaiian to 48px, not just the one page title.
   2. `!important` was unnecessary. Astra's own rule lives in
      astra-theme-dynamic-css, which is enqueued at position 3; this
      stylesheet is at position 12. Matching Astra's exact selector wins on
      cascade order alone, with no specificity escalation and nothing left
      for a future rule to have to out-shout.
   3. Additional CSS is stored in the database (as a `custom_css` post), not
      in the theme folder. It will NOT travel with OleloOnline_2026 when the
      theme is copied to the live VPS -- a real hazard for the cutover.
   4. The v0.1.1 audit deliberately removed all 21 `!important` flags from
      this stylesheet. Reintroducing one undoes that decision.

   The selector below is Astra's own, verbatim, so it targets the single
   page/post title header and nothing else. Listing titles fall back to the
   Customizer's blog title settings, where they belong.

   NOTE: 48px here vs. 45px for Global H1. Deliberate on Kaliko's part, but
   it does mean a page title is larger than an H1 inside the content.
   -------------------------------------------------------------------------- */

header.entry-header:not(.related-entry-header) .entry-title {
	font-size: 3rem;   /* 48px — KEEP IN SYNC with Customizer > Global > Typography > H1 */

	/* Added rev 34 (2026-08-07), moved here from the bare `.entry-title` rule
	   that used to sit in Section 02. Kaliko wants single post and page
	   titles centred and listing headings left; the old selector could not
	   tell the two apart, because Astra puts the same class on both.

	   A KNOWING DEPARTURE FROM ARCHITECTURE RULE 1. Astra can express this:
	   Customize > Post Types > Single Post > Single Post Title > Horizontal
	   Alignment, and again under Single Page. Two settings, in `astra-settings`,
	   in the database. Reasons for keeping it here instead:

	   1. This block already owns the same element's font-size, for the reason
	      given above. Splitting one heading's presentation across the
	      Customizer and this stylesheet is worse than either alone -- the next
	      person to change the alignment would not think to look here.
	   2. The go-live plan names the Customizer as the last open blocker and
	      warns that a missed setting "looks like nothing rather than like
	      something". Alignment is exactly that kind of miss. This travels
	      inside the theme folder and cannot be left behind.

	   Reverting is deleting this one declaration and setting the two
	   Customizer controls instead; nothing else depends on it. */
	text-align: center;
}

/* --------------------------------------------------------------------------
   22.5  Lining figures for the Vollkorn headings
   --------------------------------------------------------------------------
   Vollkorn ships oldstyle (text) figures by default: measured figure height is
   0.745 of cap height, so numerals sit at x-height instead of full height. In
   running prose that is elegant; in titles carrying course codes it is not.
   `OOVC-CH1` renders with the 1 as a small oldstyle numeral easily misread as
   a lowercase i or l, and `Session 202606` / `0699R` sit visibly below the
   capitals around them.

   Vollkorn does include lining figures, just not as the default, so this is a
   feature switch rather than a workaround. `font-variant-numeric` is the
   standard property; the `font-feature-settings` line is a belt-and-braces
   fallback for older engines and is harmless where the first is supported.

   Scoped to the headings that actually use Vollkorn. If the H1 face ever
   changes to one with lining figures by default, this block becomes a no-op
   rather than a problem -- fonts without an `lnum` feature simply ignore it.
   -------------------------------------------------------------------------- */

header.entry-header:not(.related-entry-header) .entry-title,
.entry-content h1 {
	font-variant-numeric: lining-nums;
	font-feature-settings: "lnum" 1;
}

/* ====================== END SECTION 22 ==================================== */


/* ==========================================================================
   23. PAID MEMBERSHIPS PRO — FRONT-END PAGES
   ==========================================================================
   Added 2026-08-03, after the first audit of the PMPro pages performed as a
   logged-in member (test-user-monthly). Covers:

       /membership-account/
       /membership-account/your-profile/
       /membership-account/membership-levels/
       /membership-account/membership-checkout/
       /membership-account/membership-cancel/

   SCOPE: page content only. The sidebar login widget is Section 20's
   territory and is NOT touched here — every rule below is either scoped to
   `.pmpro` (page markup) or is a custom property, and Section 20.2's
   `#secondary.widget-area .widget .pmpro_card_title` at (1 id, 3 classes)
   comfortably outranks the (0, 2, 0) selectors here. Verified: after these
   rules the sidebar title still measures Inter Tight 20px/600 white.

   WHERE PMPro's COLOURS ACTUALLY COME FROM — read before adding colour here.

   PMPro has its own colour settings in wp-admin, which emit an inline
   `<style id="pmpro_colors">` block. That block loads at roughly position 15
   in the cascade — i.e. AFTER this stylesheet (position 12). Current values:

       --pmpro--color--base:     #ffffff
       --pmpro--color--contrast: #793195
       --pmpro--color--accent:   #0c8c01
       --pmpro--color--border--variation: hsl(0,0%,91%)   i.e. #e8e8e8

   (2026-08-06, rev 25: the hex on the line above used to be written as a
   nested CSS comment. CSS comments do not nest — that inner terminator closed
   THIS header block early, and the prose that followed was then parsed as a
   selector prelude which swallowed rule 23.1 whole. Verified in the browser:
   `.pmpro .pmpro_section_title { color: var(--oo-purple-mid) }` was absent
   from document.styleSheets entirely while 23.2's size rules survived. Never
   write a comment terminator inside a comment block.)

   Two consequences:

   1. A plain `:root { --pmpro--color--*: ... }` in this file would LOSE to
      that inline block. Winning from here needs `html:root` or similar, which
      is a specificity hack against a value that has a proper settings home.
   2. Those settings are therefore the right place to change PMPro's colours,
      not this file. See the ACTION list at the end of this section.

   What genuinely belongs here is only what the settings cannot express: the
   heading colour (PMPro has no separate heading colour — headings inherit the
   "contrast" text colour) and heading sizes (PMPro has no typography
   settings at all).
   ========================================================================== */


/* --------------------------------------------------------------------------
   23.1  PMPro heading colour
   --------------------------------------------------------------------------
   PMPro sets `.pmpro { color: var(--pmpro--color--contrast) }` — one colour
   for the whole wrapper, headings and body copy alike. There is no separate
   heading control.

   Because `contrast` is set to the brand purple, *entire paragraphs* render
   purple: the "You have selected the ... membership level" block on checkout,
   "You have the following active memberships." on the cancel page, and the
   thank-you copy on the account page.

   THAT IS THE DECISION, NOT A DEFECT (Kaliko, 2026-08-04). Purple body copy on
   the PMPro pages marks them as the member's own back-of-house area, the same
   signal the sidebar widgets carry. Do not "fix" it. An earlier revision of
   this comment instructed setting `contrast` to #222222; that instruction was
   withdrawn and must not be reinstated.

   So this rule is not a repair — it is the heading authority for these pages,
   and it holds whatever `contrast` is set to. Measured 2026-08-07: `contrast`
   is #783194 (7.88:1 on white, AA clear) and this rule paints the section and
   card titles --oo-purple-mid on top of it.
   -------------------------------------------------------------------------- */

.pmpro .pmpro_section_title,
.pmpro .pmpro_card_title {
	color: var(--oo-purple-mid);
}


/* --------------------------------------------------------------------------
   23.2  PMPro heading scale
   --------------------------------------------------------------------------
   PMPro ships its own sizing classes (`pmpro_font-x-large`, `pmpro_font-large`)
   which do not know about the site's type scale. Measured drift:

       .pmpro_section_title  32px / 700   vs the site's H2 at 30px / 800
       .pmpro_card_title     24px / 700   vs the site's H3 at 24px / 800

   Small, but it made "My Account" and "My Memberships" render a step larger
   and lighter than a content H2 immediately above them on the same page.
   Realigned to the Customizer scale.

   KEEP IN SYNC: if the H2 or H3 sizes change in Customizer > Global >
   Typography, these two values must change with them. They are hard-coded
   here because PMPro's classes carry explicit sizes that would otherwise win.
   -------------------------------------------------------------------------- */

.pmpro .pmpro_section_title {
	font-size: 1.875rem;   /* 30px — matches Global H2 */
	font-weight: 800;
}

.pmpro .pmpro_card_title {
	font-size: 1.5rem;     /* 24px — matches Global H3 */
	font-weight: 800;
}


/* ==========================================================================
   PMPro COLOUR SETTINGS — SETTLED, NO ACTION REQUIRED
   ==========================================================================
   wp-admin > Memberships > Settings > Design/Colors. These live in the
   database, NOT in this theme, so they do not travel to the VPS — re-enter
   them at cutover. Recorded here because this stylesheet reasons about them.

   Measured from the rendered `#pmpro_colors` inline block on 2026-08-07, not
   read from the settings screen:

   1. Accent  #0d8700  — SETTLED. White on it measures 4.68:1, clearing the
      WCAG AA floor of 4.5:1. This is the green on every PMPro button
      ("Select", "Update Profile", "Submit").

      History, so it is not re-flagged: this was #0c8c01, which measured
      4.41:1 and failed AA. Kaliko corrected it on 2026-08-04. He went to
      #0d8700 rather than the #0d8800 that was suggested; both clear AA and
      the difference is one step of red, so it was left alone. Note it is
      therefore NOT identical to --oo-green-dark — if the two ever need to
      match exactly, change the setting, not the token.

   2. Contrast  #783194  — SETTLED, KEEPING PURPLE. Measures 7.88:1 on white.

      PMPro uses `contrast` as the body text colour for all of its markup, so
      this turns whole paragraphs purple on the checkout, cancel and account
      pages. THAT IS DELIBERATE — see the decision recorded in 23.1 above.
      An earlier revision of this block instructed changing it to #222222.
      That instruction was withdrawn on 2026-08-04 and MUST NOT be reinstated;
      acting on it would undo a decision, not fix a bug.

   3. Base  #ffffff  — correct, leave alone.

   ========================================================================== */

/* ====================== END SECTION 23 ==================================== */


/* ==========================================================================
   24. BUTTONS — PRESS BEHAVIOUR
   ==========================================================================
   Added 2026-08-04.

   THE PROBLEM. PMPro's filled buttons invert on hover: the background goes
   `transparent` and the label flips to green, leaving a white button with a
   green outline. Measured on the sidebar Log In button while genuinely
   hovered -- `background-color: rgba(0,0,0,0)`, `color: rgb(13,135,0)`.

   Inversion is a legitimate convention, but it reads as the button *lighting
   up and emptying out* under the cursor. Kaliko's model is the better one for
   a control about to be pressed: a real object gets darker as your hand
   shadows it, and darker still when pushed in. It also keeps the button's
   silhouette stable -- nothing appears to change or disappear.

   THE MODEL
     rest    brand green
     hover   ~20% darker  -- the shadow of an approaching hand
     active  ~35% darker, pushed 1px down, with an inset shadow so the
             surface reads as recessed rather than merely repainted

   Contrast improves at every step, since darker green under white text only
   gains: 4.63:1 rest, 6.56:1 hover, 8.73:1 pressed. All clear WCAG AA; hover
   and pressed clear AAA.

   DERIVED, NOT HARD-CODED. The darker shades are `color-mix()` against
   PMPro's own accent variable, so if the accent is changed again in
   Memberships > Settings > Design the hover and pressed states follow it
   instead of drifting. Each is preceded by a static hex fallback, so a
   browser without `color-mix` still gets a sensible darker green.

   SCOPE -- deliberately narrow. Covers the sidebar Log In submit and PMPro's
   filled buttons. Excluded on purpose:
     .pmpro_btn-plain    the "Show Password" text toggle, not a filled button
     .pmpro_btn-outline  the "Your Level" marker, outline by design
     .pmpro_btn-cancel   destructive actions, left to PMPro's own treatment
   Astra's own buttons elsewhere use --ast-global-color-0 (a purple-blue) and
   are NOT touched -- targeting `input[type=submit]` broadly would have turned
   every form button on the site green.
   ========================================================================== */

#secondary.widget-area .widget input.button-primary,
.pmpro .pmpro_btn:not(.pmpro_btn-plain):not(.pmpro_btn-outline):not(.pmpro_btn-cancel) {
	background-color: var(--oo-green-dark);
	border: 1px solid var(--oo-green-dark);
	color: #fff;
	transition: background-color 0.15s ease,
	            border-color 0.15s ease,
	            box-shadow 0.15s ease,
	            transform 0.05s ease;
}

/* Hover and keyboard focus -- one step darker. `:focus-visible` shares the
   treatment so a keyboard user gets the same affordance a mouse user does. */
#secondary.widget-area .widget input.button-primary:hover,
#secondary.widget-area .widget input.button-primary:focus-visible,
.pmpro .pmpro_btn:not(.pmpro_btn-plain):not(.pmpro_btn-outline):not(.pmpro_btn-cancel):hover,
.pmpro .pmpro_btn:not(.pmpro_btn-plain):not(.pmpro_btn-outline):not(.pmpro_btn-cancel):focus-visible {
	background-color: #0a6d00;
	background-color: color-mix(in srgb, var(--pmpro--color--accent, #0d8800) 80%, #000);
	border-color: #0a6d00;
	border-color: color-mix(in srgb, var(--pmpro--color--accent, #0d8800) 80%, #000);
	color: #fff;
}

/* Pressed -- darker again, nudged down, recessed with an inset shadow. The
   1px translate is what sells the press; the inset shadow stops it reading as
   a plain colour swap. */
#secondary.widget-area .widget input.button-primary:active,
.pmpro .pmpro_btn:not(.pmpro_btn-plain):not(.pmpro_btn-outline):not(.pmpro_btn-cancel):active {
	background-color: #085800;
	background-color: color-mix(in srgb, var(--pmpro--color--accent, #0d8800) 65%, #000);
	border-color: #085800;
	border-color: color-mix(in srgb, var(--pmpro--color--accent, #0d8800) 65%, #000);
	color: #fff;
	transform: translateY(1px);
	box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.28);
}

/* A real focus ring as well as the colour change -- colour alone is not a
   sufficient focus indicator, and the darkening is subtle by design. */
#secondary.widget-area .widget input.button-primary:focus-visible,
.pmpro .pmpro_btn:not(.pmpro_btn-plain):not(.pmpro_btn-outline):not(.pmpro_btn-cancel):focus-visible {
	outline: 2px solid var(--oo-purple-mid);
	outline-offset: 2px;
}

/* Reduced-motion preference: keep the colour feedback, drop the movement. */
@media (prefers-reduced-motion: reduce) {
	#secondary.widget-area .widget input.button-primary,
	.pmpro .pmpro_btn:not(.pmpro_btn-plain):not(.pmpro_btn-outline):not(.pmpro_btn-cancel) {
		transition: background-color 0.15s ease, border-color 0.15s ease;
	}

	#secondary.widget-area .widget input.button-primary:active,
	.pmpro .pmpro_btn:not(.pmpro_btn-plain):not(.pmpro_btn-outline):not(.pmpro_btn-cancel):active {
		transform: none;
	}
}

/* ====================== END SECTION 24 ==================================== */


/* ==========================================================================
   SECTION 25 — DECORATIVE FERN PATTERN ON THE PAGE FIELD   (new in 0.2.5)
   Scope: the outer page field only — the margin area around the content card.
          Nothing inside the card, the header band, the sidebar or the footer
          widgets is touched.
   Status: VISUAL EXPERIMENT. Delete this whole section to revert; nothing
          else in the file depends on it.
   --------------------------------------------------------------------------
   WHERE THIS ACTUALLY LANDS, AND WHY NOT `.ast-container`

   The request was for `.ast-container`, on the belief that it paints the page
   background in #F2F0FE. Measured on /calendar/, both halves of that are off:

     - `.ast-container` computes to `rgba(0,0,0,0)` — it is a transparent
       max-width wrapper, not a painted surface. It is ALSO the class on
       `.site-primary-header-wrap`, so a background set on it would have
       tinted the green header band as well as the content area.
     - #F2F0FE is `--ast-global-color-5` — a slot in Astra's stock starter
       palette that nothing on the site currently paints with. The page field
       is #f8fafa, and it is painted on `body` by Astra's dynamic CSS
       (Global > Colors > Site Background in the Customizer).

   So the pattern goes on `body`, which is the element that genuinely owns the
   page field. That also future-proofs it: when Global > Container goes
   unboxed (item 5 on the Customizer list in calendar-page-parity), this field
   becomes the whole page rather than a band down each side.

   WHY A PSEUDO-ELEMENT AND NOT `background-image` ON `body`

   Painting the SVG straight onto `body` would work, but the only way to make
   it fainter would be to re-encode the stroke alpha inside the data URL — in
   two places, since the tile carries two rotated copies of the frond. Putting
   it on `body::before` puts the subtlety on a plain `opacity`, which is one
   token and one number. For a look-and-see experiment that dial matters more
   than the extra rule.

   HOW THE STACKING WORKS (do not "simplify" this away)
     - `body` is already `position: relative` (Astra), so `inset: 0` on the
       pseudo-element resolves against the full document box. We do not set
       position on `body` ourselves — it is Astra's, and it is already right.
     - `html` has no background, so `body`'s background-color propagates to
       the canvas. A `z-index: -1` child therefore paints ON TOP of the
       #f8fafa field but UNDER every in-flow box — including the white content
       card, which stays clean white with no pattern showing through.
     - `min-height: 100vh` alongside `inset: 0` covers the short-page case
       (login, 404), where the document is shorter than the viewport and
       `bottom: 0` alone would leave the bottom of the screen unpatterned.
     - `pointer-events: none` so it can never intercept a click.

   THE ARTWORK
   Same hāpuʻu-ish frond tile as the Bands in Town widget on kbeamer.com, at
   the same 260px repeat, restruck in brand dark green (%230d8800 is #0d8800
   URL-encoded) instead of that site's brown #9f5d3c. Two copies per tile, the
   second rotated 180°, so the repeat does not read as a grid.

   TUNING — the only two numbers you should need
     --oo-fern-opacity   how faint. 0.13 now. 0.08 is barely-there;
                         0.20 starts to read as a deliberate wallpaper.
     --oo-fern-tile      frond size. 260px now. Larger = fewer, bigger fronds.
   To change the ink colour, replace BOTH occurrences of %230d8800 in the data
   URL below (one per <g>) — e.g. %23793195 for purple-mid.
   ========================================================================== */

:root {
	--oo-fern-opacity: 0.08;
	--oo-fern-tile: 260px;
}

body::before {
	content: "";

	position: absolute;
	inset: 0;
	min-height: 100vh;
	z-index: -1;
	pointer-events: none;

	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='260' height='260' viewBox='0 0 260 260'%3E%3Cg fill='none' stroke='%230d8800' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M22 238 C48 191 70 143 102 37'/%3E%3Cpath d='M35 211 C25 193 24 178 28 166 C42 175 48 187 49 197'/%3E%3Cpath d='M48 184 C37 166 37 150 42 139 C55 148 61 160 61 171'/%3E%3Cpath d='M61 156 C51 139 52 123 57 112 C70 121 75 133 74 144'/%3E%3Cpath d='M74 128 C66 112 68 97 74 86 C86 96 90 107 87 118'/%3E%3Cpath d='M86 100 C80 85 83 71 90 61 C101 72 103 83 99 94'/%3E%3Cpath d='M46 207 C60 198 73 196 84 199 C77 211 66 217 55 218'/%3E%3Cpath d='M58 180 C73 171 86 170 97 174 C89 186 78 191 67 191'/%3E%3Cpath d='M70 152 C85 144 98 143 109 148 C101 159 90 164 79 163'/%3E%3Cpath d='M82 124 C97 117 110 118 120 123 C111 134 100 138 89 136'/%3E%3Cpath d='M94 96 C108 90 120 92 130 98 C120 108 109 111 99 108'/%3E%3C/g%3E%3Cg transform='translate(260 260) rotate(180)' fill='none' stroke='%230d8800' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M22 238 C48 191 70 143 102 37'/%3E%3Cpath d='M35 211 C25 193 24 178 28 166 C42 175 48 187 49 197'/%3E%3Cpath d='M48 184 C37 166 37 150 42 139 C55 148 61 160 61 171'/%3E%3Cpath d='M61 156 C51 139 52 123 57 112 C70 121 75 133 74 144'/%3E%3Cpath d='M74 128 C66 112 68 97 74 86 C86 96 90 107 87 118'/%3E%3Cpath d='M46 207 C60 198 73 196 84 199 C77 211 66 217 55 218'/%3E%3Cpath d='M58 180 C73 171 86 170 97 174 C89 186 78 191 67 191'/%3E%3Cpath d='M70 152 C85 144 98 143 109 148 C101 159 90 164 79 163'/%3E%3Cpath d='M82 124 C97 117 110 118 120 123 C111 134 100 138 89 136'/%3E%3C/g%3E%3C/svg%3E");

	background-repeat: repeat;
	background-position: center top;
	background-size: var(--oo-fern-tile) var(--oo-fern-tile);

	opacity: var(--oo-fern-opacity);
}

/* Phones: the field is a thin gutter or gone entirely, so a big frond shows
   as unreadable fragments -- hence the smaller tile.

   NOTE THE DIRECTION: the opacity here is HIGHER than the desktop value
   (0.10 against 0.08), not lower. That is deliberate (Kaliko, 2026-08-04).
   At 180px the fronds are small enough to carry a little more ink without
   reading as noise, and there is less field for them to sit in. Do not
   "correct" this to a smaller number on the assumption that mobile should
   always be fainter. If you change the desktop value, re-check that this
   one is still above it on purpose. */
@media screen and (max-width: 600px) {
	:root {
		--oo-fern-opacity: 0.10;
		--oo-fern-tile: 180px;
	}
}

/* Lesson pages get printed. Decorative ink is wasted toner. */
@media print {
	body::before {
		display: none;
	}
}

/* ====================== END SECTION 25 ==================================== */



/* =========================================================
   26. ARCHIVE TITLES + EMPTY-SEARCH HELPERS
=========================================================
   Added 2026-08-05, from the OleloOnline_2015 template audit
   (claude-docs/template-audit-2015-2026.md). Both blocks pair with
   functions.php rev 08: section 8.1 emits .oo-archive-term, and
   template-parts/content-none.php emits .oo-search-helpers.
========================================================= */

/* --------------------------------------------------------------------------
   26.1  Archive term colour
   --------------------------------------------------------------------------
   2015 printed "Category:<span class="colortxt"> term</span>" and coloured the
   term in the brand orange #ff9700 (kept in section 01 as --original-orange).

   NOT using --original-orange here, deliberately. Measured against the white
   content card, #ff9700 gives a contrast ratio of 2.17:1. WCAG AA wants 4.5:1
   for normal text and 3:1 for large -- the archive title renders at 32px, which
   is large text, and 2.17:1 still misses that floor. The 2015 site shipped this
   failure for eleven years; there is no reason to carry it forward.

   --oo-orange-dark (#974E08) measures 6.16:1 on the same white and reads as the
   same colour family at heading weight. If you want the brighter orange back
   anyway, swap the value and know what you are accepting.

   Scoped to the span, so "Category:" itself keeps the purple heading colour --
   which is exactly the 2015 arrangement, with 2026's purple standing in for
   2015's green.
   -------------------------------------------------------------------------- */

.oo-archive-term {
	color: var(--oo-orange-dark);
}

/* --------------------------------------------------------------------------
   26.2  Empty-search helper block
   --------------------------------------------------------------------------
   The block sits inside Astra's .no-results card (see the note in
   template-parts/content-none.php explaining why it is a template and not a
   hook), so it inherits the card background and padding and needs no colour
   declared here.

   What it does need: the three headings arrive as <h2 class="widgettitle">,
   which inherits Global H2 -- measured at 30px/600. That is the same size as a
   page section heading, for what is a set of fallback links. Sized down here
   rather than in the Customizer because Global H2 is correct everywhere else.

   Declaring margins on both sides of the heading rather than only the bottom:
   a partial rule invites the surrounding content flow to leak in.
   -------------------------------------------------------------------------- */

.oo-search-helpers {
	margin-top: 2rem;
}

.oo-search-helpers .widgettitle {
	font-size: 1.15rem;
	line-height: 1.3;
	margin-top: 1.75rem;
	margin-bottom: 0.5rem;
}

.oo-search-helpers .widget:first-of-type .widgettitle {
	margin-top: 0;
}

/* The category list is a plain <ul> from the_widget(); keep it from picking up
   the counter-based list styling that section 04 gives .post-content lists. */
.oo-search-helpers ul {
	margin: 0 0 1rem;
	padding-left: 1.25rem;
}

.oo-search-helpers ul li {
	margin-bottom: 0.25rem;
}

/* ====================== END SECTION 26 ==================================== */



/* =========================================================
   27. FOOTER MENUS — 2015 PARITY
=========================================================
   Added 2026-08-05 (rev 23). Derived from a live computed-style diff of the
   three footer menus:

     live     https://oleloonline.com/          (OleloOnline_2015)
     staging  https://olelo-online.local/       (Astra + OleloOnline_2026)

   WHAT THE TWO THEMES ACTUALLY BUILD

   2015 put the menus in the `sidebar-footer` widget area, rendered by
   sidebar-footer.php inside `.sidebar-theme-wrap`, and laid them out as three
   floated 33.3% widgets inside a 1044px centred `#sidebar`.

   2026 puts them in Astra's Header Footer Builder "Above Footer" row, which
   emits a CSS grid instead:

       #colophon
         .site-above-footer-wrap                 <- the dark band
           .ast-builder-grid-row-container-inner
             .ast-builder-footer-grid-columns    <- display:grid, 3 equal cols
               .site-footer-above-section-1..3
                 aside.footer-widget-area
                   section.widget.widget_listcategorypostswidget
                     h2.widget-title
                     ul.footlings

   The widget markup is identical across the two themes apart from the heading
   element — 2015 emits `div.widget-title`, Astra emits `h2.widget-title`. The
   selectors below match on the CLASS, not the tag, so they hold either way.

   WHAT IS DELIBERATELY NOT COPIED FROM 2015

   1. The float layout. Astra's grid already handles the tablet and mobile
      stacking through its own `ast-builder-grid-row-tablet-*` /
      `-mobile-*` classes, which are set in the Customizer. Forcing 2015's
      floats back in would mean re-implementing those breakpoints by hand and
      then keeping them in sync with a Customizer setting that does not know
      this file exists. The grid gives the same three-column result.

   2. The 1044px inner width. Astra's footer row inherits the site content
      width (1200px), so the footer columns line up with the content above
      them. Narrowing the footer alone to 1044px would put a visible step in
      the left edge of the page. If you want the 2015 measure back, it is a
      Customizer setting (Footer Builder -> Above Footer -> inner width), not
      a change here.

   3. Arial. 2015 ran Arial through the whole footer; 2026 runs Inter. The
      footer is the only place left where the old stack would surface, so
      matching it literally would make the footer the one block on the page
      that opts out of the type system. Size, weight, colour, tracking and
      rhythm are matched exactly; the face is 2026's. Inter at 20px/700 with
      3px tracking sets very slightly wider than Arial did — if the headings
      now wrap where they did not before, drop the tracking to 2px rather than
      reaching for a smaller size.

   SPECIFICITY NOTE

   Everything here is prefixed `#colophon`, giving (1,x,y). That clears three
   things at once without a single !important: Astra's `.widget-title`
   (0,1,0) and `h2.widget-title` (0,1,1), the global `h1..h6 { letter-spacing:
   -1px }`, and Section 21's site-wide link rules, which sit at (0,0,1) and
   (0,1,1) by design. Section 21's footer exclusion is handled here rather
   than by adding `.site-footer` to its four `:where(:not(...))` lists —
   editing one scoped block beats editing four long exclusion lists, and the
   trap documented in 21.2 (a class that turns out to be a body class) does
   not apply to an ID on the footer element itself.
========================================================= */

/* --------------------------------------------------------------------------
   27.1  The dark band
   --------------------------------------------------------------------------
   2015 used #222, not black. Astra's Customizer currently has this row set to
   #000, and the override lives here rather than in the Customizer so the whole
   footer treatment reads as one block in one file. If you would rather set it
   in the Customizer, delete the background-color line below — nothing else in
   this section depends on it.

   Padding is 2015's exact `60px 0 1px`. The 1px bottom is not a typo: it stops
   the last widget's 60px bottom margin from collapsing out through the band and
   dragging the background up with it.
   -------------------------------------------------------------------------- */

#colophon .site-above-footer-wrap {
	background-color: #222;
	padding: 60px 0 1px;
}

/* --------------------------------------------------------------------------
   27.2  Widget box
   --------------------------------------------------------------------------
   `color` is set on the widget rather than only on the links so that any plain
   text a widget emits — a "no posts found" string, a stray separator — comes
   out white instead of Astra's #222 on a #222 band, which would be invisible.
   -------------------------------------------------------------------------- */

#colophon .site-above-footer-wrap .footer-widget-area,
#colophon .site-above-footer-wrap .widget {
	color: #fff;
	text-align: left;
}

#colophon .site-above-footer-wrap .widget {
	margin: 10px 0 60px;
	padding: 0;
	background-color: transparent;
	border: 0;
	border-radius: 0;
}

/* --------------------------------------------------------------------------
   27.3  Heading
   --------------------------------------------------------------------------
   2015: 20px / 700 / #ffb140 / uppercase / 3px tracking / 34px line box /
   30px below. Transparent background — the purple title bar is a SIDEBAR
   treatment (Section 20.2) and never applied in the footer.

   The colour is exposed as a local custom property so it can be swapped in one
   place. #ffb140 is the exact 2015 value and measures 8.9:1 on #222, well past
   the AA floor. Section 01's --oo-orange-light (#FFB670) is the nearest token
   at 9.5:1 and is visually indistinguishable at this size — use it instead if
   you would rather the footer drew from the palette than from a fourth orange:

       --oo-footer-title: var(--oo-orange-light);

   `font-family: inherit` is explicit because Astra sets a family on h2 and
   this heading is an h2 here but was a div in 2015; inheriting keeps it on the
   body face either way.
   -------------------------------------------------------------------------- */

#colophon .site-above-footer-wrap .widget-title {
	--oo-footer-title: #ffb140;

	font-family: inherit;
	font-size: 20px;
	font-weight: 700;
	line-height: 34px;
	letter-spacing: 3px;
	text-transform: uppercase;
	color: var(--oo-footer-title);
	background-color: transparent;
	margin: 0 0 30px;
	padding: 0;
	border-radius: 0;
}

/* A heading is occasionally linked (Astra offers it as a widget option); keep
   it the heading colour rather than letting Section 21 recolour it purple. */
#colophon .site-above-footer-wrap .widget-title a,
#colophon .site-above-footer-wrap .widget-title a:link,
#colophon .site-above-footer-wrap .widget-title a:visited,
#colophon .site-above-footer-wrap .widget-title a:hover,
#colophon .site-above-footer-wrap .widget-title a:focus {
	color: var(--oo-footer-title);
	text-decoration-line: none;
}

/* --------------------------------------------------------------------------
   27.4  The list
   --------------------------------------------------------------------------
   Metrics come from Section 10 (now corrected to px). Repeated here at footer
   specificity because Astra's footer widget CSS sets its own font-size and
   line-height on `.footer-widget-area li`, which would otherwise win.

   The 6px left padding is 2015's. It is not an indent for a bullet — there are
   no bullets — it is the optical gutter that stops the first character sitting
   flush against the column edge. 2015's `ul.footlings li { padding-left: 0 }`
   lost to `#sidebar .widget li { padding-left: 6px }` on the live site, so 6px
   is what actually shipped, and 6px is what is matched here.

   FONT SIZE — DELIBERATE DEPARTURE FROM 2015 (rev 24, 2026-08-05)

   15px, not 2015's 14px. The 2026 footer runs on Astra's 1200px grid rather
   than 2015's 1044px, so each column is roughly 360px against 2015's ~348px
   and the longer entries have room they did not have before. This is the one
   value in Section 27 that is intentionally NOT at parity — everything else
   still measures identical to the live 2015 site.

   Line-height stays at 2015's 24px rather than scaling with the type. That
   moves the ratio from 1.71 to 1.60, which is still comfortable for the
   two-line entries ("Papani Pronouns #1…"), and it keeps the vertical rhythm
   of the three columns exactly where it was. If the wrapped entries start to
   feel tight, 26px restores the original ratio and is the only line to change.
   -------------------------------------------------------------------------- */

#colophon .site-above-footer-wrap ul.footlings {
	margin: 0 0 20px;
	padding-left: 0;
	list-style: none;
	font-size: 15px;
}

#colophon .site-above-footer-wrap ul.footlings li {
	font-size: 15px;
	line-height: 24px;
	margin-bottom: 16px;
	padding-left: 6px;
	list-style: none;
	color: #fff;
}

/* --------------------------------------------------------------------------
   27.5  Links
   --------------------------------------------------------------------------
   2015: white, no underline at rest, underline on hover. That is the opposite
   of Section 21's site-wide behaviour (always underlined, purple), which is
   correct for body copy on white and unreadable on a #222 band.

   :focus is carried alongside :hover for the same reason it is in Section 21 —
   keyboard users get the same feedback as mouse users. :focus-visible is NOT
   used here: the footer is the last stop in the tab order and the visible ring
   is worth keeping unconditional.

   The <span title="..."> the footlings template wraps around each label
   inherits colour, so it needs no rule of its own.
   -------------------------------------------------------------------------- */

#colophon .site-above-footer-wrap ul.footlings li a,
#colophon .site-above-footer-wrap ul.footlings li a:link,
#colophon .site-above-footer-wrap ul.footlings li a:visited {
	color: #fff;
	font-size: 15px;
	font-weight: 400;
	text-decoration-line: none;
}

#colophon .site-above-footer-wrap ul.footlings li a:hover,
#colophon .site-above-footer-wrap ul.footlings li a:focus,
#colophon .site-above-footer-wrap ul.footlings li a:active {
	color: #fff;
	text-decoration-line: underline;
	text-decoration-thickness: 1px;
	text-decoration-color: currentColor;
	text-underline-offset: 0.15em;
}

/* ====================== END SECTION 27 ==================================== */



/* =========================================================
   28. FOOTER COPYRIGHT BAR
=========================================================
   Added 2026-08-05 (rev 24).

   NOT a 2015 parity block — this is a new decision. 2015 ran the copyright
   line on a green band; this is purple, chosen to close the footer with the
   brand's darkest colour under the #222 menu band rather than jumping back to
   a third hue.

   WHAT ASTRA BUILDS

       #colophon
         .site-below-footer-wrap                 <- the bar
           .ast-builder-grid-row-container-inner
             .ast-builder-footer-grid-columns
               .site-footer-below-section-1
                 .ast-builder-layout-element.ast-footer-copyright
                   .ast-footer-copyright
                     p                           <- ALL of it, one paragraph

   The whole notice is a single <p> with two <br> separators, entered in the
   Customizer as the Copyright element's text. There is no per-line wrapper, so
   "the copyright line" and "the two link lines" cannot be addressed as three
   blocks. They are addressed as what they actually are: the paragraph's own
   text colour, and the colour of the two <a> children inside it.

   ONE VISIBLE CONSEQUENCE, worth knowing before you look: the full stops after
   "Terms and Conditions." and "Privacy Policy." sit OUTSIDE the anchors in the
   Customizer text, so they stay white while the link text goes orange. At 16px
   this is barely perceptible. If it bothers you, move each period inside its
   <a> in the Customizer — do not try to solve it here, because a CSS fix would
   mean generated content and a screen reader would then announce it twice.

   CONTRAST, measured against #4b0a65:
       #ffffff  13.7:1   — AAA
       #ffb670   8.0:1   — AAA
   Both clear AAA for normal text (7:1), so the orange is safe at this size and
   would remain safe if the bar's type ever got smaller.
========================================================= */

/* --------------------------------------------------------------------------
   28.1  The bar
   --------------------------------------------------------------------------
   Astra's Customizer currently paints this row white. As with the #222 band in
   27.1, the override lives here so the whole footer reads as one block in one
   file. Padding is left as Astra's `20px 0` — it already matches the visual
   weight the 2015 bar had.
   -------------------------------------------------------------------------- */

#colophon .site-below-footer-wrap {
	background-color: var(--oo-purple-dark);
}

/* --------------------------------------------------------------------------
   28.2  Copyright text
   --------------------------------------------------------------------------
   Set on the paragraph rather than the wrapper so it applies to the text nodes
   directly and does not have to out-specify Astra's own `.ast-footer-copyright`
   colour rule further down the cascade.
   -------------------------------------------------------------------------- */

#colophon .site-below-footer-wrap,
#colophon .site-below-footer-wrap .ast-footer-copyright,
#colophon .site-below-footer-wrap .ast-footer-copyright p {
	color: #fff;
}

/* --------------------------------------------------------------------------
   28.3  The two links
   --------------------------------------------------------------------------
   Underlined in every state, unlike the menu links above. These are policy
   documents that open in a new tab; the underline is the affordance that says
   so, and there is no hover-only version of that signal for touch users.

   Hover lifts to white rather than dimming, so the feedback direction matches
   the menus above (both get brighter, never darker).

   :link and :visited are both named for the same reason given in Section 21 —
   Astra sets `a:visited` at (0,1,1), so a rule that omitted it would leave
   visited links purple on purple once someone had clicked through.
   -------------------------------------------------------------------------- */

#colophon .site-below-footer-wrap .ast-footer-copyright a,
#colophon .site-below-footer-wrap .ast-footer-copyright a:link,
#colophon .site-below-footer-wrap .ast-footer-copyright a:visited {
	color: var(--oo-orange-light);
	text-decoration-line: underline;
	text-decoration-thickness: 1px;
	text-decoration-color: currentColor;
	text-underline-offset: 0.15em;
}

#colophon .site-below-footer-wrap .ast-footer-copyright a:hover,
#colophon .site-below-footer-wrap .ast-footer-copyright a:focus,
#colophon .site-below-footer-wrap .ast-footer-copyright a:active {
	color: #fff;
	text-decoration-line: underline;
	text-decoration-color: currentColor;
}

/* ====================== END SECTION 28 ==================================== */


/* ==========================================================================
   SECTION 29 — LIST CATEGORY POSTS: LESSON LISTINGS   (new in 0.3.0)
   ==========================================================================
   Added 2026-08-06. Restores the 2015 appearance of the LCP listings on
   /coursework-by-series/ (and anywhere else the papaheluinoa* templates run).

   SCOPE — READ THIS BEFORE ADDING A RULE HERE (rev 26, 2026-08-06)

   This section has TWO scopes on purpose, and the split is not arbitrary:

     29.2 / 29.3   `.lcp-lesson-list`   LCP output ONLY
     29.4          `.definitionListBlock`   every definition list block

   The reason is what `.definitionListBlock` actually is. It is NOT an LCP
   class. It is a general-purpose content class Kaliko hand-writes in lesson
   bodies — a search of the site database found it in at least eight distinct
   places: grammar glossaries, the kaʻi/kahi example pairs, the class timetable
   widget, the /video-index/ page, and his own CSS style-guide page. That style
   guide explicitly documents putting a LINK inside the `<dt>` as an intended
   pattern ("uses a link in the dt to create beautiful effect").

   So rev 25, which scoped everything to `.definitionListBlock dt a`, was
   turning hand-written definition-list links green as well. Measured on
   /video-index/ before the fix: `<dt>0400 Series: <a>Pronunciation</a></dt>`
   rendered #0d8800 with no underline — Section 21's purple, underlined body
   link silently replaced on a page that has nothing to do with LCP.

   The colour work is now scoped to `.lcp-lesson-list`, a marker class the
   templates emit and nothing else uses. Do not hand-author it in post content.

   29.4 stays generic, and that is deliberate rather than an oversight. Checked
   against live 2015: the hairline under each term comes from
   `.post-content dt { border-bottom: 1px solid #999 }` — a GENERIC rule that
   applied to every definition list in post content, hand-written ones included.
   Scoping it to LCP would not "tighten" anything; it would silently remove the
   separator from eight hand-authored blocks that have had it since 2015. The
   dd indent reset is generic for the same reason.

   STILL OPEN: 2015's `.post-content dt` was broader still — it also put the
   hairline on `.questionAnswerBlock` terms, which have none in 2026. Left
   alone rather than changed silently; raise it if the Q&A blocks look bare
   next to the definition lists.

   WHAT THE TEMPLATE EMITS.  All four custom templates in
   themes/oleloonline_2026/list-category-posts/ build the same link:

       <dt>
         <a href="…">
           <span class="dpurpletext" title="…">0401V</span>       ← helu kaʻina
           <span title="Click to go to …">Pronunciation #1: …</span>  ← inoaikamu
         </a>
       </dt>
       <dd>… excerpt …</dd>

   Note there is no class on the second span. The 2015 effect was never "colour
   the title green" — it was "colour the LINK green, then colour the code span
   back to purple on top of it". The title takes its colour purely by being the
   uncoloured part of a green <a>. That is why the templates need no edit here:
   the whole fix is CSS, and the same CSS will keep working when you eventually
   strip the leading codes out of the WordPress post titles, because the code
   shown on this page comes from the `inoapoko` custom field, not from
   post_title. (Confirmed against live: the visible titles here are `inoaikamu`
   values already.)

   WHY IT BROKE IN 2026.  Three separate causes, all cascade, none template:

   1. In 2015 the global rule was `a, a:visited { color: #0b8c00 }` — every
      body link was brand green, so the listing link arrived green for free and
      `.dpurpletext` only had to override the code. In 2026 Section 21 makes
      every body link `--oo-link-color` (purple-dark). Purple link + purple code
      = no distinction at all. The two-colour split has to be re-established
      explicitly for this component now; it is no longer a side effect.
   2. Section 21 also underlines every body link. 2015 removed the underline
      here (`.definitionListBlock a { text-decoration: none }`, still present in
      Section 10) but that rule is (0,1,1) and sits EARLIER in this file than
      Section 21's `a:where(…):link`, which is also (0,1,1) — so Section 21 wins
      on order and the underline came back. Fixed below by specificity, not by
      moving Section 10.
   3. Astra restores the browser default `dd { margin-inline-start: 40px }`
      (24px as measured). 2015 zeroed it, so the excerpt hung under the title
      instead of being indented away from it.

   MEASURED 2015 TARGETS (live oleloonline.com, 2026-08-06):
       dt            18px / 700 / line-height 1.7 / #4B0A65
       dt a          #0b8c00, no underline
       dt .dpurple   #4B0A65
       dt            border-bottom 1px solid #999
       dd            16px / 400 / #6B6476 / margin 0 0 40px

   CONTRAST.  Green title text is 18px bold, which is 13.5pt bold — BELOW the
   WCAG "large text" threshold (14pt bold / 18.66px), so it needs the full
   4.5:1, not 3:1. `--oo-green-dark` (#0d8800) is 4.63:1 on white and clears it.
   The older 2015 literal #0b8c00 measures 4.40:1 and would NOT — which is
   exactly why the token was darkened on 2026-08-03. Do not "restore" the 2015
   hex here; the token is the corrected version of it.
   ========================================================================== */


/* --------------------------------------------------------------------------
   29.1  Local tokens — the one place to change your mind
   --------------------------------------------------------------------------
   Kept local to this section rather than folded into Section 01, because this
   is the live open question rather than a settled palette entry.

   THE DECISION YOU MAY WANT TO REVISIT: as written below this page is the only
   place on the 2026 site with green links, which is 2015-faithful but sits
   against the site-wide purple established in Section 21. The alternative is to
   keep the link purple (site convention) and push the helu kaʻina out to a
   different colour instead — the split survives either way, only the polarity
   changes. To try that, swap the two values on the next two lines:

       --oo-lcp-title-color: var(--oo-link-color);
       --oo-lcp-code-color:  var(--oo-orange-dark);      (7.4:1 on white, AAA)

   Nothing else in this section needs to change.

   Hover derives from the resting colour with color-mix() rather than naming a
   second hex, so it follows automatically if the title colour is swapped, and
   it darkens rather than inverts — the direction settled in Section 24.
   -------------------------------------------------------------------------- */

:root {
	--oo-lcp-title-color: var(--oo-green-dark);                 /* try: var(--oo-link-color) */
	--oo-lcp-code-color:  var(--oo-purple-dark);                /* try: var(--oo-orange-dark) */
	--oo-lcp-title-color-hover: color-mix(in srgb, var(--oo-lcp-title-color) 72%, #000);
}

/* `--oo-lcp-rule` was defined here in rev 25 and REMOVED in rev 27. The same
   hairline is now needed by .questionAnswerBlock in Section 10, so the value
   moved up to the Section 01 token block as `--oo-rule-hairline`. Custom
   properties resolve regardless of source order, so a Section 29 token would
   technically have worked from Section 10 — but naming a shared value after
   one of its two consumers is how tokens rot. Change the hairline in Section
   01, not here. */


/* --------------------------------------------------------------------------
   29.2  The lesson title link
   --------------------------------------------------------------------------
   `.lcp-lesson-list dt a:link` is (0,2,2). Section 21's link rules are all
   (0,1,1), so this wins on specificity alone and does not depend on staying
   below Section 21 in the file. No !important, per the v0.1.1 decision.

   The `dt` in the middle is not redundant even now that the marker class is
   LCP-only: it keeps these rules off any link that ends up in a `<dd>`
   excerpt, which should stay a normal Section 21 body link.

   `:visited` is named alongside `:link` for the reason given in Section 21:
   Astra and Section 21 both set `a:visited` at (0,1,1), and a rule that omitted
   it would leave every already-opened lesson purple — which on a membership
   site means most of the list, for the members who use it most.

   `text-decoration-line: none` is declared here rather than relied upon from
   Section 10, and `text-decoration-color` is declared too rather than merely
   omitted — Section 07 of the project notes: a partial rule invites leaks.
   -------------------------------------------------------------------------- */

.lcp-lesson-list dt a:link,
.lcp-lesson-list dt a:visited {
	color: var(--oo-lcp-title-color);
	text-decoration-line: none;
	text-decoration-color: currentColor;
}

.lcp-lesson-list dt a:is(:hover, :focus, :active) {
	color: var(--oo-lcp-title-color-hover);
	text-decoration-line: underline;
	text-decoration-thickness: 1px;
	text-decoration-color: currentColor;
	text-underline-offset: 0.15em;
}


/* --------------------------------------------------------------------------
   29.3  The helu kaʻina (lesson code)
   --------------------------------------------------------------------------
   `.dpurpletext` in Section 02 would already hold the code at purple by
   specificity (0,1,0 beats inheritance from the <a>, which is not a rule at
   all). It is restated here at (0,2,2) on purpose, so that:

     a) the code colour is controlled by this component's own token and can be
        changed without disturbing the general-purpose `.dpurpletext` utility,
        which is used in post bodies elsewhere; and
     b) the code holds its colour through :hover — otherwise a future rule that
        set a hover colour on the <a> would drag the code along with it and
        collapse the split on hover only, which is a maddening bug to find.

   Scoped to `dt` so that a `.dpurpletext` inside an excerpt (<dd>) is left to
   the Section 02 utility, as before — and scoped to `.lcp-lesson-list` since
   rev 26, so that the hand-authored `.lpurpletext` / `.dpurpletext` codes in
   the class-timetable widget and the grammar glossaries keep answering to the
   Section 02 utilities rather than to this component's token.
   -------------------------------------------------------------------------- */

.lcp-lesson-list dt a .dpurpletext,
.lcp-lesson-list dt a:is(:hover, :focus, :active) .dpurpletext {
	color: var(--oo-lcp-code-color);
	text-decoration-color: currentColor;
}


/* --------------------------------------------------------------------------
   29.4  Row separator and excerpt indent — GENERIC, NOT LCP-SCOPED
   --------------------------------------------------------------------------
   These two stay on `.definitionListBlock` deliberately. In 2015 the hairline
   came from `.post-content dt { border-bottom: 1px solid #999 }` and the dd
   reset was equally generic, so every definition list in post content had them
   — the eight hand-authored blocks included. Narrowing them to
   `.lcp-lesson-list` would not tighten scope, it would strip the separator off
   content that has had it for eleven years.

   The hairline is doing real work in a list this long — without it the excerpt
   above and the title below run together at a glance. If you decide against it,
   delete the border-bottom block; nothing else depends on it.

   The dd reset undoes Astra's `margin-inline-start`, which is the browser
   default for <dd> and was zeroed in 2015. Written as the logical property so
   it stays correct if a page is ever rendered RTL; the physical `margin-left`
   would not be overridden by it in that case.
   -------------------------------------------------------------------------- */

.definitionListBlock > dl > dt {
	border-bottom: 1px solid var(--oo-rule-hairline);
}

.definitionListBlock > dl > dd {
	margin-inline-start: 0;
	margin-left: 0;
}


/* --------------------------------------------------------------------------
   29.5  The <ul> variant — papaheluinoanohie.php
   --------------------------------------------------------------------------
   Added 2026-08-06 (rev 31). This is the template deferred at rev 26 with
   "we'll run across where I used it soon enough". It turned up on
   /coursework-index-by-category/, which runs NINE of these blocks — one per
   course category. The `lcp-lesson-list` marker added to the template as a
   forward hook at rev 26 is already on all nine, so this is CSS only.

   MARKUP — note it is NOT the <dl> shape 29.2-29.4 handle:

       <div class="papaheluinoanohie lcp-lesson-list">
         <ul>
           <li><a href="…">
             <span class="dpurpletext">0401V</span>
             <span>Pronunciation #1: The Alphabet</span>
           </a></li>

   Same two-span link, no <dd> excerpt, no <dt>. That is why none of 29.2-29.4
   reached it and why the page was rendering as stock Astra: disc bullets, every
   link purple and underlined by Section 21, and the 2015 list geometry gone.

   THE 2015 STYLING WAS ENTIRELY INCIDENTAL. There is not one
   `.papaheluinoanohie` rule in the 2015 stylesheet — checked, the selector
   appears zero times. Everything the live page shows comes from generic
   `.post-content ul` / `.post-content li` rules plus the global green `a`.
   Astra has no equivalent for any of them, so all of it had to be restated
   here. Measured on live and reproduced below:

       ul   list-style none, margin-left 20px, padding-left 0,
            line-height 24px, margin-bottom 24px
       li   list-style none, padding-left 12px, margin-bottom 12px
       a    green, code span purple

   ONE DELIBERATE DEPARTURE FROM LIVE: the underline. On live these links are
   underlined at rest, because 2015 underlined body links generally. Kaliko
   asked for this page to match /coursework-by-series/, and there the LCP links
   are NOT underlined at rest and pick up an underline on hover. 29.5 follows
   the coursework-by-series treatment, i.e. 29.2 exactly, because that is what
   was asked for by name. To go back to 2015's always-underlined look, move
   `text-decoration-line: underline` from the hover block into the resting one.

   `li` is NOT given `position: relative` even though live carries it. On live
   that comes from the same generic rule that serves the marker lists in
   Section 09, where it is load-bearing because those have an absolutely
   positioned `::before`. These items have no marker, so it would be a rule
   that does nothing. Add it back if a bullet glyph is ever introduced here.
   -------------------------------------------------------------------------- */

/* The `.entry-content` variant is what actually wins. Astra emits
   `.entry-content ul { margin-left: revert }` at (0,1,1), which ties a bare
   `.lcp-lesson-list ul` and beats it on load order — the same trap Section 09's
   marker lists hit. (0,2,1) settles it. Both selectors are kept so the block
   still looks right if it is ever used outside post content. */

.lcp-lesson-list ul,
.entry-content .lcp-lesson-list ul {
	list-style-type: none;
	list-style-image: none;
	margin-left: 20px;
	padding-left: 0;
	line-height: 24px;
	margin-bottom: 24px;
}

.lcp-lesson-list ul > li,
.entry-content .lcp-lesson-list ul > li {
	list-style-type: none;
	padding-left: 12px;
	margin-bottom: 12px;
	line-height: 24px;
}

/* WEIGHT — a deliberate 2026 departure from 2015 (rev 33, 2026-08-07).
   Live 2015 renders this page's rows at Arial 16px/400, and rev 31 reproduced
   that faithfully. Kaliko asked for it heavier after comparing against the <dl>
   listings on /coursework-by-series/, whose `dt` is 18px/700.

   WHY DEPART. The numeric parity with 2015 was concealing a real loss: Inter
   400 is optically lighter than Arial 400 at the same size, so the page reads
   thinner in 2026 than it did in 2015 despite the numbers matching. The two
   pages are also two views of the same 71 items and want to read as a pair.

   WHY 600 AND NOT 700. 700 would match the `dt` weight, but not its size, so it
   is not real parity either — and it turns all 71 consecutive rows bold, which
   leaves the h3 category headings (25.6px/800) separated by size alone. 600 is
   a distinct Inter SemiBold cut: clearly heavier, still legible as a list.
   Rendered at 400/600/700 on staging and compared before choosing.

   NOT the font-size. Raising 16px to 18px to match `dt` as well was considered
   and rejected — it would lengthen an already long nine-block page by roughly a
   sixth for no gain in scannability. The `dt` is 18px because it has a `<dd>`
   excerpt beneath it to out-weigh; these rows have nothing to separate from.

   Declared on the link rather than the `li` so it cannot reach any non-link
   text, and stated once outside the :link/:visited/:hover split so the weight
   cannot shift under the cursor. It inherits to BOTH spans, so the purple helu
   kaʻina bolds with the green inoaikamu — matching the <dl> variant, where the
   whole `dt` is 700. Contrast is unaffected either way: --oo-green-dark is
   4.63:1 on white at 400 already, and weight only improves legibility. */

.lcp-lesson-list ul li a,
.entry-content .lcp-lesson-list ul li a {
	font-weight: 600;
}

/* Colours come from the 29.1 tokens, so this variant and the <dl> variant can
   never drift apart — change the polarity once and both follow. (0,2,2), which
   clears Section 21's (0,1,1) link rules. */

.lcp-lesson-list ul li a:link,
.lcp-lesson-list ul li a:visited {
	color: var(--oo-lcp-title-color);
	text-decoration-line: none;
	text-decoration-color: currentColor;
}

.lcp-lesson-list ul li a:is(:hover, :focus, :active) {
	color: var(--oo-lcp-title-color-hover);
	text-decoration-line: underline;
	text-decoration-thickness: 1px;
	text-decoration-color: currentColor;
	text-underline-offset: 0.15em;
}

/* The helu kaʻina, restated for the same reason as 29.3: so it answers to this
   component's token rather than the general-purpose `.dpurpletext` utility, and
   so it holds its colour through hover instead of being dragged along with the
   title. */

.lcp-lesson-list ul li a .dpurpletext,
.lcp-lesson-list ul li a:is(:hover, :focus, :active) .dpurpletext {
	color: var(--oo-lcp-code-color);
	text-decoration-color: currentColor;
}

/* ====================== END SECTION 29 ==================================== */


/* ==========================================================================
   SECTION 30 — RELATED POSTS ("curriculum index" treatment)
   --------------------------------------------------------------------------
   RESTORED 2026-08-06 (rev 29) from the CSS Kaliko was handed earlier the
   same day, which was written as "Section 28" and which he renumbered to 30.x
   when he found 28 and 29 already taken. Renumbering redone here identically.
   Full design rationale, the three measured contrast tables, the Customizer
   dependencies and the verification figures are in the project doc
   `related-posts-section30.md` — read that before changing anything below.

   WHY IT NEEDED RESTORING: the theme's style.css was last written
   2026-08-05 11:50 HST, whereas this section was applied and verified on the
   morning of 2026-08-06. The file on disk had reverted to a state predating
   both this section AND the earlier Section 29, and nobody noticed until the
   related-posts block rendered as stock Astra. See "the missing revision"
   note in the project doc.

   SCOPE: the Astra Pro related-posts block below single posts only —
   `.ast-single-related-posts-container`. Nothing here touches blog or
   archive listings.

   WHY THIS EXISTS: Astra ships the block as four narrow columns of centred
   text with a comma-run of categories and tags underneath. On this site the
   related items are lesson pages with long titles ("0403V Pronunciation #3:
   The Glottal Stop"), so at ~160px per column every title shredded into
   three ragged lines and the block read as debris rather than as a next
   step. The treatment here turns it into a curriculum index: a lesson
   numeral in a left rail, the series and format as a quiet eyebrow, the
   title in Vollkorn, one hairline rule per entry. It is the same object a
   student meets in the back of a language textbook.

   TWO COLUMNS COME FROM THE CUSTOMIZER, NOT FROM HERE. Astra Pro's dynamic
   CSS sets `grid-template-columns: repeat(4, 1fr)` on
   `.ast-single-related-posts-container .ast-related-posts-wrapper` — (0,2,0),
   loaded at ~13-14, i.e. AFTER this stylesheet at ~12. Matching that
   selector here would tie on specificity and lose on order, and beating it
   would mean a specificity hack for something that has a proper settings
   home. Set it at:
       Customizer > Post Types > Single Post > Related Posts > Grid Column: 2
   `row-gap` / `column-gap` below are safe to set here because the dynamic
   rule does not touch them and Astra's own `gap: 25px` sits at (0,1,0),
   which this (0,2,0) selector beats on specificity alone. If the block ever
   looks like four columns again, the Customizer setting was lost — not this
   file.

   THE font-size: 0 IS LOAD-BEARING. DO NOT "TIDY" IT.
   Astra's meta markup is:
       <div class="entry-meta">
         <span class="cat-links">…</span>  /  <span class="tags-links">…</span>
       </div>
   The " / " between the spans and the ", " between links are BARE TEXT
   NODES. There is no element to hide them with. Zeroing the font-size on
   the three containers collapses them, and each <a> restores its own size.
   Remove those three declarations and a stray slash and a run of commas
   reappear immediately.

   display: contents ON .entry-meta IS ALSO LOAD-BEARING.
   The eyebrow (categories) has to sit ABOVE the title and the numeral has
   to sit beside both, but in the markup the whole `.entry-meta` div comes
   AFTER the <h3>. `display: contents` dissolves that div so its two spans
   become direct grid items of `.related-entry-header` and can be placed
   independently — which is what buys this layout with no PHP and no
   template override.

   THE NUMERAL IS THE FIRST TAG. This is a genuine assumption: the lesson
   code is first only because numerals sort before letters in the tag list
   ("0401, pronunciation, spelling"). A related post with no numeric tag
   would promote its first topic tag into the rail and it would look wrong
   rather than break. If that ever happens, the durable fix is a check in
   functions.php, not a selector here.

   lnum IS REQUIRED, NOT DECORATIVE. Vollkorn defaults to OLDSTYLE figures:
   without `"lnum" 1` the code renders 0401 with hanging, varied-height
   digits and reads as a typo on a page whose whole subject is precision.
   This is the `lnum` trap noted in heading-font-okina-audit.md, confirmed
   live here. Any future rule that puts Vollkorn near a lesson code needs
   the same two lines.

   COLOUR SCHEME, REVISED 2026-08-06 (rev 30): helu kaʻina deep purple,
   lesson title brand green — the same split as the LCP lesson listings in
   Section 29, so the curriculum reads the same way in both places. This
   REPLACES the original scheme (green numeral / purple title), which was the
   other way round.

   The old warning about not lightening the numeral below a 75% green/white
   mix is retired with it: the numeral is now solid `--oo-purple-dark` at
   13.7:1 on white, and the title is `--oo-green-dark` at 4.63:1, which clears
   AA for normal text at 20px/600.

   STILL TRUE, and the reason no mint background belongs here:
   `--oo-green-dark` on `--oo-bg-mint` measures 4.46:1 and FAILS AA for normal
   text. Now that the TITLE is the green element, that matters more than it
   did — a mint field behind this block would put the largest run of green
   text on the failing pairing.

   RETIRING THIS SECTION: delete the whole block. Nothing else in the file
   depends on it. The Customizer column setting is independent and should
   be reset to 4 by hand if you want Astra's stock layout back.
   ========================================================================== */

/* -- 30.1 The grid --------------------------------------------------------- */

/* (0,2,0) — beats Astra's own `.ast-related-posts-wrapper { gap: 25px }` at
   (0,1,0) on specificity, so this does not depend on load order. */
.ast-single-related-posts-container .ast-related-posts-wrapper {
	row-gap: 26px;
	column-gap: 44px;
}

/* Every lesson post in this set has no featured image, so Astra emits an
   empty `.ast-no-thumb` div that still takes a line box. Collapse it.
   If featured images are ever adopted site-wide, this line is the first
   thing to remove and the layout will need a real image slot. */
.ast-related-post .ast-related-post-featured-section.ast-no-thumb {
	display: none;
}

/* -- 30.2 The entry ------------------------------------------------------- */

/* Border is declared on all four sides then re-declared on top, rather than
   just setting border-top: a partial rule here would let any future Astra
   card styling leak in around the sides. Same reasoning for background,
   radius and shadow — this block is the authority for the entry box, so it
   states what it wants OFF as well as on. */
.ast-related-post {
	border: 0 none;
	border-top: 1px solid var(--oo-rule-light);
	border-radius: 0;
	background: none;
	box-shadow: none;
	padding: 22px 0 26px;
	transition: border-top-color .18s ease;
}

.ast-related-post:hover {
	border-top-color: var(--oo-green-dark);
}

/* -- 30.3 The header grid ------------------------------------------------- */

/* col 1 = numeral rail (auto, sized by the numeral), col 2 = text.
   NOTE the phantom third row: the " / " text node between the two meta
   spans becomes an anonymous grid item once .entry-meta is dissolved, and
   auto-places into an implicit row 3. It measures 0px because font-size is
   0, and this grid deliberately uses NO row-gap — the eyebrow's
   margin-bottom does that job instead — so the phantom row costs nothing.
   Add a row-gap here and you will get unexplained space under every entry. */
.ast-related-post .related-entry-header {
	display: grid;
	grid-template-columns: auto 1fr;
	column-gap: 18px;
	align-items: start;
	font-size: 0;
}

.ast-related-post .entry-meta {
	display: contents;
	font-size: 0;
}

.ast-related-post .entry-meta .ast-taxonomy-container {
	font-size: 0;
}

/* -- 30.4 The lesson numeral (left rail) ---------------------------------- */

.ast-related-post .tags-links {
	grid-area: 1 / 1 / 3 / 2;
}

/* RECOLOURED 2026-08-06 (rev 30). Was a 78%-white mix of --oo-green-dark, with
   the title in purple. That polarity is now INVERTED to match the LCP lesson
   listings on /coursework-by-series/ (Section 29): the helu kaʻina is
   deep purple, the lesson title is brand green. One convention across both
   places a member browses the curriculum.

   The old contrast caveat about the 78% mix no longer applies and has been
   removed from the section header — the numeral is now solid --oo-purple-dark
   at 13.7:1 on white, with no lightening to police.

   Specificity raised to (0,4,1) — see the note in 30.6. It is not strictly
   needed for the numeral, which was already winning, but keeping both halves
   of the pair at the same weight means a future Astra update that reaches one
   cannot silently take only the other and split the colour scheme in half. */

.ast-single-related-posts-container .ast-related-post .tags-links a:link,
.ast-single-related-posts-container .ast-related-post .tags-links a:visited,
.ast-single-related-posts-container .ast-related-post:hover .tags-links a:first-of-type,
.ast-single-related-posts-container .ast-related-post .tags-links a:first-of-type:is(:focus, :active) {
	color: var(--oo-purple-dark);
}

.ast-related-post .tags-links a:first-of-type {
	font-family: Vollkorn, Georgia, serif;
	font-feature-settings: "lnum" 1, "onum" 0;
	font-variant-numeric: lining-nums;
	font-size: 30px;
	font-weight: 600;
	line-height: 1.05;
	letter-spacing: 0;
	text-transform: none;
	text-decoration-line: none;
	text-decoration-color: var(--oo-rule-hairline);
	text-decoration-thickness: 1px;
	text-underline-offset: 0.12em;
	transition: color .18s ease, text-decoration-color .18s ease;
}

/* Hover is driven off the ENTRY, not the link, so pointing anywhere in the row
   underlines the numeral and the title together — they read as one target,
   which is what they are. :focus and :active are on the link itself so keyboard
   users get the same feedback on the element they are actually on. */
.ast-single-related-posts-container .ast-related-post:hover .tags-links a:first-of-type,
.ast-single-related-posts-container .ast-related-post .tags-links a:first-of-type:is(:focus, :active) {
	text-decoration-line: underline;
	text-decoration-color: var(--oo-rule-hairline);
}

/* Topic tags (pronunciation, spelling, syntax…) are hidden rather than
   turned off in the Customizer, because the Customizer switch is all-or-
   nothing and the FIRST tag is the lesson code this layout is built on.
   Tags must stay ENABLED at Post Types > Single Post > Related Posts. */
.ast-related-post .tags-links a:not(:first-of-type) {
	display: none;
}

/* -- 30.5 The eyebrow (series + format) ----------------------------------- */

.ast-related-post .cat-links {
	grid-area: 1 / 2 / 2 / 3;
	margin-bottom: 5px;
}

.ast-related-post .cat-links a {
	font-family: "Inter Tight", Inter, sans-serif;
	font-size: 11px;
	font-weight: 600;
	line-height: 1.4;
	letter-spacing: .1em;
	text-transform: uppercase;
	text-decoration-line: none;
	color: var(--oo-text-gray);
}

.ast-related-post .cat-links a:hover,
.ast-related-post .cat-links a:focus {
	color: var(--oo-green-dark);
}

/* Replaces the collapsed ", " text node. The pseudo-element inherits the
   <a>'s font-size, so it survives the font-size: 0 above. */
.ast-related-post .cat-links a + a::before {
	content: "\00b7";
	margin: 0 6px;
	opacity: .55;
}

/* -- 30.6 The title ------------------------------------------------------- */

/* (0,3,0) — Astra sets line-height and size on `.ast-related-post-title` at
   a specificity this has to clear. Measured before/after: 30px -> 25.6px. */
.ast-single-related-posts-container .ast-related-post .ast-related-post-title {
	grid-area: 2 / 2 / 3 / 3;
	margin: 0;
	font-family: Vollkorn, Georgia, serif;
	font-feature-settings: "lnum" 1, "onum" 0;
	font-variant-numeric: lining-nums;
	font-size: 20px;
	font-weight: 600;
	line-height: 1.28;
	letter-spacing: 0;
	text-align: left;
	text-transform: none;
}

/* NOTE: this is the ONLY heading on the site other than H1 that is set in
   Vollkorn. Measured 2026-08-06: H2, H3 and H4 all compute Inter; only H1
   is Vollkorn. So this is a deliberate departure, not a continuation. To
   fold the block back into the site's actual heading voice, change the two
   font-family lines in 30.4 and 30.6 to "Inter Tight", Inter, sans-serif
   and drop the two font-feature/variant lines with them. */

/* RECOLOURED 2026-08-06 (rev 30): green, to match the lesson titles in the LCP
   listings (Section 29). Paired with the purple helu kaʻina in 30.4.

   SPECIFICITY — THIS IS WHY THE SELECTOR IS SO LONG. The previous rule was
   `.ast-related-post .ast-related-post-title a` at (0,2,1), and it had NEVER
   APPLIED. Astra Pro's dynamic CSS emits

       .ast-related-post-content .entry-header .ast-related-post-title a
           { color: var(--ast-global-color-2) }

   at (0,3,1). Measured on all four entries with none hovered: the title rested
   at #793195 (--ast-global-color-2), not the #4B0A65 the rule asked for — and
   because the old hover rule was also (0,2,1) and also lost, rest and hover
   were IDENTICAL and the hover state did nothing at all. Nobody spotted it
   because the acceptance table checked the title's font, size and line-height
   but not its colour.

   Note this is specificity, not load order: a (0,3,1) selector here would only
   TIE, and Astra Pro's dynamic sheet loads at ~13-14, after this file at ~12,
   so a tie still loses. Hence (0,4,1) — three classes plus a pseudo-class.

   Contrast: --oo-green-dark #0d8800 is 4.63:1 on white. The title is 20px/600,
   which is below the WCAG large-text threshold whether or not 600 counts as
   bold, so it needs the full 4.5:1 — and clears it. The 19px phone size in
   30.7 is the same colour and the same verdict. */

.ast-single-related-posts-container .ast-related-post .ast-related-post-title a:link,
.ast-single-related-posts-container .ast-related-post .ast-related-post-title a:visited {
	color: var(--oo-green-dark);
	text-decoration-line: none;
	text-decoration-color: var(--oo-rule-hairline);
	text-decoration-thickness: 1px;
	text-underline-offset: 0.12em;
}

/* Entry-level hover, link-level focus/active — same reasoning as 30.4, so the
   numeral and the title always underline together. Colour deliberately does NOT
   change on hover: the underline is the whole of the feedback, which keeps the
   two-colour scheme readable in every state. */
.ast-single-related-posts-container .ast-related-post:hover .ast-related-post-title a,
.ast-single-related-posts-container .ast-related-post .ast-related-post-title a:is(:focus, :active) {
	color: var(--oo-green-dark);
	text-decoration-line: underline;
	text-decoration-color: var(--oo-rule-hairline);
}

/* -- 30.7 Phone --------------------------------------------------------- */

/* At 390px Astra drops to one column on its own (its mobile setting), and
   the rail survives at 65px. The only real problem was the eyebrow wrapping
   to two lines — "0800 SERIES · PRACTICE HAʻAWINA" is the longest one on the
   site. Trimming the size and tracking brings it back to one line with room
   to spare. Verified at 390px via the iframe method in
   mobile-viewport-method-and-toggle.md; scrollWidth === clientWidth (373). */
@media (max-width: 600px) {

	.ast-single-related-posts-container .ast-related-posts-wrapper {
		row-gap: 20px;
	}

	.ast-related-post {
		padding: 18px 0 20px;
	}

	.ast-related-post .related-entry-header {
		column-gap: 13px;
	}

	.ast-related-post .tags-links a:first-of-type {
		font-size: 26px;
	}

	.ast-related-post .cat-links a {
		font-size: 10.5px;
		letter-spacing: .06em;
	}

	.ast-single-related-posts-container .ast-related-post .ast-related-post-title {
		font-size: 19px;
	}

	/* Added 2026-08-06 (rev 29). Recorded in related-posts-section30.md as
	   "DELIVERED, NOT COMMITTED" and folded in here while the section was
	   being restored, so it stops living in limbo. Measured at 390px: the
	   heading rendered 23.71px on a 37.94px line (1.6, inherited from the
	   global heading scale) and wrapped to three lines / 114px before the
	   reader reached the first lesson. After: 21px / 26.25px, two lines,
	   53px — 61px given back, and still comfortably larger than the 19px
	   lesson titles below. Desktop untouched. Delete these two declarations
	   to revert. */
	.ast-single-related-posts-container .ast-related-posts-title {
		font-size: 21px;
		line-height: 1.25;
	}
}

/* ===================== END SECTION 30 ==================================== */


/* ==========================================================================
   SECTION 31 — MOBILE HORIZONTAL OVERFLOW: THE CLOCK TABLES
   ==========================================================================
   Committed 2026-08-06 (rev 30). Designed, tested and verified in-browser
   earlier the same day but left uncommitted; the CSS below is the version
   recorded verbatim in `mobile-table-overflow-section31.md`. Read that doc
   before changing anything here — it holds the measurements.

   SCOPE: `table.oo_uaki` only, the MX Time Zone Clocks tables on /calendar/.
   Nothing else on the site is touched.

   THE BLOCKER WAS MUCH SMALLER THAN RECORDED. `go-live-plan.md` called mobile
   overflow "the single largest remaining risk" on the strength of a 557px
   measurement taken while the clocks were BROKEN — each cell then held a blank
   300px default canvas. The clock fix (functions rev 09) brought canvases to
   120px and nobody re-measured. Actual overflow: ~50px at 390px.

     General lesson worth keeping: the number in the blocker outlived the
     condition that produced it by two days. Re-measure before designing
     against a recorded figure.

   THE CLASS TIMETABLE ALREADY FITS. The plan speculated it "may deserve a
   purpose-built narrow layout". Measured at a 390px viewport, all six tables
   on /calendar/: the timetable, the session dates and the conversion table are
   306px each and fit; only the three `table.oo_uaki` are 390px. DO NOT build a
   narrow timetable layout on the strength of that note.

   ROOT CAUSE: each clock table is ONE row of three cells whose min-content
   width is 130px — the 120px canvas plus padding, plus the `04:49:16 AM` label
   that the plugin pins with its own injected
   `.mx-clock-<zone> * { font-size: 16px !important }`. 3 x 130 = 390px, a hard
   floor against a 306-330px column. The table cannot shrink. It can only wrap.

   Shrinking the canvas would not get three across — the floor is set as much
   by the time label as by the clock, and beating that `!important` would need
   one of our own, which architecture rule 2 forbids. Canvas size is the
   plugin's own setting anyway.

   WHY NOT THE FIX THE PLAN SUGGESTED. The plan proposed
   `@media (max-width: 768px) { .entry-content table { display: block;
   overflow-x: auto } }`. Rejected twice over: it makes a row of three clocks
   scroll sideways inside its own box, which is worse for the reader than
   letting them flow onto a second line, and it would apply to three tables
   that are already fine.

   NO `@media` QUERY, DELIBERATELY. `flex-wrap` breaks the row exactly when the
   cells stop fitting, at whatever width that turns out to be. A breakpoint
   would be a guess about a number the browser already knows.

   `flex: 1 1 130px` IS WHAT KEEPS DESKTOP PIXEL-IDENTICAL. Measured at a 988px
   viewport before and after: table 535 x 194, cells 178 / 178 / 178 in both
   cases. The only behaviour this section changes is what happens when the row
   runs out of room.

   `> tbody >` child combinators stop these rules reaching a table nested inside
   a clock table. Nothing nests one today; the combinators make it impossible
   rather than unlikely.

   VERIFIED (iframe method, per mobile-viewport-method-and-toggle.md):
       360px  scrollWidth 343 === clientWidth 343, 0 elements over
       390px  373 === 373
       414px  397 === 397
       988px  973 === 973, cells unchanged from stock

   COSMETIC CONSEQUENCE, ACCEPTED: three clocks wrapping into a 306px column
   give a 2 + 1 rhythm, so each group ends with one clock centred alone. Nine
   clocks read as 2+1, 2+1, 2+1 rather than an even grid, because they live in
   three separate `[mxmtzc_time_zone_clocks]` shortcodes and no CSS can flow
   them together. Fixing that means merging the three shortcodes into one — a
   content change on /calendar/, not a stylesheet change. Not actioned.
   ========================================================================== */

table.oo_uaki,
table.oo_uaki > tbody {
	display: block;
}

table.oo_uaki > tbody > tr {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
}

table.oo_uaki > tbody > tr > td {
	display: block;
	flex: 1 1 130px;
}

/* ===================== END SECTION 31 ==================================== */


/* ==========================================================================
   32. PAGINATION — CENTRED CLUSTER
   ==========================================================================
   Added 2026-08-07 (rev 34), found while auditing /?s=grammar.

   SCOPE: every paginated listing — search results, category and tag archives,
   the blog index. Not search-specific, despite where it was found.

   THE SYMPTOM. On /?s=grammar (34 hits, 3 pages) the numbers `1 2 3` sat left
   of centre while `Next →` was flung to the right margin, with a wide empty
   gap between them. It reads as a broken float, and that is exactly what it
   is.

   THE CAUSE — Astra contradicts itself, in one file, in the same request.
   `astra/inc/dynamic-css/pagination.php` writes the same selector twice:

       line  32-35   '.ast-pagination .next.page-numbers' => float: none
       line 215-220  .ast-pagination .next.page-numbers   { float: right }
                     .ast-pagination .prev.page-numbers   { float: left  }

   Identical specificity (0,2,0), so the later one wins and the element floats.
   Both were confirmed present and in that order in the served
   astra-theme-dynamic-css on staging. The first block is the one that states
   the intent — it is grouped with the pagination *colour* output, which only
   runs when pagination is enabled — so this is not a design choice being
   overridden here, it is Astra's own newer rule losing to its own older one.

   WHY THE FLOAT LOOKS WRONG HERE SPECIFICALLY. `.ast-pagination` is
   `text-align: center` and `.nav-links` is `display: inline-block; width:100%`.
   A floated child leaves the normal flow, so the numbers centre themselves
   inside the *remaining* line box rather than inside the track. The more
   page numbers there are, the further off-centre the cluster drifts.

   THE FIX is to restate Astra's own stated intent for both directions. Same
   selector, same (0,2,0) specificity; this stylesheet loads at ~12 against
   Astra's dynamic CSS at ~3, so it wins on cascade order alone. No
   `!important` (rule 2), no specificity escalation.

   The two padding lines are consequential, not decorative.
   `.ast-pagination-default` zeroes the outer padding on prev/next precisely
   *because* they were floated to the track edges. Once they rejoin the flow
   that zero closes the gap between `3` and `Next →` to nothing, so the
   1.5em from Astra's own `.prev/.next` rule is restated.

   MEASURED AFTER: on /?s=grammar at 1273px the four items span 327–571px
   inside a 29–869px track. Cluster centre 449, track centre 449. Confirmed by
   full-viewport screenshot as well as by getBoundingClientRect, per the
   standing warning about stale property reads.

   IF ASTRA EVER FIXES THIS, this section becomes a harmless no-op rather
   than a conflict — it would be restating a value Astra already sets. Worth
   re-reading after a major Astra update all the same.
   ========================================================================== */

.ast-pagination .prev.page-numbers,
.ast-pagination .next.page-numbers {
	float: none;
}

.ast-pagination-default .ast-pagination .next.page-numbers {
	padding-right: 1.5em;
}

.ast-pagination-default .ast-pagination .prev.page-numbers {
	padding-left: 1.5em;
}

/* ===================== END SECTION 32 ==================================== */


/* End Kaliko Important CSS as OleloOnline_2026 Child */
