/* ---- 00-tokens.css ---- */
/* ==========================================================================
   00-tokens.css -- the only file in the rail that may declare a raw value.
   ==========================================================================

   Every value below was measured out of the corpus, not chosen. The counts in
   the comments are occurrences across the shipped stylesheets
   (assets/legacy-theme, build/wordpress_pages/css) plus staticsite/templates
   and scripts/*.py, taken 2026-08-03. Where a plan or a memory disagrees with
   a count here, the count is the authority -- see "Corrections" at the bottom.

   Two tiers, and the split is load-bearing:

     RAMPS      --color-ink-600, --font-size-400, ...   raw scale values
     SEMANTICS  --color-surface, --color-link, ...      what a declaration uses

   Declarations in 10-* through 90-* must reference a SEMANTIC token and never
   a ramp token or a literal. That is what makes a future dark mode ~20 variable
   redefinitions instead of a corpus-wide search. It is also why this file is
   the whole of phase 0a: it declares custom properties and nothing else, so
   adding it to every page changes no rendered pixel. Custom properties on
   :root are inert until something references them.

   No @layer anywhere in this rail. All six inherited Twenty Eleven stylesheets
   are unlayered, and unlayered CSS beats layered CSS regardless of source
   order -- layering here would lose every conflict it was added to win.
   Order plus scoping is the mechanism instead. */

:root {
  /* --- ink: neutrals -----------------------------------------------------
     The Tailwind slate ramp, four rungs of which the corpus already uses:
     #64748b (17), #475569 (9), #e2e8f0 (8), #0f172a (6). The remaining rungs
     are the canonical values from that same ramp, so nothing here is invented.

     A parallel Tailwind *gray* ramp is also in use -- #1f2937 (41), #111827
     (7), #e5e7eb (6), #4b5563 (6), #6b7280 (6) -- and a third flat-UI family,
     #2c3e50 (61) and #7f8c8d (11). Those are not given tokens: converging them
     onto slate is the point. Their nearest rungs are noted per line. */
  --color-ink-50:  #f8fafc;
  --color-ink-100: #f1f5f9;
  --color-ink-200: #e2e8f0;  /* absorbs #e5e7eb, #e0e0e0, #e2e2e2 */
  --color-ink-300: #cbd5e1;  /* absorbs #ccc, #d3d3d3 */
  --color-ink-400: #94a3b8;  /* absorbs #bbb, #95a5a6 */
  --color-ink-500: #64748b;  /* absorbs #7f8c8d, #6b7280, #888 */
  --color-ink-600: #475569;  /* absorbs #4b5563, #666 */
  --color-ink-700: #334155;  /* absorbs #555, #373737 */
  --color-ink-800: #1e293b;  /* absorbs #2c3e50, #1f2937, #34495e */
  --color-ink-900: #0f172a;  /* absorbs #111827, #222, #252525 */
  --color-ink-950: #020617;  /* absorbs #111, #0a0a0a */

  /* --- brand: four blues, because the site has four ----------------------
     Kept as four distinct tokens on purpose. Collapsing them is a visual
     decision for a later phase; doing it here would repaint the site under
     cover of a change advertised as inert.

       #024985 (1)   legal banner background. 9.16:1 on white.
       #0073aa (4)   templates only, never in a stylesheet.
       #1982d1 (14)  the inherited Twenty Eleven link colour -- what a visitor
                     actually sees on chrome links today.
       #3498db (82)  the flat-UI blue, and the most-used blue on the site by a
                     wide margin; it dominates generated content.
       #a5d8ff (1)   the legal banner's link, on the 800 background. */
  --color-brand-800: #024985;
  --color-brand-600: #0073aa;
  --color-brand-500: #1982d1;
  --color-brand-400: #3498db;
  --color-brand-200: #a5d8ff;

  /* --- accents -----------------------------------------------------------
     #f16521 is the simple-banner plugin's configured link colour, emitted by
     partials/shared_chrome_styles.html.j2:3 -- and overridden inline on the
     one anchor it applies to, on every page, for as long as the markup has
     existed. It renders nowhere. Kept as a token because it is still the
     site's one warm accent and a later phase may want it somewhere it can
     pass contrast; see --color-banner-link for why that place is not the
     banner. */
  --color-accent-500: #f16521;
  --color-teal-700:   #0f766e;  /* 19 uses; the site's "positive/settled" tone */

  /* --- status ------------------------------------------------------------
     Backgrounds are what the corpus actually carries; foregrounds are the
     matched rung from the same family so a badge has a legible pair. */
  --color-danger-100: #fee2e2;
  --color-danger-200: #f8d7da;
  --color-danger-700: #b91c1c;
  --color-warning-100: #fff3cd;
  --color-warning-200: #fff9c0;
  --color-warning-800: #854d0e;
  --color-info-50:  #f8fbff;   /* the forum callout's tint; barely off white */
  --color-info-100: #e0f2fe;
  --color-info-200: #dbeafe;
  --color-info-800: #075985;

  --color-white: #ffffff;

  /* --- type --------------------------------------------------------------
     The genuinely broken axis: 17 distinct sizes with no ratio between them.
     Eight steps on 1.2 from a 16px base. Rem, so a reader's browser setting
     still scales the site. */
  --font-size-100: 0.694rem;  /* 11.1px */
  --font-size-200: 0.833rem;  /* 13.3px */
  --font-size-300: 1rem;      /* 16px -- base */
  --font-size-400: 1.2rem;    /* 19.2px */
  --font-size-500: 1.44rem;   /* 23.0px */
  --font-size-600: 1.728rem;  /* 27.6px */
  --font-size-700: 2.074rem;  /* 33.2px */
  --font-size-800: 2.488rem;  /* 39.8px */

  --line-height-tight: 1.25;
  --line-height-snug: 1.4;
  --line-height-normal: 1.6;

  --font-weight-normal: 400;
  --font-weight-medium: 500;
  --font-weight-bold: 700;

  /* Matches what the inherited theme resolves to; not a font change. */
  --font-family-body: "Helvetica Neue", Helvetica, Arial, sans-serif;
  --font-family-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

  /* --- space -------------------------------------------------------------
     The corpus is already effectively on a 4px grid: 127 of ~148 spacing
     declarations land on a multiple of 4. This is a snap-to-grid, not a
     new system. */
  --space-0: 0;
  --space-1: 0.25rem;  /* 4px  */
  --space-2: 0.5rem;   /* 8px  */
  --space-3: 0.75rem;  /* 12px */
  --space-4: 1rem;     /* 16px */
  --space-5: 1.5rem;   /* 24px */
  --space-6: 2rem;     /* 32px */
  --space-7: 3rem;     /* 48px */
  --space-8: 4rem;     /* 64px */

  /* --- shape -------------------------------------------------------------- */
  --radius-sm: 3px;
  --radius-md: 6px;
  --radius-lg: 10px;
  --radius-pill: 999px;

  --border-width: 1px;
  --border-width-thick: 4px;  /* the accent rule on a left-ruled notice */

  --shadow-sm: 0 1px 2px rgb(15 23 42 / 0.06);
  --shadow-md: 0 2px 8px rgb(15 23 42 / 0.08);

  /* --- controls -----------------------------------------------------------
     The minimum box a finger can reliably hit. 44px is Apple's HIG figure and
     WCAG 2.5.5 (AAA); WCAG 2.5.8 (AA) would allow 24. This is the site's bar
     because the phone is the majority viewport here, and it has to match
     TOUCH_TARGET_MIN_PX in scripts/static_layout_qa.mjs -- the gate that
     measures it. A token rather than a literal so the two can only ever be
     changed together, on purpose.

     --dot-size is the visible part of a carousel dot, which stays small while
     its hit box does not. See 40-components/50-touch-targets.css. */
  --touch-target-min: 44px;
  --dot-size: 10px;

  /* --- semantic aliases ---------------------------------------------------
     This block is the dark-mode surface area. Roughly twenty names; a theme
     redefines these and touches nothing else. Declarations use only these. */
  --color-surface:        var(--color-white);
  --color-surface-raised: var(--color-ink-50);
  --color-surface-sunken: var(--color-ink-100);
  --color-border:         var(--color-ink-200);
  --color-border-strong:  var(--color-ink-300);

  --color-text:           var(--color-ink-800);
  --color-text-muted:     var(--color-ink-500);
  --color-text-inverse:   var(--color-white);
  --color-heading:        var(--color-ink-900);

  --color-link:           var(--color-brand-500);
  --color-link-hover:     var(--color-brand-800);
  --color-link-visited:   var(--color-brand-600);

  /* A bordered notice inside body copy -- the forum callout today, and the
     shape any "here is a related thing" box should take. */
  --color-callout-surface: var(--color-info-50);
  --color-callout-border:  var(--color-info-200);

  /* An advisory at the top of a case page -- the rehearing note today. Warmer
     than a callout on purpose: a callout points sideways, a notice qualifies
     what you are about to read. --color-notice-rule is the accent bar on the
     left-ruled variant (the consolidated-dockets banner), which takes its
     surface from the callout tokens above rather than the warning family. */
  --color-notice-surface: var(--color-warning-100);
  --color-notice-border:  var(--color-warning-200);
  --color-notice-text:    var(--color-warning-800);
  --color-notice-rule:    var(--color-brand-500);

  --color-banner-bg:      var(--color-brand-800);
  /* Not --color-accent-500. #f16521 on #024985 is 2.79:1, well under AA, and
     the markup has always overridden it inline with this light blue (6.7:1).
     The rendered value is the correct one; the token was describing a colour
     no visitor has ever seen. */
  --color-banner-link:    var(--color-brand-200);

  --font-size-body:  var(--font-size-300);
  --font-size-small: var(--font-size-200);
  --font-size-lead:  var(--font-size-400);  /* one step up: widget and module titles */
  --line-height-body: var(--line-height-normal);

  /* --- layout ------------------------------------------------------------- */
  --container-base: 1000px;   /* the header logo's intrinsic width */
  --container-wide: 1200px;
  --container-prose: 68ch;
  --container-media: 960px;   /* the case video's measure, on 427 case pages */
  --gutter: var(--space-5);

  /* --- breakpoints --------------------------------------------------------
     Recorded here for reference only. Custom properties CANNOT be used in a
     media query condition -- `@media (min-width: var(--bp-md))` does not work
     in any browser. Media queries in this rail hard-code these three values
     and are min-width only; a max-width query is a review failure. */
  --breakpoint-sm: 600px;
  --breakpoint-md: 900px;
  --breakpoint-lg: 1200px;
}

/* --- Corrections to the design brief ---------------------------------------
   Two premises in the W4 plan did not survive measurement, and the tokens
   above follow the measurement:

   1. "--color-brand-500: #0073aa (existing link color)". #0073aa appears four
      times in the entire project and never inside a stylesheet. The colour a
      visitor sees on a chrome link is #1982d1 (Twenty Eleven's default), and
      the most-used blue anywhere is #3498db at 82 occurrences. #0073aa is
      kept as --color-brand-600 rather than promoted to the link role.

   2. "retiring the parallel flat-UI family: #2c3e50 -> ink-800, #7f8c8d ->
      ink-500". Correct as a direction, but the family is far larger in
      templates than in CSS -- #2c3e50 is 61 occurrences, 59 of them in
      templates and Python, i.e. inline style attributes rather than
      stylesheets. Retiring it is a phase-2 markup job, not a stylesheet job.
   -------------------------------------------------------------------------- */

/* ---- 10-reset.css ---- */
/* ==========================================================================
   10-reset.css -- SCOPED normalisation. Empty until phase 2.
   ==========================================================================

   Reserved deliberately rather than filled, because a reset is the one thing
   in this rail that cannot ship inert: it changes rendering by definition, and
   phase 0a's acceptance test is that the rendered corpus differs by exactly
   one <link> per page.

   When it is filled, the binding constraint is: no global `* { }` rule, ever.
   The dashboard already carries `* { margin:0; padding:0; box-sizing:border-box }`
   and it leaks onto site chrome -- that leak is one of the defects phase 1
   exists to fix, so reintroducing it here at corpus scale would be a
   regression dressed as a foundation. Anything normalised here is scoped under
   `.azhoa`, applied by the template that opts in.

   The markup contract that governs this file (pinned by
   tests/staticsite/test_design_system_assets.py):

     - may add ancestors and classes
     - must not change the element {% block content %} renders into
     - must not constrain content width without an explicit opt-in class
     - must not introduce a global reset

   The dead Gutenberg `max-width: none !important` override in
   azhoawatch_wordpress_creator.py was an earlier attempt to defeat exactly
   such an ancestor. It is evidence the contract is needed, not decoration. */

/* ---- 20-typography.css ---- */
/* ==========================================================================
   20-typography.css -- type scale application. Empty until phase 2.
   ==========================================================================

   Holds the rules that point headings, body copy and small print at
   --font-size-* and --line-height-*. Empty in phase 0a because applying the
   scale changes rendering, and 0a must be provably inert.

   Constraint when filled: reference only the semantic aliases
   (--font-size-body, --font-size-small, --line-height-body) or the numbered
   ramp; never a literal px or rem value. The whole reason the ramp exists is
   that the corpus currently carries 17 distinct font sizes with no ratio
   between them, and a literal here would make it 18. */

/* ---- 30-layout.css ---- */
/* ==========================================================================
   30-layout.css -- page shell, containers, grid.
   ==========================================================================

   Phase 2 moved the 17 footer/banner inline style attributes here, out of
   partials/colophon.html.j2 (extracted from both base templates, which carried
   byte-identical copies), partials/legal_banner.html.j2 and the two bases'
   hidden second-banner shell. Those attributes rendered on all 18,335 pages,
   so this file is roughly 70% of the corpus's inline-style debt for four
   template edits.

   Per-record inline values -- status colours, bar widths -- stay inline. Those
   are data, not presentation debt, and hoisting them here would require a
   class per value.

   Media queries here are min-width only, hard-coding 600px / 900px / 1200px
   (a custom property cannot be used in a media query condition). A max-width
   query is a review failure. */

/* Hub page heading -- the <h1> partials/page_heading.html.j2 supplies to the
   ten hub routes whose generated fragment has no title of its own.

   Spacing only. The type comes from Twenty Eleven's .entry-title, so this
   heading reads identically to a singular post's. A class, not an element or
   id selector, because /, /about/ and /dashboard/ open their fragments with an
   inline `* { margin: 0; padding: 0; box-sizing: border-box }` reset: that
   block sits in the body and therefore wins on source order against anything
   in <head> at equal specificity, but the universal selector has specificity
   zero, so one class beats it either way. */
.azhoa-page-heading {
  margin: 0 0 var(--space-5, 1.5rem);
}


/* --------------------------------------------------------------------------
   Colophon (partials/colophon.html.j2)
   --------------------------------------------------------------------------
   Twenty Eleven styles #site-generator with an id selector
   (twentyeleven/style.css:2359-2377), which is why these are id selectors too:
   they must be able to tie on specificity and win on source order, the same
   mechanism partials/design_system.html.j2 relies on everywhere. The inline
   attributes these replace were doing exactly that with specificity 1,0,0,0.

   The values snap onto the token scales rather than carrying the previous
   literals across, which is the point of the hoist and does move a few pixels:

     color        #555 -> ink-700, #666 -> ink-600. Slightly darker and cooler,
                  and better contrast on the theme's #f9f9f9 footer band
                  (7.4:1 -> 10.4:1 and 5.6:1 -> 7.5:1).
     font-size    14px -> --font-size-small (13.3px). 14px is not a step on the
                  1.2 ratio; collapsing the corpus's 17 arbitrary sizes onto 8
                  steps is what the scale exists for.
     padding      20px 16px -> --space-5 --space-4 (24px 16px). The 4px grid.
     margin       8px -> --space-2, exact.
     link colour  #0073aa -> --color-brand-600, exact.

   Nothing else changes: text-align, the 1100px measure and the theme's bold
   link weight are all as they were. */
#site-generator {
  color: var(--color-ink-700);
  font-size: var(--font-size-small);
  line-height: var(--line-height-normal);
  padding: var(--space-5) var(--space-4);
  text-align: center;
}

/* Theme rule is `#site-generator a { color: #555; font-weight: bold }`. Only
   the colour and underline were overridden inline, so the bold is inherited
   deliberately and stays. */
#site-generator a {
  color: var(--color-brand-600);
  text-decoration: underline;
}

/* Deliberately not --container-base (1000px, the header logo's intrinsic
   width). 1100px is what the footer has always been, and reconciling the
   footer's measure with the header's is a visual decision that belongs in the
   phase that makes it on purpose -- not smuggled in under a change advertised
   as an inline-style hoist. */
.azhoa-colophon__inner {
  margin: 0 auto;
  max-width: 1100px;
}

.azhoa-colophon__line {
  margin-bottom: var(--space-2);
}

.azhoa-colophon__legal {
  color: var(--color-ink-600);
  margin-top: var(--space-2);
}

/* --------------------------------------------------------------------------
   Legal banner (partials/legal_banner.html.j2)
   --------------------------------------------------------------------------
   partials/shared_chrome_styles.html.j2:3 sets this anchor to the plugin's
   configured #f16521 at specificity 0,3,0. This rule ties and wins on source
   order, which is the same thing the inline attribute was doing -- see
   --color-banner-link in 00-tokens.css for why the plugin's value is the wrong
   one. */
.simple-banner .simple-banner-text a {
  color: var(--color-banner-link);
  text-decoration: underline;
}

/* The second banner shell both bases emit after the Facebook SDK: captured
   chrome from the simple-banner plugin's slot 1, always empty, always hidden.
   simple-banner.css sets `.simple-banner { display: block }` at 0,1,0; two
   classes on one element beat it without needing the `!important` the inline
   attribute carried. The real banner is a `.simple-banner-text` *inside* a
   `.simple-banner`, never both on one element, so it is not matched here. */
.simple-banner.simple-banner-text {
  display: none;
}


/* --------------------------------------------------------------------------
   Main menu touch targets
   --------------------------------------------------------------------------
   The header nav is site chrome, so it lives here rather than in
   40-components/50-touch-targets.css, which owns the rest of phase 5's touch
   work.

   Twenty Eleven sets `#access a { line-height: 3.333em; padding: 0 1.2125em }`
   (twentyeleven/style.css), which lands at exactly 40px -- four short of
   --touch-target-min, on every page of the site, for all twelve menu items.
   That specificity is 0,1,0,1, so a class cannot reach it; `#access li a` ties
   on the id and wins on the element, without raising the id count.

   min-height rather than a taller line-height: the line box is what centres
   the label, and changing it moves the text off centre. */
#access li a {
  align-items: center;
  display: flex;
  min-height: var(--touch-target-min);
}

/* ---- 40-components/10-forum-callout.css ---- */
/* Forum callout -- partials/entry_post.html.j2
   ==========================================================================
   The "Community Discussion" / "Community Update" box under a post's content.
   708 pages carry it, and both branches of the template's conditional carried
   the same three inline style attributes, so a change to one was a change
   somebody had to remember to make twice.

   Ours, not captured chrome, which is why it tokenises. The Facebook comments
   widget a few lines above it in the same template does not, and stays inline:
   it is a replica of a WordPress plugin's output, its own `<style>` block
   depends on `!important` to beat the Facebook SDK's inline iframe sizing, and
   this directory forbids `!important` for good reason. Redesigning a widget we
   do not own is not what an extraction pass is for.

   Values snap onto the scales: 18px margin -> --space-4, 12px 14px padding ->
   --space-3 (the 4px grid does not have a 14), 6px -> --space-2, 8px radius ->
   --radius-md, font-weight 600 -> --font-weight-bold. */
.oah-forum-discuss-box {
  background: var(--color-callout-surface);
  border: var(--border-width) solid var(--color-callout-border);
  border-radius: var(--radius-md);
  margin: var(--space-4) 0;
  padding: var(--space-3);
}

.oah-forum-discuss-box > strong {
  display: block;
  margin-bottom: var(--space-2);
}

.oah-forum-discuss-box a {
  font-weight: var(--font-weight-bold);
}

/* ---- 40-components/20-embeds.css ---- */
/* Embeds -- the decision PDF viewer, the case video, the case podcast
   ==========================================================================
   Three components, one origin: scripts/azhoawatch_wordpress_publisher.py's
   compose_content and scripts/generate_oah_static_export.py's
   render_decision_section, both of which run on every static build via
   build_case_records.

   These three carried 2,524 of the 2,529 inline style attributes in the 428
   OAH fragments -- every one of them a repeated literal, none of them per-
   record data. That distinction is what makes them extractable: a status
   colour or a bar width computed per record stays inline, because hoisting it
   would need a class per value. A border that is byte-identical on 1,245
   iframes is presentation debt.

   The leverage is much larger than the fragment count suggests. A fragment's
   content is re-rendered in full on every archive page that lists the post --
   its own page, plus each tag, category and author archive -- so 2,524
   attributes at the source were producing roughly 49,000 across the corpus,
   about a 20:1 multiplier. That is why this file is worth more than its size.

   Transition note: adding the class is inert on already-built pages. An inline
   style attribute has specificity 1,0,0,0 and beats every rule here, so a page
   that still carries the attribute keeps its exact previous appearance and a
   page regenerated without it picks these up. The corpus may be mixed between
   a producer change and the next regeneration without any page rendering
   wrong in the interval.

   Value shifts, stated rather than buried -- these are not all exact:

     border colour  #d1d5db -> --color-border-strong (ink-300, #cbd5e1). The
                    gray-300 to slate-300 convergence 00-tokens.css exists to
                    make. Marginally cooler; both are hairlines on white.
     radius         8px  -> --radius-md  (6px), 2px tighter.
                    12px -> --radius-lg (10px), 2px tighter.
     margin-bottom  0.75rem -> --space-3 (0.75rem), exact.
     max-width      960px -> --container-media, exact; the literal moved to
                    00-tokens.css rather than changing.

   aspect-ratio carries no token because a ratio is not a design scale value.
   16/9 is the video's intrinsic shape, not a choice this rail should own. */

/* The decision-document viewer. `height: auto` is load-bearing: the iframe
   carries a `height="600"` HTML attribute, and without this the attribute
   wins and the aspect ratio is ignored. Same shape as the video below. */
.oah-doc-viewer {
  border: var(--border-width) solid var(--color-border-strong);
  border-radius: var(--radius-md);
  margin-bottom: var(--space-3);
}

/* Case video. The wrapper already had this class in the markup; it just had
   no rule, so its measure lived inline. */
.case-video-embed {
  max-width: var(--container-media);
}

.case-video-embed iframe {
  aspect-ratio: 16 / 9;
  border: 0;
  height: auto;   /* beats the iframe's height="540" attribute */
  width: 100%;
}

/* Case podcast episode. */
.oah-audio-embed {
  border-radius: var(--radius-lg);
}

/* ---- 40-components/30-facebook-comments.css ---- */
/* Facebook comments box -- the WP-Devart plugin's markup, reproduced
   ==========================================================================
   partials/entry_post.html.j2 renders a byte-for-byte replica of what the
   "WP Facebook Comments" plugin emitted, so the static pages keep the widget
   the live site had. Three of its attributes were inline, on every one of the
   3,284 pages that template renders: 9,852 attributes, the largest single
   remaining block after the case embeds.

   Unlike the embeds there is no archive multiplier here -- this is page
   chrome, not post content, so archives render entry_archive.html.j2 and
   never repeat it. 3,284 pages, 3 attributes, exactly 9,852. That makes it
   the cleanest measurement in the extraction and the easiest to verify.

   Value shifts, stated rather than buried:

     width 100%      -> unchanged.
     text-align left -> unchanged.
     display block   -> unchanged, and stays on the SDK's own .fb-comments
                        class, which the markup already carries.
     padding 10px    -> --space-3 (12px), +2px. 10px is off the 4px grid the
                        rest of the site sits on; this is the snap.
     font-size 20px  -> --font-size-lead (--font-size-400, 1.2rem = 19.2px),
                        0.8px smaller and now on the 1.2 type ratio.
     font-family     -> --font-family-body. Same four families; the plugin put
                        Arial first, the site puts Helvetica Neue first.
     color #000000   -> --color-heading (ink-900, #0f172a). Pure black was the
                        plugin's, not the site's; every other heading here is
                        already this near-black slate.

   Two things stay exactly as they are, deliberately:

   1. The `<style>` block in the template. It carries `!important` (the plugin
      forces the FB iframe to full width), which this directory forbids, and it
      is a <style> tag rather than a style attribute so it never counted toward
      the inline debt. Moving it here would trade a rule nobody has to think
      about for a rule that violates the file's own contract.

   2. `#wpdevar_comment_1`. That id is what the template's own <style> block
      targets, and it is part of the plugin replica. The class is added
      alongside it so the rules below can scope on a class per this directory's
      contract, without changing what the id-based rule matches.

   .fb-comments-title is a new class rather than a bare `span` selector: the
   Facebook SDK injects its own markup into .fb-comments at runtime, and a
   `.fb-comments-box span` rule would put 20px Arial on whatever it injects. */

.fb-comments-box {
  text-align: left;
  width: 100%;
}

.fb-comments-box .fb-comments-title {
  color: var(--color-heading);
  font-family: var(--font-family-body);
  font-size: var(--font-size-lead);
  padding: var(--space-3);
}

.fb-comments-box .fb-comments {
  display: block;
}

/* ---- 40-components/40-case-notices.css ---- */
/* Case notices -- the two advisories that open a decision page
   ==========================================================================
   Both are emitted by scripts/azhoawatch_wordpress_publisher.py's
   compose_content: the rehearing advisory (`:2273`, inside `if rehearing:`)
   and the consolidated-dockets banner (consolidated_dockets_banner, `:2251`).
   They are the last two live producers of inline style attributes in case
   content, which is what makes this file the closing move of the extraction
   rather than another slice of it.

   475 corpus attributes -- 441 rehearing, 34 consolidated -- and, as with the
   embeds, most of that is the archive multiplier rather than the fragment
   count: a fragment's content is re-rendered in full on its own page and on
   every tag, category and author archive that lists it.

   Both are ours, not captured plugin chrome, so both tokenise cleanly. What
   this file does NOT touch is the other seven `#fff3cd` sites in scripts/ --
   azhoawatch_wordpress_creator.py, oah_case_analysis.py,
   generate_attorney_posts.py. Every one of those is inside a `<style>` block
   or a JS assignment, not a style attribute, so none counted toward the debt
   and none is in scope here.

   Value shifts, stated rather than buried:

     rehearing background  #fff3cd -> --color-notice-surface (warning-100).
                           Exact; the token was seeded from this very value.
     rehearing border      #ffeeba -> --color-notice-border (warning-200,
                           #fff9c0). A touch more yellow, a touch less tan.
     rehearing text        #856404 -> --color-notice-text (warning-800,
                           #854d0e). Same brown to within a hair.
     rehearing padding     15px -> --space-4 (16px), +1px onto the 4px grid.
     rehearing radius      8px  -> --radius-md (6px), 2px tighter. Same call
                           20-embeds.css made for the doc viewer's 8px.
     rehearing margin      20px -> --space-4 (16px), -4px. 20 is on the 4px
                           grid but not on the spacing scale, which steps
                           16 -> 24. Rounding down matches the consolidated
                           banner exactly, so two notices stacked at the top
                           of one page now share a rhythm instead of
                           disagreeing by 4px.

     consolidated surface  #f0f4ff -> --color-callout-surface (info-50,
                           #f8fbff). The lightest shift in the file and the
                           most deliberate: this is the "here is a related
                           thing" box the callout tokens were named for, and
                           it should look like the forum callout, because it
                           is the same kind of object.
     consolidated rule     #4a6fa5 -> --color-notice-rule (brand-500,
                           #1982d1). Brighter and more saturated. #4a6fa5 is
                           a one-off muted blue that appears nowhere else on
                           the site; brand-500 is the blue a visitor already
                           sees on every chrome link.
     consolidated padding  12px -> --space-3, exact.
     consolidated margin   16px 0 -> --space-4 0, exact.

   Transition note, same as 20-embeds.css: adding a class is inert on pages
   that already carry the attribute. Inline style has specificity 1,0,0,0 and
   beats everything here, so the corpus may sit mixed between this change and
   the next regeneration without any page rendering wrong in the interval. */

/* The rehearing advisory. Sits above the case summary on decision pages whose
   tracker row carries rehearing=yes. */
.oah-rehearing-notice {
  background-color: var(--color-notice-surface);
  border: var(--border-width) solid var(--color-notice-border);
  border-radius: var(--radius-md);
  color: var(--color-notice-text);
  margin-bottom: var(--space-4);
  padding: var(--space-4);
}

/* The consolidated-dockets banner. Left-ruled rather than fully bordered,
   which is what distinguishes it from the forum callout it otherwise
   matches. */
.oah-consolidated-banner {
  background: var(--color-callout-surface);
  border-left: var(--border-width-thick) solid var(--color-notice-rule);
  margin: var(--space-4) 0;
  padding: var(--space-3);
}

/* ---- 40-components/50-touch-targets.css ---- */
/* Touch targets — phase 5, tranche A.
 *
 * scripts/static_layout_qa.mjs measures every control on the phone viewport and
 * scores anything under --touch-target-min. Across the 19 QA pages it found
 * 1,394 undersized targets over 45 distinct selectors. This file takes the ones
 * that can reach 44px without changing what the page is; the rest are recorded
 * at the bottom with the reason they stay.
 *
 * Two things govern how these rules are written.
 *
 * Cascade. Most of these controls are styled from a <style> block that a
 * generator script emits into the page body, which is *after* the bundle link
 * in the head. At equal specificity the page block wins, so every rule here
 * that overrides an existing declaration adds an element to the selector --
 * `button.carousel-dot` (0,0,1,1) beats `.carousel-dot` (0,0,1,0) wherever it
 * sits in the document. Where nothing styles the target today (the docket table
 * has no `td a` rule at all) the plain component selector is enough.
 *
 * Mobile-first. The phone is the base and any relaxation is a min-width query,
 * never max-width. Only the docket table needs one: 44px rows are right on a
 * phone and wrong on a 1440px table of 200 dockets.
 *
 * Sizing uses min-height with inline-flex rather than padding. Padding has to
 * be computed against a line-height nobody here controls, and gets it wrong the
 * moment a font size changes; min-height states the intent and centring the
 * text is one more declaration.
 */

/* --- the docket table ------------------------------------------------------
 * 727 of the 1,394 findings, more than every other selector combined. The rows
 * are injected by JS into an empty tbody, so these anchors exist only after
 * scripting -- which is why they never showed up in a markup grep and why the
 * browser-driven QA harness is what found them.
 *
 * scripts/court_case_creator.py:2379 sets the cell padding and nothing sets
 * anything on the anchor, so no override is needed here. */
.ccx-docket-table td a {
  align-items: center;
  display: inline-flex;
  min-height: var(--touch-target-min);
}

@media (min-width: 600px) {
  /* A pointer does not need the row height, and 200 dockets at 65px a row is a
     worse table than 200 at 36px. */
  .ccx-docket-table td a {
    display: inline;
    min-height: 0;
  }
}

/* --- filter and pagination buttons -----------------------------------------
 * Styled in scripts/generate_attorney_posts.py (the two filters) and in the
 * association directory's own block. All three are already close -- 31 to 37px
 * -- so this is a padding correction, not a redesign. */
button.violation-filter,
button.issue-filter,
#association-card-pagination > button {
  min-height: var(--touch-target-min);
}

/* --- carousel dots ---------------------------------------------------------
 * The worst target on the site at 10x10, and the one that cannot simply grow:
 * a 44px dot is not a dot.
 *
 * So the hit box grows and the visible dot does not. content-box sizing keeps
 * width/height describing the dot itself, the padding carries the box out to
 * 44px, and background-clip stops the fill from following it. The border radius
 * of an inner box is reduced by the padding, so 50% on the padding box still
 * lands as 50% on the content box -- the dot stays round.
 *
 * The existing rule is .carousel-dot in scripts/oah_case_analysis.py:5796, so
 * these selectors carry the element to win regardless of document order. */
button.carousel-dot {
  background-clip: content-box;
  box-sizing: content-box;
  height: var(--dot-size);
  padding: calc((var(--touch-target-min) - var(--dot-size)) / 2);
  width: var(--dot-size);
}

button.carousel-dot.active {
  /* The active dot is a 30x10 lozenge rather than a circle. Same treatment,
     wider content box. */
  width: calc(var(--dot-size) * 3);
}

button.carousel-nav {
  min-height: var(--touch-target-min);
  min-width: var(--touch-target-min);
}

/* --- disclosure summaries --------------------------------------------------
 * A <summary> is a real control and reads as one; at 26px it is also the
 * easiest thing on the page to miss. */
details.azcc-filings-more > summary,
details.directory-crawlable-summary > summary,
#faq > details > summary {
  align-items: center;
  display: flex;
  min-height: var(--touch-target-min);
}

/* --- list and card links ---------------------------------------------------
 * Each of these is the whole row or the whole card title -- a link the visitor
 * is meant to tap, not read past. They are between 22px and 38px today. */
a.case-link,
a.entity-card-name,
li.case-item > a,
.association-resource-links > a,
.azhoa-docket-download-list > a,
.oah-forum-discuss-box > a,
.case-nav a,
a.to-top {
  align-items: center;
  display: inline-flex;
  min-height: var(--touch-target-min);
}

/* --- post-to-post navigation -----------------------------------------------
 * The pagination the plan names. Twenty Eleven gives these anchors nothing but
 * a font size, so they inherit the 14px line box. */
#nav-single .nav-previous a,
#nav-single .nav-next a,
#nav-below .nav-previous a,
#nav-below .nav-next a {
  align-items: center;
  display: inline-flex;
  min-height: var(--touch-target-min);
}

/* --- what is deliberately not here -----------------------------------------
 *
 * The main menu (li#menu-item-NN > a at 40px). Site chrome, not a component --
 * it belongs to 30-layout.css, and it is 4px short, so it is a one-line fix
 * there rather than a component rule reaching up into the header.
 *
 * Links inside a sentence. The harness already exempts these (isSetInProse,
 * static_layout_qa.mjs:544-553) and so does tranche B's :only-child rule, which
 * is the same predicate spelled in CSS. A 44px box in the middle of a text
 * column is a worse page than a 16px link in it.
 */

/* --- tranche B ------------------------------------------------------------
 * The harness scores `Math.min(width, height) < 44` (static_layout_qa.mjs:564),
 * so a control that is tall enough and narrow enough still fails. Three of the
 * rules above set min-height only and left a short control short: the
 * post-to-post "Next →" measured 38x44, `a.to-top` 28x44, and the association
 * pagination buttons 41x44. Everything in this section either supplies the
 * missing axis or covers a selector tranche A did not reach.
 *
 * Where a rule below needs to mean "inside the page body, not the header or
 * footer", it scopes to #main and not #content. #content is emitted only by
 * base.html.j2 and so exists on 7,134 of 18,334 pages; base_no_sidebar.html.j2
 * emits #main, and base.html.j2 emits #main as an ancestor of #content. #main
 * is therefore the one wrapper both templates share, and scoping to #content
 * would have missed the 11,200-page litigation group entirely.
 */

/* Width for the controls tranche A made tall enough but not wide enough. */
#nav-single .nav-previous a,
#nav-single .nav-next a,
#nav-below .nav-previous a,
#nav-below .nav-next a,
a.to-top,
#association-card-pagination > button {
  justify-content: center;
  min-width: var(--touch-target-min);
}

/* --- card titles -----------------------------------------------------------
 * 432 findings on court-cases-hub, the largest remaining population by far and
 * the same shape as `a.entity-card-name` above: the link is the card's title
 * and the whole point of the card. Once the docket table was fixed these became
 * the page's entire remainder. */
article.court-case-card > h3 > a {
  align-items: center;
  display: inline-flex;
  min-height: var(--touch-target-min);
}

/* --- breadcrumbs -----------------------------------------------------------
 * Tranche A excluded these on the grounds that a 44px box per crumb "turns one
 * line into a three-line stack". That was wrong, and the markup says so: the
 * trail is `Home / Associations / <current>` and the current crumb is a <span>,
 * not a link. Only two anchors are ever scored, and the wider of them is
 * already 75px -- so min-width costs exactly 11px, on "Home", once. The bar
 * becomes 44px tall and stays on one line.
 *
 * 139 findings on category-archive, the second-largest population. */
nav.azcc-breadcrumbs .crumb > a {
  align-items: center;
  display: inline-flex;
  justify-content: center;
  min-height: var(--touch-target-min);
  min-width: var(--touch-target-min);
}

/* --- links in table cells --------------------------------------------------
 * Tranche A scoped this to `.ccx-docket-table`, which was the docket table and
 * nothing else. The same defect is on every other table in the corpus: the
 * "View source opinion/order" row link (author/tag archives, court-case posts),
 * "Document Source" on litigation, and the manual's "Download" -- which at
 * 20x91 is not merely short but wrapped vertically in a column too narrow to
 * hold the word, so min-width is the fix that also makes it legible.
 *
 * Same shape as the docket rule: a phone gets tappable rows, a pointer gets the
 * compact table back at 600px. */
#main td a {
  align-items: center;
  display: inline-flex;
  min-height: var(--touch-target-min);
  min-width: var(--touch-target-min);
}

@media (min-width: 600px) {
  #main td a {
    display: inline;
    min-height: 0;
    min-width: 0;
  }
}

/* --- source and reference lists --------------------------------------------
 * `li > a` link lists, all between 15px and 17px tall: the primary-source lists
 * on authority pages, the statute chips inside a docket cell, the roster on a
 * law-firm page, and the "back to <court>" link that closes an authority page.
 * Each is a navigation link on its own line, not prose. */
ul.azhoa-authority-sources > li > a,
ul.court-case-statutes > li > a,
.firm-attorneys > ul > li > a,
a.court-case-back-link {
  align-items: center;
  display: inline-flex;
  min-height: var(--touch-target-min);
}

/* --- the /cases/ hub controls ----------------------------------------------
 * Its pagination is a different implementation from the association directory's
 * (button.page-btn in #pagination, 35x30) and its search box is a bare input at
 * 34px tall. A form control the visitor is asked to tap into gets the same bar
 * as a button. */
#pagination > button.page-btn {
  justify-content: center;
  min-height: var(--touch-target-min);
  min-width: var(--touch-target-min);
}

#main input[type="search"],
#main input[type="text"],
#main select {
  min-height: var(--touch-target-min);
}

/* --- standalone links that only look like prose ----------------------------
 * Tranche A left `#content main p > a` and `dl > dd > a` alone as body copy.
 * Re-reading the harness, that was the wrong call in one specific case: these
 * are scored *because* `isSetInProse` found no other text in the block
 * (static_layout_qa.mjs:544-553), i.e. the link is the entire paragraph. That
 * predicate has an exact CSS spelling -- :only-child -- so the rule can reach
 * the standalone call-to-action ("View this attorney's AZHOAWatch page →",
 * "Official Court Record") without touching a citation inside a sentence.
 *
 * A link in the middle of a paragraph still has a text-node sibling, is still
 * exempt, and is still not matched here. */
#main p > a:only-child,
#main dl > dd > a:only-child {
  align-items: center;
  display: inline-flex;
  min-height: var(--touch-target-min);
}

/* ===========================================================================
 * Tranche C -- the tail
 *
 * After tranche B the whole corpus sample scored zero except one page: the
 * court-cases hub, with 234. Two rules took that to 21 and a third took it to
 * zero, which is where the QA sample stands now: 19 pages x 3 viewports, no
 * finding of any severity.
 *
 * Worth recording how the tail behaved, because it is the argument for
 * measuring after every tranche rather than writing all the rules at once.
 * Each fix uncovered the next population rather than shrinking a single one:
 * 691 -> 235 (card titles, breadcrumbs, table links) -> 21 (the card's second
 * link, one FAQ summary) -> 0 (the filter pills). The pills were never
 * invisible; they were simply outnumbered, and no amount of reading the markup
 * would have ordered them correctly.
 * ======================================================================== */

/* The card's call-to-action, 136x21. Its own generator sets
 * `.court-case-card .read-link { display: inline-block }` (0,0,2,0) from a
 * <style> block in the page body, which beats the head bundle on a tie -- so
 * this has to out-specify it rather than merely follow it. The element
 * selectors take it to 0,0,2,2. */
article.court-case-card > a.read-link {
  align-items: center;
  display: inline-flex;
  min-height: var(--touch-target-min);
}

/* The FAQ disclosure on the authority pages, 283x26. The tranche A rule
 * covered `#faq > details > summary` and three other shapes, but this one is
 * keyed on a section class rather than an id, so it fell through -- a reminder
 * that the selector list here is an inventory, not a pattern. */
.azhoa-authority-faq > details > summary {
  align-items: center;
  display: flex;
  min-height: var(--touch-target-min);
}

/* --- the court-cases filter bar --------------------------------------------
 * The last population, and the only one left after tranche C: 21 filter pills
 * at 29px tall on the /court-cases/ hub. They are the page's primary control
 * -- court, topic, year -- and on a phone they are the whole interaction.
 *
 * scripts/court_case_creator.py:1982 gives `.ccx-pill, .ccx-more` a 0.32rem
 * vertical padding from a <style> block in the page body, so these selectors
 * carry the element (0,0,1,1) to win the tie. `.ccx-more` and `.ccx-clear` are
 * the same bar's "show more topics" and "clear filters"; neither scored,
 * because `.ccx-more` is `hidden` unless a facet overflows and `.ccx-clear` is
 * a text link in the status row -- but they are the same control at the same
 * height, and the one that is hidden today is shown by a script tomorrow.
 *
 * Width is deliberately not set on the pills: every one is already 79-187px
 * wide. The status-row clear control is shorter, however, so it needs the same
 * minimum in both dimensions when JavaScript reveals it. */
button.ccx-pill,
button.ccx-more,
button.ccx-clear {
  align-items: center;
  display: inline-flex;
  justify-content: center;
  min-height: var(--touch-target-min);
}

button.ccx-clear {
  min-width: var(--touch-target-min);
}

/* ---- 90-utilities.css ---- */
/* ==========================================================================
   90-utilities.css -- single-purpose helpers. Empty until phase 2.
   ==========================================================================

   Last in the bundle so a utility wins against a component of equal
   specificity by source order alone -- no !important, which is what keeps the
   inherited Twenty Eleven stylesheets winnable rather than escalating into a
   war the design system cannot end.

   Expected first occupants: the table overflow wrapper (`overflow-x: auto`,
   the single most common source of horizontal overflow on phones) and the
   visually-hidden helper. */
