/*
Theme Name: PayGen
Theme URI: https://paygennow.com
Author: NewGen Business Solutions
Author URI: https://newgennow.com
Description: Block theme for paygennow.com — payment processing built natively into Oracle NetSuite, by NewGen Business Solutions. Design tokens live in theme.json; this file carries only what theme.json cannot express.
Requires at least: 6.7
Tested up to: 7.0
Requires PHP: 8.1
Version: 0.26.0
License: GNU General Public License v2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html
Text Domain: paygen
Tags: block-theme, business, one-column, custom-colors, custom-menu, editor-style, full-site-editing
*/

/* ===========================================================
   Everything expressible in theme.json belongs in theme.json.
   This file carries only what the schema genuinely cannot do:
   block style variations, the canvas/ledger hosts, and the
   hairline lattice.

   NO LITERAL COLOURS OR SIZES. Every value below is a
   theme.json token reference.
   =========================================================== */

/* ===========================================================
   Fluent Forms — the demo request form
   design-system.md §7.7. Added 2026-09-02 with form 3.

   The plugin ships its own stylesheet; this overrides it from
   the theme so no plugin template is touched and nothing is
   lost on a plugin update. Selectors are the plugin's real
   DOM, read off a `do_shortcode()` render on the box, not
   guessed: .ff-el-group wraps a field, .ff-el-input--label the
   label, .ff-el-input--content the control, .ff-el-form-control
   IS the input/select/textarea.

   SCOPED TO .pg-form so it cannot reach a form added elsewhere
   later. Everything is a token; there is not a literal colour
   or size below.

   🔴 TURNSTILE IS NOT STYLED, HIDDEN OR MOVED. The widget is a
   real control that must stay visible and clickable; the only
   rule touching it reserves vertical space. Do not add
   display/visibility/position/transform rules to .cf-turnstile.
   =========================================================== */

.pg-form .frm-fluent-form {
	display: grid;
	gap: var(--wp--preset--spacing--60);
}

.pg-form .ff-el-group {
	margin-bottom: 0;
}

/* Label — the eyebrow treatment, per §7.7: mono, uppercase,
   muted, sitting above the field. */
.pg-form .ff-el-input--label label {
	color: var(--wp--preset--color--muted);
	font-family: var(--wp--preset--font-family--mono);
	font-size: var(--wp--preset--font-size--xs-mono);
	font-weight: 400;
	letter-spacing: var(--wp--custom--kicker--letter-spacing);
	line-height: 1.4;
	text-transform: var(--wp--custom--kicker--text-transform);
}

.pg-form .ff-el-input--label {
	margin-bottom: var(--wp--preset--spacing--20);
}

.pg-form .ff-el-is-required.asterisk-right label::after {
	color: var(--wp--preset--color--error);
}

/* Controls. THE FONT SIZE IS THE ONE PLACE THE COMP IS
   OVERRULED — design-system.md §C8: the design specs 15.5px and
   trap 16 says anything under 16px triggers iOS focus zoom.
   --control--min-font-size is 1rem and is not negotiable. */
.pg-form .ff-el-form-control {
	background-color: var(--wp--preset--color--base-white);
	border: 1px solid var(--wp--preset--color--line-strong);
	border-radius: var(--wp--custom--radius--control);
	color: var(--wp--preset--color--ink);
	font-family: var(--wp--preset--font-family--body);
	font-size: var(--wp--custom--control--min-font-size);
	line-height: 1.5;
	min-height: var(--wp--custom--control--touch-target);
	padding: var(--wp--custom--control--padding);
	transition: border-color var(--wp--custom--motion--duration-fast) var(--wp--custom--motion--easing);
	width: 100%;
}

.pg-form textarea.ff-el-form-control {
	min-height: calc(var(--wp--custom--control--touch-target) * 2.5);
	resize: vertical;
}

.pg-form .ff-el-form-control::placeholder {
	color: var(--wp--preset--color--disabled-text);
	opacity: 1;
}

/* Focus. §7.7 says `outline: none` with a border-color shift;
   we keep BOTH. The design's own rule list also requires a 2px
   ring at 3px offset on every focusable element, and dropping
   the outline here would take the SC 2.4.7 indicator with it.
   The border shift is the comp's signal, the ring is the
   accessible one. */
.pg-form .ff-el-form-control:focus {
	border-color: var(--wp--preset--color--accent-blue);
}

/* Errors — never colour-only: the plugin prints a message
   element, this only carries the colour. */
.pg-form .ff-el-form-control.has-error,
.pg-form .ff-el-form-control[aria-invalid="true"] {
	border-color: var(--wp--preset--color--error);
}

.pg-form .error.text-danger,
.pg-form .ff-el-is-error .error {
	color: var(--wp--preset--color--error);
	font-size: var(--wp--preset--font-size--s);
	margin-top: var(--wp--preset--spacing--20);
}

/* Submit — matches theme.json's button element exactly, because
   the plugin's button is not a wp-element-button and inherits
   none of it. The 15px/28px padding is DUPLICATED from
   theme.json styles.elements.button, which hardcodes it too;
   there is no preset for either value. If that padding changes,
   change it here as well — nothing enforces the pairing. */
.pg-form .ff-btn-submit {
	background-color: var(--wp--preset--color--accent-green);
	border: 0;
	border-radius: var(--wp--custom--radius--control);
	color: var(--wp--preset--color--base-navy);
	cursor: pointer;
	font-family: var(--wp--preset--font-family--body);
	font-size: var(--wp--custom--control--min-font-size);
	font-weight: 600;
	line-height: 1.2;
	min-height: var(--wp--custom--control--touch-target);
	padding: 15px 28px;
	transition: background-color var(--wp--custom--motion--duration-fast) var(--wp--custom--motion--easing);
	width: 100%;
}

.pg-form .ff-btn-submit:hover,
.pg-form .ff-btn-submit:focus {
	background-color: var(--wp--preset--color--accent-green-light);
	color: var(--wp--preset--color--base-navy);
}

/* The name field is laid out as a table by the plugin; strip
   the cell padding so it lines up with the other fields. */
.pg-form .ff-t-container,
.pg-form .ff-t-cell {
	padding: 0;
}

/* TURNSTILE — space only. See the header of this section. */
.pg-form .cf-turnstile {
	margin-block: var(--wp--preset--spacing--40);
}

/* Confirmation — the design's "Got it" panel (§C9). */
.pg-form .ff-message-success {
	background-color: var(--wp--preset--color--status-success-surface);
	border: 1px solid var(--wp--preset--color--line);
	border-radius: var(--wp--custom--radius--card);
	color: var(--wp--preset--color--ink);
	padding: var(--wp--preset--spacing--70);
}

/* --- Band seams inside <main> ------------------------------
   The 0.14.0 rule above fixed the THREE ROOT children. This
   fixes the bands, one level below it, which the root
   selector cannot reach.

   Core opts every blockGap theme into a SECOND gap rule, on
   every flow container:

     :root :where(.is-layout-flow) > * { margin-block-start: <gap> }

   `.entry-content` is `is-layout-flow`, so every band took
   `margin-top: 26px` from its own margin — the same
   spacing-60 token, a different selector. Measured 2026-09-02
   at 26.0px on ALL THIRTEEN band boundaries across the four
   pages (page 8 nine, 17 two, 18 one, 3 one).

   Three of the thirteen painted as white stripes: a body-white
   gap only shows where a non-white band sits on BOTH sides.
   #cycle→#platform was the worst — both surface, and framed by
   a border-bottom and a border-top, so it read as
   surface · line · white · line · surface.

   NO DESIGN INTENT IS BEING REMOVED. Every band owns its
   vertical rhythm through --wp--custom--section--rhythm
   padding; the 26px is core's default leaking through.
   Recolouring it instead would mean a per-boundary colour
   decision at thirteen boundaries — this is one rule.

   ⚠️ SPECIFICITY IS NOT THE SAME AS THE ROOT CASE. Core's root
   selector is (0,0,0); THIS one is (0,1,0), because `:root`
   counts as a pseudo-class. A (0,1,0) override would only tie
   and fall back to source order, which is not dependable —
   global styles can be printed inline and after this sheet
   (trap 30). Two classes gives (0,2,0) and wins outright.

   SCOPED TO DIRECT CHILDREN ONLY. `>` means the bands and
   nothing else: flow spacing INSIDE a band comes from the same
   core rule applied to nested `is-layout-flow` containers, and
   is deliberately untouched.
   ---------------------------------------------------------- */

.entry-content.is-layout-flow > * {
	margin-block-start: 0;
}

/* --- Root band seams --------------------------------------
   Core opts every blockGap-supporting theme into

     :where(.wp-site-blocks) > * { margin-block-start: <gap>; }

   and our gap is spacing 60 = 26px. The three root children are
   <header>, <main> and <footer>, so that put a 26px margin on
   BOTH sides of <main> — outside any band's background, so it
   painted as a white seam under the navy header AND, on the
   one-pager, between the navy closing band and the navy footer.
   Measured 26.0px at 1440 / 834 / 390 on pages 8 and 18.

   Every band owns its vertical rhythm through
   --wp--custom--section--rhythm padding; nothing depends on the
   root gap. Zeroed unscoped so it covers both seams and any
   template added later.

   THIS WINS ON SPECIFICITY, NOT LOAD ORDER. Core's selector is
   (0,0,0) — :where() contributes nothing and so does `*`. This
   one is (0,1,0). Load order is not dependable: global styles
   can be printed inline and after this stylesheet (trap 30).
   ---------------------------------------------------------- */

.wp-site-blocks > * {
	margin-block-start: 0;
}

/* --- Accessibility: skip link ----------------------------- */

.skip-link:focus {
	background-color: var(--wp--preset--color--base-white);
	color: var(--wp--preset--color--link);
	outline: var(--wp--custom--focus--width) solid var(--wp--preset--color--focus-ring);
	outline-offset: var(--wp--custom--focus--offset);
	z-index: 100000;
}

/* --- Block style: secondary button ------------------------
   design-system.md §7.3. The border uses `line-strong`, which
   the 2026-08-18 accessibility fix darkened to #79879F so a
   control boundary clears SC 1.4.11's 3:1. It is visibly
   heavier than the comp's #C9D5E8. To revert to the comp,
   swap line-strong for line-emphasis on the two rules below
   and accept 1.48:1.
   ---------------------------------------------------------- */

.wp-block-button.is-style-secondary > .wp-block-button__link {
	background-color: var(--wp--preset--color--base-white);
	color: var(--wp--preset--color--link);
	border: 1px solid var(--wp--preset--color--line-strong);
	border-radius: var(--wp--custom--radius--control);
}

.wp-block-button.is-style-secondary > .wp-block-button__link:hover {
	border-color: var(--wp--preset--color--accent-blue);
	color: var(--wp--preset--color--accent-blue);
	background-color: var(--wp--preset--color--base-white);
}

.wp-block-button.is-style-secondary > .wp-block-button__link:focus {
	border-color: var(--wp--preset--color--accent-blue);
	color: var(--wp--preset--color--accent-blue);
}

/* Secondary on a dark band: transparent, white, weight 500. */

.has-base-navy-background-color .wp-block-button.is-style-secondary > .wp-block-button__link,
.has-surface-dark-background-color .wp-block-button.is-style-secondary > .wp-block-button__link {
	background-color: transparent;
	color: var(--wp--preset--color--base-white);
	border-color: var(--wp--preset--color--on-dark-border-strong);
	font-weight: 500;
}

.has-base-navy-background-color .wp-block-button.is-style-secondary > .wp-block-button__link:hover,
.has-surface-dark-background-color .wp-block-button.is-style-secondary > .wp-block-button__link:hover {
	border-color: var(--wp--preset--color--base-white);
	background-color: transparent;
	color: var(--wp--preset--color--base-white);
}

/* --- Block style: eyebrow / kicker ------------------------
   design-system.md §7.1 — the most repeated element in the
   system. Not mapped onto h6 (that mapping was reverted
   2026-08-18, §12.3); it is an explicit opt-in style.
   ---------------------------------------------------------- */

.is-style-eyebrow {
	font-family: var(--wp--preset--font-family--mono);
	font-size: var(--wp--preset--font-size--xs-mono);
	letter-spacing: var(--wp--custom--kicker--letter-spacing);
	text-transform: var(--wp--custom--kicker--text-transform);
	line-height: 1.4;
}

/* --- Block style: card ------------------------------------
   design-system.md §7.2 — white, 1px hairline, 5px radius,
   no shadow at rest, shadow + border shift on hover.
   ---------------------------------------------------------- */

.wp-block-group.is-style-card {
	background-color: var(--wp--preset--color--base-white);
	border: 1px solid var(--wp--preset--color--line);
	border-radius: var(--wp--custom--radius--card);
	padding: var(--wp--preset--spacing--60);
	transition: box-shadow var(--wp--custom--motion--duration) var(--wp--custom--motion--easing),
		border-color var(--wp--custom--motion--duration) var(--wp--custom--motion--easing);
}

.wp-block-group.is-style-card:hover {
	box-shadow: var(--wp--preset--shadow--card-hover);
	border-color: var(--wp--preset--color--line-emphasis);
}

/* Card sitting inside a navy band. */

.has-base-navy-background-color .wp-block-group.is-style-card {
	background-color: var(--wp--preset--color--surface-dark);
	border-color: var(--wp--preset--color--on-dark-border);
}

/* --- Block style: stat block ------------------------------
   design-system.md §7.2 — the rule colour is semantic: green
   for outcomes, blue for platform facts.
   ---------------------------------------------------------- */

.wp-block-group.is-style-stat {
	border-left: 2px solid var(--wp--preset--color--accent-green);
	padding-left: var(--wp--preset--spacing--50);
}

.wp-block-group.is-style-stat-fact {
	border-left: 2px solid var(--wp--preset--color--accent-blue);
	padding-left: var(--wp--preset--spacing--50);
}

/* --- Block style: status pill -----------------------------
   design-system.md §7.5 — 2px radius, tighter than anything
   else, so it reads as a data chip and not a button.
   ---------------------------------------------------------- */

.is-style-pill {
	display: inline-block;
	font-family: var(--wp--preset--font-family--mono);
	font-size: var(--wp--preset--font-size--xs-mono);
	letter-spacing: var(--wp--custom--kicker--letter-spacing);
	text-transform: var(--wp--custom--kicker--text-transform);
	border-radius: var(--wp--custom--radius--pill);
	padding: var(--wp--preset--spacing--10) var(--wp--preset--spacing--20);
	margin: 0;
}

/* --- Hairline lattice -------------------------------------
   design-system.md §7.10, and a build rule the design states
   explicitly because it broke before: each cell draws its OWN
   border-top and border-left. Never a container background
   showing through gaps — an auto-fit track can resolve to 2,
   3, 4 or 5 columns and any orphan cell paints as a grey slab.
   ---------------------------------------------------------- */

/* The lattice is a GRID, not core's flex columns. Core stacks
   .wp-block-columns in one step at 782px; the comp reflows its cells
   continuously with auto-fit. Matching that is what lets the six
   security cells live in ONE wrapper — which is what removes the 2px
   seam and the mid-grid rounded corners. Selector is doubled
   (.wp-block-columns.pg-lattice) so it beats core's own
   .wp-block-columns display rule on specificity, not load order.

   THE MINIMUM IS 340px, NOT THE COMP'S 210px, AND THE COMP'S NUMBER
   WOULD BE WRONG HERE. In the comp the lattice sits in the RIGHT
   COLUMN of a two-column band, roughly 600px wide, where a 210px
   minimum yields 2-3 across. This theme stacks that band full width,
   so the same 210px yielded floor(1280 / 210) = SIX across in one row
   at 213px each — measured, not guessed. auto-fit fits
   floor(width / minimum) tracks, so three across at a 1280px content
   width needs a minimum above 1280/4 = 320px and at or below
   1280/3 = 426px. 340px sits inside that band with room either side,
   and still collapses to 2 and then 1 as the viewport narrows.

   Porting a minmax minimum without its container width is the trap
   here: the value is meaningless on its own. */

.wp-block-columns.pg-lattice {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(min(100%, 340px), 1fr));
}

.pg-lattice {
	border-right: 1px solid var(--wp--preset--color--line);
	border-bottom: 1px solid var(--wp--preset--color--line);
	border-radius: var(--wp--custom--radius--card);
	overflow: hidden;
}

.pg-lattice > .wp-block-column,
.pg-lattice > .wp-block-group {
	border-top: 1px solid var(--wp--preset--color--line);
	border-left: 1px solid var(--wp--preset--color--line);
	background-color: var(--wp--preset--color--surface-raised);
	/* Comp draws 18px 18px 20px (PayGen.dc.html:322-327). The spacing
	   scale has no 18px step, so this is spacing-50 (20px) throughout —
	   the nearest step, and the bottom value is exact. Was 12px/16px. */
	padding: var(--wp--preset--spacing--50);
	margin: 0;
}

.has-base-navy-background-color .pg-lattice {
	border-right-color: var(--wp--preset--color--on-dark-border);
	border-bottom-color: var(--wp--preset--color--on-dark-border);
}

.has-base-navy-background-color .pg-lattice > .wp-block-column,
.has-base-navy-background-color .pg-lattice > .wp-block-group {
	border-top-color: var(--wp--preset--color--on-dark-border);
	border-left-color: var(--wp--preset--color--on-dark-border);
	background-color: var(--wp--preset--color--surface-dark);
}

/* --- Dark band -------------------------------------------
   The glow gradients sit behind the content. The palette
   background CLASS is mandatory on every dark band — the
   focus ring switches to brand green off it, and a literal
   background gets the light ring instead (design-system.md
   §12.1).
   ---------------------------------------------------------- */

.pg-band {
	position: relative;
	isolation: isolate;
	overflow: hidden;
}

/* --- Canvas hero host ------------------------------------
   design-system.md §C1. assets/js/paygen-hero.js defines
   <pg-canvas> and injects it here at runtime, so pattern
   content stays pure block markup — no wp:html anywhere.
   The host is decorative and aria-hidden; if the script never
   loads, the band renders as a plain dark section.
   ---------------------------------------------------------- */

.pg-canvas-host {
	position: absolute;
	inset: 0;
	z-index: -1;
	pointer-events: none;
}

/* The host is a direct child of a CONSTRAINED section, so core's layout
   support matches it with
     `<sel> > :where(:not(.alignleft):not(.alignright):not(.alignfull))`
     { max-width: 1280px; margin-left: auto !important; margin-right: auto
       !important }
   (wp-includes/block-supports/layout.php, the `'constrained'` branch).
   An absolutely-positioned box with `inset: 0`, a max-width and auto
   margins is CENTRED and clipped to the content column instead of
   filling the band. The canvas then paints a band-relative composition
   against the wrong origin. Undone here rather than by adding
   `alignfull` in the markup, because a class change to a seeded pattern
   costs a page re-seed (trap 2) and this does not. The `!important` is
   required to beat core's own, not for weight of opinion — the
   selector is deliberately more specific than core's. */

.pg-band > .pg-canvas-host {
	max-width: none;
	margin-left: 0 !important;
	margin-right: 0 !important;
}

.pg-canvas-host pg-canvas {
	display: block;
	width: 100%;
	height: 100%;
}

.pg-band > :not(.pg-canvas-host) {
	position: relative;
}

/* --- Column overflow -------------------------------------
   Flex/grid children default to min-width: auto, so a long
   unbroken string (a URL, a mono figure) forces the column
   wider than its track instead of wrapping. TWO ancestors
   then clip it rather than scroll it: .pg-band and
   .pg-lattice both set overflow: hidden. Result is content
   silently cut off, worst at 390px.

   Scoped to this theme's own containers, not applied to
   every .wp-block-column globally — core layouts elsewhere
   are left alone.
   ---------------------------------------------------------- */

.pg-band .wp-block-column,
.pg-lattice > .wp-block-column {
	min-width: 0;
}

/* --- Inline links on dark bands ---------------------------
   theme.json sets `elements.link` to `--...--color--link`
   (#2F4E85) globally, with an accent-blue hover. Neither was
   ever given an on-dark counterpart, so every inline <a> on
   a navy band took a link colour intended for white:
   #2F4E85 on #0B1A2F measures 2.12:1, and the hover 3.56:1.
   AA wants 4.5:1 at these sizes. Numbers from
   scripts/pg-contrast.py.

   THE FIX IS `inherit`, NOT A NEW COLOUR. Every dark-band
   paragraph already carries an on-token colour that passes
   comfortably — on-dark-meta 7.00:1, on-dark-lede 10.08:1,
   on-dark-link 9.11:1, base-white 17.46:1. Letting the link
   take its parent's colour fixes the contrast everywhere at
   once and invents no treatment: it is exactly what the comp
   draws for the header phone number, `color: #8FA6C4` with a
   white hover and NO underline (PayGen.dc.html:45). A blanket
   white-plus-underline rule would have been a visual change
   the comp does not ask for, on every page.

   This did NOT affect navigation blocks: core ships
   `.wp-block-navigation .wp-block-navigation-item__content
   .wp-block-navigation-item__content { color: inherit }`, a
   deliberately doubled class at (0,3,0) that already outranks
   theme.json's `:root :where(a…)` at (0,1,0). The menus were
   always taking their block textColor; it was the plain
   paragraph links that broke — both phone numbers, the
   security band's CTA, and the support-ticket breadcrumb.

   Fixed in style.css rather than theme.json because trap 7
   rejects comma-joined `&` selectors there, and because CSS
   and parts take effect without a page re-seed while block
   markup does not (traps 2 and 26).
   ---------------------------------------------------------- */

.has-base-navy-background-color a:not(.wp-element-button),
.has-surface-dark-background-color a:not(.wp-element-button),
.has-surface-dark-raised-background-color a:not(.wp-element-button) {
	color: inherit;
}

.has-base-navy-background-color a:not(.wp-element-button):hover,
.has-surface-dark-background-color a:not(.wp-element-button):hover,
.has-surface-dark-raised-background-color a:not(.wp-element-button):hover {
	color: var(--wp--preset--color--accent-green-light);
}

.has-base-navy-background-color a:not(.wp-element-button):focus,
.has-surface-dark-background-color a:not(.wp-element-button):focus,
.has-surface-dark-raised-background-color a:not(.wp-element-button):focus {
	color: var(--wp--preset--color--accent-green-light);
}

/* --- Standalone on-dark CTA link ---------------------------
   A link sitting alone in its own paragraph has no
   surrounding sentence to mark it as a link, and `inherit`
   deliberately makes it the same colour as the copy around
   it. The underline is what carries the affordance. White
   with a 1px 35%-white rule, hovering to green, is the comp's
   own treatment for exactly this link (PayGen.dc.html:320).

   Applied by class, so it stays opt-in: an underline under
   every inline link on a dark band is not the design. Note
   this one needs a page re-seed to appear (trap 2) — until
   then the link is plain inherited white, which is 17.46:1
   and already passes AA. It degrades safely.
   ---------------------------------------------------------- */

.pg-link-underline a:not(.wp-element-button) {
	color: var(--wp--preset--color--base-white);
	border-bottom: 1px solid var(--wp--preset--color--on-dark-border-strong);
	padding-bottom: 3px;
}

.pg-link-underline a:not(.wp-element-button):hover,
.pg-link-underline a:not(.wp-element-button):focus {
	color: var(--wp--preset--color--accent-green-light);
	border-bottom-color: var(--wp--preset--color--accent-green-light);
}

/* --- Live ledger ------------------------------------------
   design-system.md §C2. Injected by the same script into
   .pg-ledger. Empty and invisible until the script runs.
   ---------------------------------------------------------- */

.pg-ledger table {
	width: 100%;
	border-collapse: collapse;
	font-size: var(--wp--preset--font-size--s);
}

.pg-ledger td {
	padding: var(--wp--preset--spacing--30) var(--wp--preset--spacing--40);
	/* line-soft is the comp's own row rule, #EEF1F7 (PayGen.dc.html:120).
	   Was on-dark-border, which is white at 11% — invisible on the white
	   card the ledger became. */
	border-top: 1px solid var(--wp--preset--color--line-soft);
}

.pg-ledger .pg-amount {
	font-family: var(--wp--preset--font-family--mono);
	font-variant-numeric: tabular-nums;
	text-align: right;
}

.pg-ledger .pg-row {
	transition: background-color var(--wp--custom--motion--duration) var(--wp--custom--motion--easing);
}

.pg-ledger .pg-row.is-clearing {
	background-color: var(--wp--preset--color--surface-raised);
}

.pg-ledger .pg-pill {
	display: inline-block;
	font-family: var(--wp--preset--font-family--mono);
	font-size: var(--wp--preset--font-size--xs-mono);
	letter-spacing: var(--wp--custom--kicker--letter-spacing);
	text-transform: var(--wp--custom--kicker--text-transform);
	border-radius: var(--wp--custom--radius--pill);
	padding: var(--wp--preset--spacing--10) var(--wp--preset--spacing--20);
}

.pg-ledger .pg-pill.is-due {
	background-color: var(--wp--preset--color--surface-inset);
	color: var(--wp--preset--color--muted);
}

.pg-ledger .pg-pill.is-clearing {
	background-color: var(--wp--preset--color--status-clearing-surface);
	color: var(--wp--preset--color--link);
}

.pg-ledger .pg-pill.is-paid {
	background-color: var(--wp--preset--color--status-paid-surface);
	color: var(--wp--preset--color--accent-green-text);
}

/* --- Live ledger: narrow-width row layout ------------------
   The four-column table needs 399px of min-content (customer
   90.7 / invoice 42 / amount 58.8 / pill 79.5, plus 4x32px of
   td padding). The card it sits in offers 296px at 390px wide
   and only 219px at 782px — one pixel above the column stack
   breakpoint, where the ledger drops from 718px to 273px in a
   single step. Below min-content, core's overflow-wrap:
   break-word on .wp-block-column escalates to emergency
   breaking and splits digit runs: "$18,4 / 75", "DU / E".

   Gated on the ledger's own inline size, not the viewport: the
   widths where four columns fit are disjoint (493–781px, then
   1174px+) because the hero columns stack at 782. A media
   query would have to hardcode 1173px, a number derived from
   the 52% / 72px gap split that would drift the moment those
   are retuned.
   ---------------------------------------------------------- */

.pg-ledger {
	container-type: inline-size;
}

/* Values never break mid-token, at any width. */

.pg-ledger .pg-amount,
.pg-ledger .pg-pill,
.pg-ledger td:nth-child(2) {
	white-space: nowrap;
}

@container (max-width: 440px) {

	.pg-ledger table,
	.pg-ledger tbody,
	.pg-ledger td {
		display: block;
	}

	/* The row border moves to the tr: once the cells are block
	   the per-td border-top would draw once per cell. */

	.pg-ledger tr {
		display: grid;
		grid-template-columns: minmax(0, 1fr) auto;
		column-gap: var(--wp--preset--spacing--40);
		row-gap: var(--wp--preset--spacing--10);
		padding: var(--wp--preset--spacing--30) 0;
		border-top: 1px solid var(--wp--preset--color--on-dark-border);
	}

	.pg-ledger td {
		padding: 0;
		border-top: 0;
	}

	.pg-ledger td:nth-child(2) {
		grid-area: 1 / 2;
		text-align: right;
	}

	.pg-ledger td:nth-child(3) {
		grid-area: 2 / 1;
		text-align: left;
	}

	.pg-ledger td:nth-child(4) {
		grid-area: 2 / 2;
		text-align: right;
	}
}

/* --- Live dot (pgPulse) -----------------------------------
   design-system.md §8 — one of the two keyframes the design
   allows. Collapses under prefers-reduced-motion via the rule
   theme.json emits.
   ---------------------------------------------------------- */

@keyframes pgPulse {
	0%,
	100% {
		opacity: 1;
		transform: scale(1);
	}
	50% {
		opacity: 0.35;
		transform: scale(0.82);
	}
}

@keyframes pgRise {
	from {
		opacity: 0;
		transform: translateY(10px);
	}
	to {
		opacity: 1;
		transform: none;
	}
}

.pg-live-dot::before {
	content: "";
	display: inline-block;
	width: var(--wp--preset--spacing--20);
	height: var(--wp--preset--spacing--20);
	margin-right: var(--wp--preset--spacing--20);
	border-radius: 50%;
	background-color: var(--wp--preset--color--accent-green);
	animation: pgPulse 2s ease-in-out infinite;
}

/* --- Figures ---------------------------------------------- */

.has-figure-font-size {
	font-variant-numeric: tabular-nums;
	/* comp-diff §3. The `figure` preset carries a size and nothing
	   else, so a 52px figure was inheriting the global 1.62 line
	   height — about 84px of line box where the comp draws 52px
	   (PayGen.dc.html:738-757). No tracking token exists for -0.03em;
	   the literal is the comp's value. Font-weight 600 is also in the
	   comp and is NOT set here — that is still open in comp-diff. */
	line-height: 1;
	letter-spacing: -0.03em;
}

/* --- Measure caps ----------------------------------------
   design-system.md §6.2 — line-length controls, not container
   widths.
   ---------------------------------------------------------- */

.pg-measure-lede {
	max-width: var(--wp--custom--measure--lede);
}

.pg-measure-body {
	max-width: var(--wp--custom--measure--body);
}

.pg-measure-heading {
	max-width: var(--wp--custom--measure--heading);
	text-wrap: balance;
}

/* ===========================================================
   PayGen — additions for the one-pager.

   Append to theme/style.css. Same rule as the rest of that
   file: NO LITERAL COLOURS OR SIZES. Every value below is a
   theme.json token reference.

   Five new components:
     .pg-stages / .pg-stage-rail / .pg-stage-tab  — band 4
     .pg-specs                                     — spec lists
     .pg-note                                      — inset note
     .pg-today                                     — band 3 rows
     .pg-shot                                      — band 6 frames
   =========================================================== */

/* --- Anchor scrolling -------------------------------------
   The header is deliberately NOT sticky, so there is no
   offset to compensate for. Gated on the motion preference:
   a full-page smooth scroll is exactly the kind of motion the
   preference exists to suppress.
   ---------------------------------------------------------- */

@media (prefers-reduced-motion: no-preference) {

	html {
		scroll-behavior: smooth;
	}
}

/* --- Five-stage selector ----------------------------------
   Authored as five plain stacked .pg-stage groups.
   assets/js/paygen-stages.js adds .is-enhanced and the rail.

   The un-enhanced state is styled FIRST and must stay
   readable on its own: it is what renders with JS off, and
   what an editor sees in the block editor, where the script
   does not run.
   ---------------------------------------------------------- */

.pg-stages {
	display: flex;
	flex-direction: column;
	gap: var(--wp--preset--spacing--60);
}

.pg-stages.is-enhanced {
	gap: var(--wp--preset--spacing--50);
}

.pg-stage-rail {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
	gap: var(--wp--preset--spacing--30);
}

.pg-stage-tab {
	display: flex;
	flex-direction: column;
	gap: var(--wp--preset--spacing--30);
	align-items: flex-start;
	text-align: left;
	cursor: pointer;
	padding: var(--wp--preset--spacing--40);
	background-color: var(--wp--preset--color--surface-raised);
	border: 1px solid var(--wp--preset--color--line);
	border-radius: var(--wp--custom--radius--card);
	/* duration-fast (0.2s) is the comp's own timing for the rail
	   (PayGen.dc.html:769). The token was declared and unused. */
	transition: background-color var(--wp--custom--motion--duration-fast) var(--wp--custom--motion--easing),
		border-color var(--wp--custom--motion--duration-fast) var(--wp--custom--motion--easing),
		box-shadow var(--wp--custom--motion--duration-fast) var(--wp--custom--motion--easing);
}

.pg-stage-tab:hover {
	border-color: var(--wp--preset--color--line-emphasis);
	box-shadow: var(--wp--preset--shadow--panel);
}

.pg-stage-tab[aria-selected="true"] {
	background-color: var(--wp--preset--color--base-white);
	border-color: var(--wp--preset--color--accent-blue);
	box-shadow: var(--wp--preset--shadow--card-hover);
}

.pg-stage-tab__num {
	font-family: var(--wp--preset--font-family--mono);
	font-size: var(--wp--preset--font-size--xs-mono);
	letter-spacing: var(--wp--custom--kicker--letter-spacing);
	color: var(--wp--preset--color--muted);
}

.pg-stage-tab[aria-selected="true"] .pg-stage-tab__num {
	color: var(--wp--preset--color--accent-blue);
}

.pg-stage-tab__title {
	font-size: var(--wp--preset--font-size--s);
	font-weight: 600;
	line-height: 1.25;
	color: var(--wp--preset--color--ink);
}

/* --- Spec lists -------------------------------------------
   A plain core list block, two columns, with the green dot
   marker the design uses. A list rather than a lattice on
   purpose: an editor adds a spec by pressing Enter.
   ---------------------------------------------------------- */

.pg-specs {
	list-style: none;
	margin: 0;
	padding: 0;
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(165px, 1fr));
	gap: var(--wp--preset--spacing--30) var(--wp--preset--spacing--40);
}

.pg-specs li {
	position: relative;
	padding-left: var(--wp--preset--spacing--40);
	font-size: var(--wp--preset--font-size--s);
	font-weight: 500;
	line-height: 1.45;
}

.pg-specs li::before {
	content: "";
	position: absolute;
	left: 0;
	top: 0.55em;
	width: var(--wp--preset--spacing--10);
	height: var(--wp--preset--spacing--10);
	border-radius: 50%;
	background-color: var(--wp--preset--color--accent-green);
}

.has-base-navy-background-color .pg-specs li {
	color: var(--wp--preset--color--base-white);
}

/* --- Inset note ------------------------------------------- */

.pg-note {
	background-color: var(--wp--preset--color--surface-inset);
	border-radius: var(--wp--custom--radius--control);
	padding: var(--wp--preset--spacing--30) var(--wp--preset--spacing--40);
}

/* --- "Today" rows, band 3 ---------------------------------
   The mono label is a fixed-width gutter so the statements
   align down the column. Below the flex wrap it stacks, which
   is correct at narrow widths.
   ---------------------------------------------------------- */

.pg-today > .is-style-eyebrow {
	flex: 0 0 auto;
	min-width: 4.5em;
	padding-top: 0.2em;
}

.pg-today > p:last-child {
	flex: 1 1 auto;
	min-width: 0;
}

/* --- Product screenshots, band 6 --------------------------
   Sitting on the navy band, so the frame is a light card with
   a hairline and the caption picks up the on-dark meta colour.
   ---------------------------------------------------------- */

.pg-shot {
	margin: 0;
}

/* The screenshot's border, radius and shadow moved to .pg-shot__frame
   when the chrome bar was added. They must NOT stay on the image: the
   frame already clips with overflow hidden, so a radius here rounds the
   image inside an already-rounded frame and the 1px border draws a
   second line just inside the chrome bar. Caught by the render check —
   the image measured border-radius 5px inside a 5px frame. */

.pg-shot figcaption {
	margin-top: var(--wp--preset--spacing--40);
	font-size: var(--wp--preset--font-size--s);
	line-height: 1.55;
	color: var(--wp--preset--color--on-dark-meta);
	text-align: left;
}

/* --- Spec rows, band 7 ------------------------------------
   Key/value rows. The last row drops its border so the stack
   does not end on a dangling hairline.
   ---------------------------------------------------------- */

.pg-specrows > .wp-block-group:last-child {
	border-bottom: 0 !important;
}

/* --- Footer capability list -------------------------------
   Plain text, deliberately not links: the pages behind these
   no longer exist. Same rhythm as the footer nav columns so
   the four columns read as one row.
   ---------------------------------------------------------- */

.pg-footer-plain {
	list-style: none;
	margin: 0;
	padding: 0;
}

.pg-footer-plain li {
	line-height: 1.45;
}

/* ===========================================================
   PayGen — comp fidelity, round 1 (2026-08-27)
   Every rule below closes a gap recorded in
   design/comp-diff.md. CSS-side only: none of it needs a page
   re-seed, which is why it ships first.
   =========================================================== */

/* --- Navigation hover -------------------------------------
   comp-diff finding 4: 30 of the comp's 73 `style-hover`
   attributes are nav links going #C7D3E6 -> #ffffff, and the
   theme had no hover on any of them.

   THIS CANNOT BE DONE FROM theme.json, which is why it is
   here. Core ships
     .wp-block-navigation .wp-block-navigation-item__content
     .wp-block-navigation-item__content { color: inherit }
   — a deliberately DOUBLED class, specificity (0,3,0). A
   theme.json `core/navigation` elements.link :hover emits
   `:root :where(.wp-block-navigation) a…:hover`, which is
   (0,2,1) and loses. The entry would have parsed fine and
   simply never applied — trap 4's shape exactly. Matching
   core's doubled class and adding :hover gives (0,3,1),
   which wins on specificity rather than on load order.

   White on base-navy is 17.46:1 (scripts/pg-contrast.py).
   ---------------------------------------------------------- */

.wp-block-navigation .wp-block-navigation-item__content.wp-block-navigation-item__content {
	transition: color var(--wp--custom--motion--duration-fast) var(--wp--custom--motion--easing);
}

.wp-block-navigation .wp-block-navigation-item__content.wp-block-navigation-item__content:hover,
.wp-block-navigation .wp-block-navigation-item__content.wp-block-navigation-item__content:focus {
	color: var(--wp--preset--color--base-white);
}

/* --- Text wrapping ----------------------------------------
   comp-diff finding 6. The comp sets `text-wrap: pretty` on
   roughly 25 lede and body paragraphs and `balance` on 14
   headings. The theme had `balance` on .pg-measure-heading
   only — so card h3s, the #live step h3s and the security
   lattice titles were unbalanced, and `pretty` appeared
   nowhere at all.

   Both are progressive enhancements: a browser without
   support ignores them and renders exactly as before.
   ---------------------------------------------------------- */

p {
	text-wrap: pretty;
}

h1,
h2,
h3 {
	text-wrap: balance;
}

/* --- Hero eyebrow pill ------------------------------------
   comp-diff §2. The comp draws the eyebrow as an inline-flex
   pill (PayGen.dc.html:78-81): 1px border, 100px radius,
   7px 14px 7px 10px. Only the pulsing dot and the type
   survived the port; `radius--badge: 100px` was declared and
   referenced nowhere.

   Border uses on-dark-border-strong (0.26) where the comp has
   rgba(255,255,255,0.18). design-system §3.4 records the
   deliberate normalisation of nine white-alpha steps down to
   three, and 0.18 is not one of them — so this reads very
   slightly stronger than drawn, by decision rather than by
   accident.
   ---------------------------------------------------------- */

.pg-live-dot {
	display: inline-flex;
	align-items: center;
	border: 1px solid var(--wp--preset--color--on-dark-border-strong);
	border-radius: var(--wp--custom--radius--badge);
	padding: var(--wp--preset--spacing--20) var(--wp--preset--spacing--40)
		var(--wp--preset--spacing--20) var(--wp--preset--spacing--30);
}

/* The hero ledger's shadow moved INTO .pg-ledger-card below.
   It used to hang off `#top .is-style-card`, and the ledger no
   longer carries that class — the rule would have matched
   nothing and the shadow would have disappeared with no error.
   Recorded because that is the exact shape of trap 7. */

/* --- Light-band hairlines ---------------------------------
   comp-diff §4. The comp puts a 1px #E3E8F1 rule under almost
   every light band (PayGen.dc.html:139, 163, 760, 779, 803,
   861, 883). The theme had none anywhere.

   Applied by anchor rather than by a blanket section rule, so
   it lands only where the comp draws it. The client-story
   band carries no anchor, so it is NOT covered here — that
   one needs markup and is recorded in comp-diff.
   ---------------------------------------------------------- */

#why,
#cycle,
#live,
#faq {
	border-bottom: 1px solid var(--wp--preset--color--line);
}

/* --- #platform ground -------------------------------------
   comp-diff §5: the comp's platform band is #F5F7FB with a
   1px #E3E8F1 rule top AND bottom; the theme shipped it
   white and unruled. Restoring the tint also makes the white
   is-style-card children read as cards again, which is how
   the comp separates them from the band.
   ---------------------------------------------------------- */

#platform {
	background-color: var(--wp--preset--color--surface);
	border-top: 1px solid var(--wp--preset--color--line);
	border-bottom: 1px solid var(--wp--preset--color--line);
}

/* --- FAQ accordion card -----------------------------------
   comp-diff §10 and design-system §7.9. The comp holds every
   row in ONE card — 1px border, 5px radius, overflow hidden —
   with `line-soft` dividers between rows and an #FBFCFE
   trigger hover. The theme shipped seven independent
   <details>, each with its own bottom rule and a 16px gap.

   Rebuilt from the outside in: the sides and radius come from
   :first-of-type / :last-of-type, so the row count can change
   without touching CSS.

   The `!important`s are not opinion — core writes the row
   margin and bottom border as INLINE styles from the block's
   own border and spacing supports, and an inline style cannot
   be overridden any other way. Removing them from the markup
   would cost a page re-seed (trap 2); this does not.
   ---------------------------------------------------------- */

#faq .wp-block-details {
	margin-top: 0 !important;
	border-left: 1px solid var(--wp--preset--color--line);
	border-right: 1px solid var(--wp--preset--color--line);
	border-bottom-color: var(--wp--preset--color--line-soft) !important;
}

#faq .wp-block-details:first-of-type {
	margin-top: var(--wp--preset--spacing--70) !important;
	border-top: 1px solid var(--wp--preset--color--line);
	border-top-left-radius: var(--wp--custom--radius--card);
	border-top-right-radius: var(--wp--custom--radius--card);
}

#faq .wp-block-details:last-of-type {
	border-bottom-color: var(--wp--preset--color--line) !important;
	border-bottom-left-radius: var(--wp--custom--radius--card);
	border-bottom-right-radius: var(--wp--custom--radius--card);
}

#faq .wp-block-details > summary {
	padding: var(--wp--preset--spacing--40) var(--wp--preset--spacing--50);
	cursor: pointer;
	transition: background-color var(--wp--custom--motion--duration-fast) var(--wp--custom--motion--easing);
}

#faq .wp-block-details > summary:hover {
	background-color: var(--wp--preset--color--surface-raised);
}

/* measure--wide (56em) was declared and unused; design-system
   §7.9 names the FAQ answer as its one intended home. */

#faq .wp-block-details > p {
	max-width: var(--wp--custom--measure--wide);
	margin: 0 var(--wp--preset--spacing--50) var(--wp--preset--spacing--50);
}

/* --- Navigation breakpoint --------------------------------
   comp-diff §1. The comp's header collapses to a hamburger at
   1040px; `overlayMenu:"mobile"` gives core's 600px, so
   between 600 and 1040 the theme rendered five links, a phone
   number and a button inline where the comp shows a toggle.
   `layout--nav-breakpoint: 1040px` was declared and unused.

   Core's breakpoint is exactly two declarations, both in
   `@media (min-width: 600px)` in
   wp-includes/blocks/navigation/style.min.css. This undoes
   them across 600-1040 and nothing else. Both selectors are
   core's own plus a leading .wp-block-navigation, so they win
   on specificity, not on stylesheet order — block styles can
   be printed inline and after the theme stylesheet.

   The upper bound is 1039.98px, not 1039px: viewport widths
   are fractional on scaled displays, and a whole-pixel bound
   leaves a dead band.
   ---------------------------------------------------------- */

@media (min-width: 600px) and (max-width: 1039.98px) {
	.wp-block-navigation .wp-block-navigation__responsive-container:not(.hidden-by-default):not(.is-menu-open) {
		display: none;
	}

	.wp-block-navigation .wp-block-navigation__responsive-container-open:not(.always-shown) {
		display: flex;
	}
}

/* ===========================================================
   PayGen — panel-class comp fixes (2026-08-27)
   Six components the comp draws as a bordered or filled panel
   had shipped as bare rows or bare columns. Measurements in
   design/comp-diff.md; the operator listed them by name.
   =========================================================== */

/* --- Hero ledger card -------------------------------------
   comp-diff finding 1. The comp draws a WHITE card
   (PayGen.dc.html:96): 6px radius, a deep shadow, an #F5F7FB
   header strip, then a headline figure and progress bar, then
   the rows. The theme shipped `is-style-card`, which on a navy
   band resolves to the dark `surface-dark` fill, with no
   shadow and no figure at all.

   THE CLASS IS REPLACED, NOT STACKED. The dark override
   `.has-base-navy-background-color .wp-block-group.is-style-card`
   is (0,3,0); a bare `.pg-ledger-card` at (0,1,0) would have
   lost and the card would have stayed dark with no error.

   `color` is set explicitly because the band carries
   `has-base-white-color`: the table cells inherit, and on a
   white card inherited white is invisible. Every colour inside
   this card was re-mapped for that reason — the pills were
   already light-tinted and needed nothing.
   ---------------------------------------------------------- */

.pg-ledger-card {
	background-color: var(--wp--preset--color--base-white);
	color: var(--wp--preset--color--base-navy);
	border-radius: var(--wp--custom--radius--card);
	overflow: hidden;
	box-shadow: var(--wp--preset--shadow--screenshot-on-dark-lg);
}

.pg-ledger-card__head {
	background-color: var(--wp--preset--color--surface);
	border-bottom: 1px solid var(--wp--preset--color--line);
	padding: var(--wp--preset--spacing--30) var(--wp--preset--spacing--50);
}

.pg-ledger-card__figure {
	padding: var(--wp--preset--spacing--50) var(--wp--preset--spacing--50)
		var(--wp--preset--spacing--40);
}

/* Trap 21: a money figure must never break mid-token, and this
   one is the largest on the page. */

.pg-ledger-total {
	font-weight: 600;
	font-size: clamp(2rem, 3.6vw, 2.625rem);
	letter-spacing: -0.02em;
	line-height: 1;
	font-variant-numeric: tabular-nums;
	white-space: nowrap;
	margin: var(--wp--preset--spacing--10) 0 0;
}

.pg-ledger-bar {
	height: 5px;
	margin-top: var(--wp--preset--spacing--30);
	border-radius: var(--wp--custom--radius--badge);
	background-color: var(--wp--preset--color--line);
	overflow: hidden;
}

.pg-ledger-bar__fill {
	height: 100%;
	width: 73%;
	border-radius: var(--wp--custom--radius--badge);
	background-color: var(--wp--preset--color--accent-green);
}

@media (prefers-reduced-motion: no-preference) {
	.pg-ledger-bar__fill {
		transition: width 0.8s cubic-bezier(0.2, 0.7, 0.3, 1);
	}
}

.pg-ledger-meta {
	margin-top: var(--wp--preset--spacing--20);
	white-space: nowrap;
}

/* The rows sit flush to the card edge, so the table supplies
   its own gutter rather than the card padding doing it. */

.pg-ledger-card .pg-ledger {
	border-top: 1px solid var(--wp--preset--color--line);
}

/* --- #live spec panel -------------------------------------
   comp-diff finding 5. The comp draws a #0F2138 panel with a
   1px rgba(255,255,255,0.11) border, 5px radius and hairline
   rows (PayGen.dc.html:932-948). The theme shipped bare rows
   with a light-grey bottom rule on a white band.

   This is a DARK panel on a LIGHT band, so it cannot reuse
   `.pg-lattice`'s dark variant — that is keyed to
   `.has-base-navy-background-color`, and #live is white. The
   on-dark tokens are named here directly.
   ---------------------------------------------------------- */

.pg-specrows {
	background-color: var(--wp--preset--color--surface-dark);
	border: 1px solid var(--wp--preset--color--on-dark-border);
	border-radius: var(--wp--custom--radius--card);
	overflow: hidden;
	box-shadow: var(--wp--preset--shadow--panel);
}

.pg-specrows > .wp-block-group {
	border-bottom: 1px solid var(--wp--preset--color--on-dark-border);
	padding: var(--wp--preset--spacing--40) var(--wp--preset--spacing--50);
	margin: 0;
}

.pg-specrows > .wp-block-group:last-child {
	border-bottom: 0;
}

/* --- #live step lattice -----------------------------------
   comp-diff §7. The comp draws the three steps as ONE lattice
   — white cells, 1px #E3E8F1 hairlines, 5px radius, overflow
   hidden (PayGen.dc.html:293-310). The theme shipped three
   bare columns.

   Built on `.pg-lattice`, so the hairlines come from each
   cell's own border-top and border-left. The comp itself uses
   `gap: 1px` over a coloured container, which design-system
   §7.10 forbids as a build rule: an auto-fit track can resolve
   to an orphan cell, and the container then paints through as
   a grey slab. Same look, no orphan.

   NOTE for a later pass: three items under auto-fit has a 2+1
   orphan window, which §7.10's pairing rule warns about. The
   per-cell borders keep that from breaking, but the comp's own
   260px minimum is kept here so the wrap point matches.
   ---------------------------------------------------------- */

.wp-block-columns.pg-steps {
	grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr));
}

.pg-steps > .wp-block-column {
	background-color: var(--wp--preset--color--base-white);
	padding: clamp(1.75rem, 3vw, 2.375rem);
}

/* --- Product screenshot frames ----------------------------
   comp-diff finding 8. The comp wraps each screenshot in a
   white frame with a browser chrome bar — three #D9E1EE dots
   and a mono label — over a deep shadow (PayGen.dc.html:997).
   The theme shipped a bare 1px border.

   The border, radius and shadow live on the FRAME, not the
   image: the frame clips with overflow hidden, and rounding
   both would double the corner.

   The dots are one element, not three: a repeating radial
   gradient at the size of the dot pitch. `state-inactive`
   (#D9E1EE) is exactly the comp's dot colour and was on the
   orphaned-token list.
   ---------------------------------------------------------- */

.pg-shot {
	margin: 0;
}

.pg-shot__frame {
	background-color: var(--wp--preset--color--base-white);
	border-radius: var(--wp--custom--radius--card);
	overflow: hidden;
	box-shadow: var(--wp--preset--shadow--screenshot-on-dark);
}

.pg-shot__chrome {
	display: flex;
	align-items: center;
	gap: var(--wp--preset--spacing--20);
	margin: 0;
	padding: var(--wp--preset--spacing--20) var(--wp--preset--spacing--30);
	background-color: var(--wp--preset--color--surface);
	border-bottom: 1px solid var(--wp--preset--color--line);
	color: var(--wp--preset--color--muted);
	text-transform: none;
	letter-spacing: 0;
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}

.pg-shot__chrome::before {
	content: "";
	flex: 0 0 auto;
	width: 36px;
	height: 8px;
	background-image: radial-gradient(
		circle at 4px 4px,
		var(--wp--preset--color--state-inactive) 4px,
		transparent 4px
	);
	background-size: 12px 8px;
	background-repeat: repeat-x;
}

.pg-shot__img {
	margin: 0;
}

.pg-shot__img img {
	display: block;
	width: 100%;
	height: auto;
}

.pg-shot__cap {
	margin-top: var(--wp--preset--spacing--40);
	line-height: 1.55;
}

/* --- "TODAY" chips ----------------------------------------
   comp-diff §3. The comp draws an inset chip — #F5F7FB, 3px
   radius, 11px 13px (PayGen.dc.html:968). The theme shipped a
   ruled list, which is a treatment the comp never uses here.
   ---------------------------------------------------------- */

.pg-today {
	background-color: var(--wp--preset--color--surface);
	border-radius: var(--wp--custom--radius--control);
	padding: var(--wp--preset--spacing--30);
}

/* --- Client story attribution -----------------------------
   comp-diff §9. The comp marks the attribution with a
   34x2px green bar (PayGen.dc.html:338).

   ⚠️ The quote ALSO carries a 2px accent-green LEFT rule from
   theme.json, which design-system §11.8 records as borrowed
   from the stat block — and comp-diff notes the comp has no
   left rule, the bar being what it replaced. The operator
   asked for the bar and listed the quote's rule as
   do-not-touch, so BOTH now ship. Two green marks on one
   quote is a live question, not an oversight.

   The comp's 40px client logo is NOT carried: there is no
   logo-decorative-materials asset in assets/img.
   ---------------------------------------------------------- */

.wp-block-quote cite {
	display: block;
}

.wp-block-quote cite::before {
	content: "";
	display: block;
	width: 34px;
	height: 2px;
	margin-bottom: var(--wp--preset--spacing--30);
	background-color: var(--wp--preset--color--accent-green);
}

/* --- Measure caps must not centre ---------------------------
   MEASURED, not inferred. At a 1416px viewport, inside band
   `#security`:

     eyebrow            left  60.5   max-width 1280   margin 20.5 / 20.5
     h2  .pg-measure-heading  left 280.5   max-width  840   margin 240.5 / 240.5
     p   .pg-measure-body     left 309.5   max-width  782   margin 269.5 / 269.5
     p   .pg-measure-body     left 344.0   max-width  713   margin  304  / 304

   FOUR left edges in one band, and the equal left/right margins
   name the cause exactly: they are AUTO margins.

   The mechanism is core's constrained layout, the same rule that
   mis-sized the canvas hosts. It emits

     <sel> > :where(:not(.alignleft):not(.alignright):not(.alignfull))
       { max-width: <contentSize>; margin-left: auto !important;
         margin-right: auto !important }

   on EVERY direct child of a constrained container. A child whose
   own max-width is NARROWER than the content size — which is the
   entire job of `.pg-measure-*` — is then centred in the leftover
   space. The wider the measure, the smaller the offset, which is
   why the heading (840px) sits left of the body (782px) and the
   second body paragraph (713px, no lede size, so 46em resolves
   smaller) sits right of both. The band reads as a staircase.

   The comp does none of this: its bands are a left-aligned grid
   column and its `max-width: 34em` on the lede is a measure cap
   in normal flow, which never moves a left edge
   (PayGen.dc.html:314-320).

   `!important` is required to beat core's own `!important`, and
   the class is doubled so the win is on specificity — (0,2,0)
   against core's (0,1,0) — rather than on stylesheet order, which
   is not dependable when block styles can print inline and after
   the theme stylesheet.

   `margin-left: 0` IS THE WRONG FIX, and was tried first. It
   moved the measure elements to 40.0px while the full-width
   children stayed at 60.5px — a NEW misalignment, 20.5px the
   other way. That 20.5px is the container's OWN centring: the
   section's content box is 1321px at this viewport, the content
   size is 1280px, and core splits the 41px difference. A
   full-width child is centred by exactly that much, so the text
   column starts 20.5px in from the padding edge.

   So the measure elements must reproduce that offset, not
   discard it: `max(0px, (100% - contentSize) / 2)`, where 100%
   is the container's content box. Below the content size the
   expression clamps to 0 and every child — measure-capped or
   not — sits flush at the padding edge, which is why the narrow
   viewports were already passing.

   `!important` is required to beat core's own `!important`, and
   the class is doubled so the win is on specificity — (0,2,0)
   against core's (0,1,0) — rather than on stylesheet order,
   which is not dependable when block styles can print inline
   and after the theme stylesheet.

   pg-render-check.sh now asserts every band has ONE left edge,
   so neither this nor the over-correction can come back quietly.
   ---------------------------------------------------------- */

.pg-measure-heading.pg-measure-heading,
.pg-measure-body.pg-measure-body,
.pg-measure-lede.pg-measure-lede {
	margin-left: max(
		0px,
		calc((100% - var(--wp--style--global--content-size, 1280px)) / 2)
	) !important;
	margin-right: auto !important;
}

/* --- Back to top ------------------------------------------
   Ported from portalgen's "Back to top" section, which exists
   ONLY on the portalgennow server and not in that repo —
   docs/portalgen-drift-20260908.md. DOM injected by
   assets/js/paygen-top.js.

   ⚠️ The hidden state is `visibility`, NOT `opacity` alone.
   This is portalgen's detail and it is load-bearing:
   `opacity: 0` leaves a fully focusable link sitting over the
   footer, so a keyboard user tabs into an invisible control.
   The pair lets it FADE (opacity transitions) while still
   leaving the tab order (visibility flips at transition end).

   ⚠️ Shown at EVERY width — divergence 2. portalgen hides it
   below 641px because its phone-only sticky CTA bar owns this
   corner; PayGen has no sticky bar, so there is nothing to
   yield to and a narrow viewport needs this control most.

   z-index sits well below the skip link (100000), which must
   always win: a floating control must never cover the first
   thing a keyboard user reaches.

   No motion rule is needed here. theme.json's global
   `prefers-reduced-motion: reduce` block already forces every
   transition-duration to 0.01ms, and `scroll-behavior: smooth`
   is gated on `no-preference` in the smooth-scroll section
   above. Both were verified rather than assumed.
   ---------------------------------------------------------- */

.pg-top {
	position: fixed;
	right: var(--wp--preset--spacing--60);
	bottom: var(--wp--preset--spacing--60);
	z-index: 35;
	display: flex;
	align-items: center;
	justify-content: center;
	/* border-box so the 1px border sits INSIDE the 44px token. Without it the
	   border is added outside and the control measures 46x46 — still above the
	   44px minimum, but no longer the token's value, and no longer portalgen's
	   measured 44. Verified in the browser both ways. */
	box-sizing: border-box;
	width: var(--wp--custom--control--touch-target);
	height: var(--wp--custom--control--touch-target);
	padding: 0;
	border: 1px solid var(--wp--preset--color--line);
	border-radius: 50%;
	background-color: var(--wp--preset--color--base-white);
	color: var(--wp--preset--color--link);
	box-shadow: var(--wp--preset--shadow--raised);
	opacity: 0;
	visibility: hidden;
	transition:
		opacity var(--wp--custom--motion--duration-fast) var(--wp--custom--motion--easing),
		visibility var(--wp--custom--motion--duration-fast),
		background-color var(--wp--custom--motion--duration-fast) var(--wp--custom--motion--easing),
		border-color var(--wp--custom--motion--duration-fast) var(--wp--custom--motion--easing);
}

.pg-top.is-visible {
	opacity: 1;
	visibility: visible;
}

/* The chevron must not pick up the underline the theme puts on
   links in body copy, and the box must not inherit link
   text-decoration on hover either. */
.pg-top,
.pg-top:hover,
.pg-top:focus {
	text-decoration: none;
}

.pg-top:hover {
	background-color: var(--wp--preset--color--link);
	border-color: var(--wp--preset--color--link);
	color: var(--wp--preset--color--base-white);
}

/* 🔴 FOCUS RING SHAPE OVERRIDE — required, not cosmetic.
   theme.json's global `:focus-visible` rule sets
   `border-radius: var(--wp--custom--radius--pill)`, which is
   2px. On a 50%-radius circle that draws a near-rectangular
   ring around a round target, which reads as a rendering bug.
   Only the RADIUS is restated; colour, width and offset stay
   inherited from the global rule so this cannot drift from it. */
.pg-top:focus-visible {
	border-radius: 50%;
}

/* The scroll target carries tabindex="-1" so fragment
   navigation moves focus as well as scroll position. It is a
   destination, not a control, so it takes no visible ring of
   its own — paygen-top.js sets outline:none on it for the same
   reason. Declared here too so the intent survives a reading of
   the stylesheet alone. */
#pg-top:focus,
#pg-top:focus-visible {
	outline: none;
}
