/* ==========================================================================
   GE Polish — Task 23: layout rhythm, alignment grid, motion.
   Generated by _bd-build/polish.php. Do not hand-edit this file or its
   mu-plugin copy — edit polish.php and re-run the job instead.
   ========================================================================== */

/* ---- 1. Spacing scale (8px base unit) --------------------------------- */
:root{
  --ge-space-1:8px;
  --ge-space-2:16px;
  --ge-space-3:24px;
  --ge-space-4:32px;
  --ge-space-5:48px;
  --ge-space-6:64px;
  --ge-space-7:96px;
  --ge-space-8:128px;
}

/* ---- 2. Section vertical rhythm ----------------------------------------
   Collapses 12 ad-hoc section paddings into 3 tiers, detected
   structurally. See polish.php header comment for the full reasoning on
   each selector and on why their specificity is deliberately balanced.
--------------------------------------------------------------------------*/

/* Standard (default): 96 / 72 / 56 */
.breakdance .bde-section .section-container{
  padding-top:var(--ge-space-7) !important;
  padding-bottom:var(--ge-space-7) !important;
}
@media (max-width:1023px){
  .breakdance .bde-section .section-container{
    padding-top:72px !important;
    padding-bottom:72px !important;
  }
}
@media (max-width:767px){
  .breakdance .bde-section .section-container{
    padding-top:56px !important;
    padding-bottom:56px !important;
  }
}

/* Compact band: no heading at all (proof/stat bars), or a heading with a
   single CTA button and no card grid. 56 / 48 / 40. */
.breakdance .bde-section:where(
    :not(:has(h1,h2,h3,h4,h5,h6)),
    :has(> .section-container > .bde-button):not(:has(.bde-columns)),
    :has(> .section-container > .bde-div > .bde-button):not(:has(.bde-columns))
  ) .section-container{
  padding-top:56px !important;
  padding-bottom:56px !important;
}
@media (max-width:1023px){
  .breakdance .bde-section:where(
      :not(:has(h1,h2,h3,h4,h5,h6)),
      :has(> .section-container > .bde-button):not(:has(.bde-columns)),
      :has(> .section-container > .bde-div > .bde-button):not(:has(.bde-columns))
    ) .section-container{
    padding-top:48px !important;
    padding-bottom:48px !important;
  }
}
@media (max-width:767px){
  .breakdance .bde-section:where(
      :not(:has(h1,h2,h3,h4,h5,h6)),
      :has(> .section-container > .bde-button):not(:has(.bde-columns)),
      :has(> .section-container > .bde-div > .bde-button):not(:has(.bde-columns))
    ) .section-container{
    padding-top:40px !important;
    padding-bottom:40px !important;
  }
}

/* Hero: the section immediately after the site header. 128 / 96 / 72.
   One extra real class (.bde-header-builder) vs. the two rules above, so
   this always outranks them on specificity regardless of source order. */
.breakdance .bde-header-builder + .bde-section .section-container{
  padding-top:var(--ge-space-8) !important;
  padding-bottom:var(--ge-space-8) !important;
}
@media (max-width:1023px){
  .breakdance .bde-header-builder + .bde-section .section-container{
    padding-top:96px !important;
    padding-bottom:96px !important;
  }
}
@media (max-width:767px){
  .breakdance .bde-header-builder + .bde-section .section-container{
    padding-top:72px !important;
    padding-bottom:72px !important;
  }
}

/* ---- 3. Alignment grid --------------------------------------------------
   The core fix. See polish.php header comment for the full reasoning.
   Section-level headings and their eyebrow labels/standfirst text get the
   same left inset as card content (32px), so both land on one shared
   left edge.

   Exclusion is scoped to ".bde-column > .bde-div *" (a descendant of a
   div that is itself a direct child of a grid column) rather than just
   "inside .bde-column" — a plain two-column text/image split also puts
   its heading directly inside .bde-column, with NO intermediate padded
   div, so it never had the 28px card offset to begin with and must NOT
   be excluded, or it would be left stranded at the old edge while every
   other section-level heading on the page moves. A genuine card always
   has that intermediate div (it is where the card's own padding and
   background live), so this boundary correctly separates the two cases.

   margin-left, NOT padding-left: these elements have no background/
   border of their own, so padding would only push the TEXT right while
   leaving the element's own box (and therefore getBoundingClientRect())
   in place — invisible to any edge measurement, including the one this
   task is graded on. Card text moves because it's a child of a PADDED
   parent (the card div); a heading has no such parent, so its own box
   has to move via margin to actually land on the shared edge.

   Four sibling patterns are covered, since a section heading commonly
   travels with an eyebrow label before it and/or a standfirst paragraph
   after it, and all of them need to move together or the "fix" just
   creates a new internal misalignment: label -> heading, heading -> text,
   heading -> text -> text, and (confirmed on /government/, where a
   numbered eyebrow badge and the heading share a small wrapper div, and
   the body paragraph is a sibling of THAT WRAPPER rather than of the
   heading itself) wrapper-containing-a-heading -> text.

   width:auto rides along with every margin-left here for a real reason,
   not belt-and-braces: some of these elements (confirmed on the news
   archive H1 and the single-post H1, both wrapped in a Breakdance code
   block) inherit `width:100%` from the generic
   `.bde-code-block > *{width:100%}` rule. Adding margin-left to a box
   that's already fixed at 100% width pushes its right edge out by
   exactly the margin amount — a real, measured horizontal-overflow bug
   introduced by an earlier version of this same fix (caught during
   verification, not theoretical). width:auto restores standard
   block-box sizing, where the browser computes width as
   "available space minus margins" — which both closes the overflow AND,
   unlike a manual `max-width: calc(100% - 32px)` override would have,
   leaves any element's own explicit max-width (e.g. the 640px/720px
   caps already set on some headings for line-length) fully intact,
   since max-width still bounds the auto-computed result.
--------------------------------------------------------------------------*/
/* REVERSED 2026-07-29 after visual review.

   The previous rule here indented section headings by 32px so their text
   would land on the same optical line as text INSIDE a card. It enumerated
   sibling patterns (label -> heading, heading -> text, wrapper -> text) to
   drag the heading's neighbours along with it.

   That approach cannot work, and a screenshot showed why. A section's
   children are not just headings and text: they are also badges, buttons,
   images, numbered list rows and arbitrary wrapper divs. Any pattern list
   misses some of them, and every miss leaves an element stranded at the old
   edge. On the homepage hero the H1 moved while the CRADA badge above it and
   both CTA buttons below it did not — producing exactly the "indented in odd
   places" complaint this pass was meant to fix, in a new location.

   The correct rule is the opposite and much simpler: EVERYTHING aligns to the
   container edge. A card's internal padding is a property of the card, not a
   violation of the grid — a heading sitting flush with a card's outer edge is
   what standard editorial layout looks like, and it is what makes the column
   read as a straight line down the page.

   So: no indent rules. The alignment work is done by the container itself
   plus the spacing scale in section 2 above.
--------------------------------------------------------------------------*/

/* ---- 4. Card padding — REMOVED 2026-07-29 -------------------------------
   This rule tried to collapse the site's ten different card paddings into one
   value by DETECTING what a card is: "a div, direct child of a grid column,
   containing its own heading" — later narrowed to also require an image, two
   paragraphs, or a button.

   That heuristic describes far more than cards, and it misfired twice in ways
   the client saw before I did:

     · /government/ — it matched the badge+heading flex row in every
       two-column anchor section, pushing "02 Drivers License" 32px right of
       its own paragraph (measured at x=173 against x=141 everywhere else).
     · the footer — it matched the About column (heading + logo image) and the
       Contact column (heading + address paragraphs) but NOT Site Map or
       Follow Us, whose children are link elements rather than .bde-text. Two
       of four columns got 32px of top padding and two got none, so the column
       headings sat on two different baselines.

   Real cards already set their own padding in their build scripts. The
   inconsistency this was meant to fix (32/28 vs 24/28) is small and nobody
   has remarked on it; the misalignment this CAUSED was noticed immediately.
   Detecting semantic roles from DOM shape is the mistake — if card padding
   ever genuinely needs normalising, the cards should be marked with a class
   at build time, the way .ge-utilitybar is.
--------------------------------------------------------------------------*/

/* ---- 5. Motion -----------------------------------------------------------
   Reveal state is driven ENTIRELY by JS-added classes (ge-polish.js) —
   .ge-reveal-init / .ge-revealed never appear in server-rendered markup,
   so if JS fails to run, content simply never receives them and stays at
   its normal, visible-by-default CSS. Everything in this block is
   wrapped in prefers-reduced-motion:no-preference, including the hover
   transitions, so a reduced-motion user gets none of it.
----------------------------------------------------------------------------*/
@media (prefers-reduced-motion:no-preference){
  .ge-reveal-init{
    opacity:0;
    transform:translateY(16px);
    transition:opacity .5s cubic-bezier(.2,.7,.3,1), transform .5s cubic-bezier(.2,.7,.3,1);
  }
  .ge-reveal-init.ge-revealed{
    opacity:1;
    transform:translateY(0);
  }

  .breakdance .bde-columns .bde-column > .bde-div,
  .breakdance .button-atom,
  .breakdance .bde-button__button{
    transition:transform .2s ease, border-color .2s ease, background-color .2s ease, box-shadow .2s ease;
  }
  .breakdance .bde-columns .bde-column > .bde-div:hover{
    transform:translateY(-2px);
  }
  .breakdance .button-atom:hover,
  .breakdance .bde-button__button:hover{
    transform:translateY(-1px);
  }
}
/* ---- 8. Flush the first and last cell of any horizontal cell row ----------
   Rows of equal cells (the homepage proof bar, footer link columns, stat
   strips) give every cell the same horizontal padding so the gaps between
   them read evenly. That is right for the INNER gaps and wrong at the two
   ends: the first cell's left padding pushes its content off the container
   edge, so a stat numeral no longer lines up with the heading above it, and
   the last cell's right padding does the same on the right.

   Confirmed on the homepage: the proof bar's "7" sat 28px right of the hero
   H1 and of the section heading below it, which is visible as a kink in the
   page's left column.

   Zeroing only the outer padding keeps the inner rhythm intact.
--------------------------------------------------------------------------*/
.breakdance .bde-section .bde-div > .bde-div:first-child{ padding-left:0 !important; }
.breakdance .bde-section .bde-div > .bde-div:last-child { padding-right:0 !important; }

/* ---- 9. Header gutter — ATTEMPTED AND REVERTED 2026-07-29 ---------------
   Adding a horizontal gutter to .bde-header-builder__container to match the
   section gutter looked right on paper (the logo sits ~20px left of the body
   content column). But that container has max-width:var(--bde-header-width),
   so padding eats content width rather than insetting the box — the nav and
   the GET THE SDK button wrapped onto a second row at 1440px.

   Left as-is. A 20px logo offset is a far smaller problem than a two-row
   header, and fixing it properly means changing the header's own width
   settings in Breakdance rather than patching from a global layer.
--------------------------------------------------------------------------*/

/* ---- 10. THE ROOT CAUSE OF "sometimes centred, sometimes left" ------------
   50 sections across the site set a narrowed --bde-section-width (860, 760,
   900, 1000, 780 and 1100px — six different values). The intent was good:
   cap the measure so long paragraphs stay readable.

   But Breakdance centres .section-container with margin:0 auto, so narrowing
   the CONTAINER does not cap the text in place — it slides the whole block to
   the middle of the page. Six different widths means six different left
   edges, and the eye sees the column wander as it scrolls. Measured on
   /government/: a 860px container in a 1440px viewport puts content at
   (1440-860)/2 + 20 = 310px, while the hero above it sits at 140px.

   Fix: the cap belongs on the TEXT, not the container. Every section
   container returns to the global width so all sections share one left edge,
   and body copy is capped by max-width in ch units, which is what actually
   governs readability.
--------------------------------------------------------------------------*/
.breakdance .bde-section > .section-container{
  --bde-section-width:var(--bde-section-max-width,1200px) !important;
}
.breakdance .bde-section > .section-container > .bde-text,
.breakdance .bde-section > .section-container > .bde-div > .bde-text{
  max-width:74ch;
}

/* ---- 11. Mobile horizontal overflow — PRE-EXISTING BUG -------------------
   Verified by disabling this entire polish layer and re-shooting at 390px:
   the homepage H1, body copy, hero badge and proof-bar figures were all cut
   off at the right edge with the layer OFF. So this predates the layout pass
   and has been shipping since the pages were first built.

   Cause: the section container is sized with a fixed width from
   --bde-section-width rather than a max-width, so a 1200px (or 900px, or
   860px) container stays that wide at a 390px viewport and the whole column
   overflows. Nothing inside can rescue it.

   Belt-and-braces here because this is the single most visible defect on the
   site: cap the container, cap replaced elements, and stop any long
   unbroken string (a URL, an email address) forcing the page wider.
--------------------------------------------------------------------------*/
/* REMOVED 2026-07-29 — this rule was wrong twice over.

   It was added to fix a mobile overflow that did not exist: headless Chrome
   on macOS clamps to a ~500px minimum window, so every "390px" screenshot was
   really a 390px CROP of a 500px page. The apparent clipping was the
   screenshot, not the site.

   Worse, it actively broke the desktop layout. Breakdance constrains content
   with `max-width: var(--bde-section-width)`, so `max-width:100% !important`
   overrode the 1200px cap and let every section run the full width of the
   viewport — measured at 1920px as content spanning x=20 to x=1899 instead of
   a centred x=360 to x=1560.

   The container must stay capped. Section 10 above already normalises every
   section to the 1200px global; nothing here should widen it.
--------------------------------------------------------------------------*/
.breakdance img,
.breakdance video,
.breakdance iframe,
.breakdance table{ max-width:100%; }
.breakdance img{ height:auto; }

/* height:auto above is right for in-flow content images — WordPress ships
   hard-coded width/height attributes, and without it max-width:100% distorts
   them. But at (0,1,1) it also outranks any component rule setting an explicit
   height, which silently broke two deliberate object-fit cases:

     · the YouTube facade thumbnail lost height:100%, so object-fit:cover had
       no box to crop against and YouTube's 4:3 hqdefault.jpg showed its baked
       -in letterbox bars inside a 16:9 tile
     · the Gen-2 hero background video would lose its fill the same way

   Restored explicitly rather than weakening the blanket rule. */
.breakdance .ge-yt-facade__thumb,
.breakdance .ge-gen2-hero-video{ height:100% !important; }
/* overflow-x:hidden deliberately NOT set. It would hide the mobile overflow
   by clipping text mid-word, which is worse than an honest scrollbar and
   would stop the real defect being noticed. Left visible until fixed. */
.breakdance .bde-text,
.breakdance :where(h1,h2,h3,h4){ overflow-wrap:break-word; }

/* ---- 12. The header utility bar is chrome, not a content section ---------
   Section 2's vertical rhythm applies to every .bde-section. The thin bar
   above the navigation is technically a Section too, so it was picking up the
   "compact band" tier — 56px top and bottom — and rendering 128px tall
   against a design target of 60px max.

   It is marked with .ge-utilitybar in build_header.php precisely so it can be
   excluded here. Height is set by padding rather than a max-height cap, so
   the bar can still grow if its content wraps on a narrow screen instead of
   clipping the email address.
--------------------------------------------------------------------------*/
.breakdance .bde-section.ge-utilitybar > .section-container{
  padding-top:var(--ge-space-2) !important;
  padding-bottom:var(--ge-space-2) !important;
}
@media (max-width:767px){
  .breakdance .bde-section.ge-utilitybar > .section-container{
    padding-top:var(--ge-space-1) !important;
    padding-bottom:var(--ge-space-1) !important;
  }
}

/* ---- 13. Gen-2 hero background video must be full-bleed ------------------
   The video wrapper is position:absolute; inset:0, which resolves against
   .section-container — and that is capped at the 1200px content width. So the
   footage rendered as a band across the middle of the hero with dark bars
   either side, rather than filling it.

   The 100vw breakout spans the whole section; clipping on the section itself
   means the page gains no horizontal scrollbar from it.
--------------------------------------------------------------------------*/
.breakdance .bde-section:has(.ge-gen2-hero-bg){
  position:relative;
  overflow:hidden;
}
.breakdance .ge-gen2-hero-bg{
  left:50% !important;
  right:auto !important;
  width:100vw !important;
  /* The CodeBlock width-fix applies max-width:100% to every direct child of
     .bde-code-block, which silently clamped the 100vw breakout back to the
     1200px container. Measured: computed width came out 1200px despite
     width:100vw !important. */
  max-width:none !important;
  transform:translateX(-50%) !important;
}

/* ---- 14. WP Job Manager plugin defaults, corrected for a dark theme -------
   Two defects, both from plugin CSS written for a light theme.

   1. HOVER MADE TEXT INVISIBLE.
      WPJM ships `ul.job_listings li.job_listing a:hover { background-color:
      #fcfcfc }` — near-white. Against this site's white listing titles that
      turns the hovered row into a blank white bar. Our own rule only set
      border-color, so the plugin's background won.

      Replaced with a subtle dark lift plus the accent border, so the hover
      target is obvious and the text stays legible. A visible focus ring is
      added too — the plugin's hover and focus share a selector, so keyboard
      users had the same problem.

   2. UNSTYLED META LIST KEPT THE BROWSER'S DEFAULT INDENT.
      The single-job page renders <ul class="job-listing-meta meta">, and
      nothing in either the plugin or this build styles it. So it inherited
      the UA default ul padding-left: 40px, pushing the Full Time / location /
      posted-date row in from the left while the body copy beneath sat flush.
--------------------------------------------------------------------------*/
.breakdance ul.job_listings li.job_listing a:hover,
.breakdance ul.job_listings li.job_listing a:focus,
.breakdance ul.job_listings li.job_listing.job_position_featured a:hover,
.breakdance ul.job_listings li.job_listing.job_position_featured a:focus{
  background-color:#141B26 !important;
}
.breakdance ul.job_listings li.job_listing:hover{
  border-color:var(--ge-accent,#2F6DF6) !important;
}
.breakdance ul.job_listings li.job_listing a:focus-visible{
  outline:2px solid var(--ge-accent,#2F6DF6) !important;
  outline-offset:-2px;
}

.breakdance ul.job-listing-meta,
.breakdance ul.job-listing-meta.meta{
  list-style:none !important;
  padding-left:0 !important;
  margin-left:0 !important;
  display:flex !important;
  flex-wrap:wrap;
  align-items:center;
  gap:22px;
}
.breakdance ul.job-listing-meta > li{ margin:0 !important; }

/* ---- 15. Mobile menu was unreadable — white text on a white panel --------
   Reported from production. Breakdance sets .breakdance-menu-list to an
   explicit background:#fff, but the nav links are light (#C9D4E2 on live,
   #FFF here) because they are styled for the dark desktop bar. Opening the
   menu on a phone therefore produced a blank white panel with invisible
   items — verified by opening it in headless Chrome and reading the computed
   values: panel bg rgb(255,255,255), link colour rgb(255,255,255).

   Scoped to max-width:1119px, which is where the header collapses, so the
   desktop bar is untouched.
--------------------------------------------------------------------------*/
@media (max-width: 1119px) {
  .breakdance-menu-list{
    background-color:#0B0E13 !important;
    border-top:1px solid #161D27;
  }
  .breakdance-menu-list .breakdance-menu-link,
  .breakdance-menu-list a{ color:#FFFFFF !important; }
  .breakdance-menu-list .breakdance-menu-item{ border-bottom:1px solid #161D27; }
  .breakdance-menu-list .breakdance-dropdown-body,
  .breakdance-menu-list .breakdance-dropdown-floater{ background-color:#0F131A !important; }
  .breakdance-menu-list .breakdance-dropdown-link{ color:#C9D4E2 !important; }
}
