/* Counter section — layout and static typography.
 * assets/js/counter-reel.js owns the slot-machine reel: it reads the plain
 * text inside each .idia-counter__value, builds ten stacked digit columns
 * per position inside .idia-counter__digit-window, and drives the one-shot
 * GSAP ScrollTrigger tween. This file only supplies the geometry the reel
 * animates inside of, plus the section's static typography — the number
 * renders correctly as plain text with JavaScript off or with the reel
 * never built (docs/step-13-counter-section.md, Progressive enhancement).
 *
 * Section padding (120px top) is set inline via the spacing|120 token in
 * the pattern, matching how the gallery and marquee patterns set their own
 * top padding — nothing to repeat here.
 */

/* Grid: repeat(4, 1fr) with a 48px gap, not four fixed 308px columns. At the
   reference's own 1376px content width these are numerically identical
   (4 x 308 + 3 x 48 = 1376), but 1fr survives the owner adding a fifth
   statistic without anyone touching this file — a fixed track would not.
   The 4-column track comes from core/group's own grid layout support
   (columnCount:4 in the pattern, which WordPress renders as
   grid-template-columns: repeat(4, minmax(0, 1fr)) inline — equivalent to a
   plain 1fr track at any width this section is used); the 48px gap is the
   block's own editable blockGap (spacing|48), not a rule in this file — see
   AGENTS.md §8.4, "grids take their column gap from blockGap or a spacing
   token." Nothing to add here for either. */

/* Rail padding for CONTENT (the pattern's point 2). WRAPPER (.idia-counter) is
   align:full so the section background reaches the true viewport edge — but
   that means WRAPPER itself is has-global-padding, and WordPress's de-dup
   rule zeroes a nested has-global-padding descendant's own padding rather
   than letting it re-apply. Read here directly from --wp--custom--rail
   instead of relying on the automatic re-application, the same escape
   gallery.css's `.idia-gallery__title-block` and marquee.css's
   `.idia-marquee__content` already use for the identical structure. Steps to
   20px at ≤767px because --rail itself steps in style.css — no separate
   breakpoint override needed here.

   Compound selector: the de-dup zeroing rule itself
   (`.has-global-padding :where(:not(...) > .has-global-padding...)`) carries
   one class of real specificity via its outer `.has-global-padding` — the
   `:where()` part contributes none — which ties a plain
   `.idia-counter__content` rule (also one class), and global-styles-inline-
   css is printed after every enqueued theme stylesheet including this one,
   so it wins the tie by source order. Compounding with `.has-global-padding`,
   the class the rule itself targets, beats it the same way header.css beats
   the nav's inline flex CSS and the divider rule beats theme.json's
   core/separator global style. */
.idia-counter__content.has-global-padding {
	padding-left: var(--wp--custom--rail);
	padding-right: var(--wp--custom--rail);
}

.idia-counter__stat {
	min-width: 0;
}

/* The reel window: 90px tall while each digit glyph is 105.6px (xx-large's
   line-height), so the glyph is slightly clipped top and bottom by design —
   reproduced deliberately, not a bug. overflow:clip (not hidden) matches the
   reference and additionally never creates a scroll container. width:100%
   plus min-width:0 on .idia-counter__stat (below) lets the window shrink to
   its grid column's actual width rather than the flex row's default
   shrink-to-fit sizing, which otherwise left a 3-digit value like "100%"
   narrower than its own text and forced a wrap to a second line — the
   window's fixed 90px height then clipped mid-glyph instead of top/bottom.
   white-space:nowrap on .idia-counter__value (below) is the other half of
   that fix: the number is allowed to overflow its column horizontally
   rather than wrap, matching the reference, where every digit-window is
   sized to its own longest value rather than a shared fixed width. */
/* align-items: WordPress's core block-library CSS ships a base
   `.is-layout-flex{flex-wrap:wrap;align-items:center}` rule, printed inline
   after every enqueued theme stylesheet including this one — at equal
   specificity (one class each), source order wins, so a plain
   `.idia-counter__digit-window{align-items:flex-start}` rule here lost that
   fight silently (docs/step-13b-counter-fixes.md, Defect 1, Cause A):
   confirmed centring a 1055.9px-tall reel inside the 90px window, starting
   it roughly 483px above the clip before any transform ran. Fixed the same
   way hero-card.css beats a core-generated class — compound the selector
   with .is-layout-flex, the class core's own rule matches, so two classes
   beats core's one without needing !important. */
.idia-counter__digit-window.is-layout-flex {
	width: 100%;
	height: 90px;
	overflow: clip;
	margin-bottom: var(--wp--preset--spacing--8);
	align-items: flex-start;
}

/* .idia-counter__value is the authored plain-text fallback AND the source
   counter-reel.js reads to build the reel. Non-heading (a <p>) on purpose —
   see the pattern file's point 5 for why an <h2> at weight 600 would
   conflict with AGENTS.md §9.3. When the script builds a reel it hides this
   node with visibility:hidden rather than display:none or removing it, so
   its box still reserves layout space and a screen reader still has a
   single readable number rather than ten stacked decorative digits. */
.idia-counter__value {
	margin: 0;
	line-height: var(--wp--custom--line-height--h-1);
	letter-spacing: var(--wp--custom--letter-spacing--h-1);
	color: var(--wp--preset--color--main);
	white-space: nowrap;
}

.idia-counter__digit-window.has-reel .idia-counter__value {
	visibility: hidden;
	position: absolute;
}

/* Suffix (% or +) sits at a slightly different letter-spacing than the
   digits in the reference (-3.84px for %, normal for +) — both measured
   values are close enough to the digit's own -4.032px that reproducing the
   distinction would cost a raw px literal for no visible difference at this
   size, so the suffix inherits the digit letter-spacing rather than adding
   a second untokened value. */
.idia-counter__suffix {
	display: inline-block;
}

/* Reel columns built at runtime by counter-reel.js. One .idia-counter__reel
   replaces .idia-counter__value's role visually (the original stays in the
   DOM, hidden, per above) — each .idia-counter__reel-column is one 0-9
   stack, translated by the script's GSAP tween, never by a CSS transition,
   so a reel with reduced motion requested is simply never built. */
.idia-counter__reel {
	display: flex;
	align-items: flex-start;
}

.idia-counter__reel-column {
	display: flex;
	flex-direction: column;
	align-items: center;
	will-change: transform;
}

.idia-counter__reel-digit {
	margin: 0;
	font-size: var(--wp--preset--font-size--xx-large);
	font-weight: 600;
	line-height: var(--wp--custom--line-height--h-1);
	letter-spacing: var(--wp--custom--letter-spacing--h-1);
	color: var(--wp--preset--color--main);
}

/* Divider — 1px dashed `secondary` (#5d5d5d). Deliberately NOT the
   marquee's border-light (#e6e6e6): AGENTS.md §9.3 and the reference both
   keep these two dashed rules visually distinct. core/separator renders as
   an <hr> with its own default border-color; overridden here rather than
   via the block's own color control so the value stays traceable to the
   `secondary` preset instead of a picker-selected swatch that could drift.

   theme.json's own global style for core/separator prints as
   `:root :where(.wp-block-separator){border-width:1px;border-style:dashed;
   color:var(--wp--preset--color--border-light)}` — the :where() wrapper
   contributes zero specificity, but :root does not, so the full selector's
   specificity (0,0,1,0) TIES a plain `.idia-counter__divider` rule (also
   0,0,1,0), and this global-styles block is printed after every enqueued
   theme stylesheet including this one, so it won the tie by source order —
   same class of fight already documented in marquee.css, gallery.css, and
   header.css. Measured before this fix: border-style computed
   `dashed dashed solid` and border-color `#5d5d5d #e6e6e6 #e6e6e6` — only
   the top edge (set here) actually won; left/right/bottom silently fell
   through to the global rule's border-light regardless of how the reset was
   written, because a single class can only tie, never beat, `:root
   :where()`. Fixed by compounding with `.wp-block-separator`, the class the
   global rule itself targets, so two classes beats its one. */
.idia-counter__divider.wp-block-separator {
	border-style: dashed;
	border-width: 1px 0 0 0;
	border-color: var(--wp--preset--color--secondary);
	margin: var(--wp--preset--spacing--16) 0 var(--wp--preset--spacing--24);
	width: 100%;
}

.idia-counter__stat-content {
	width: 100%;
}

/* line-height and letter-spacing: theme.json's styles.elements.h5 carries
   these alongside the h-5 font-size preset, but only applies to a literal
   <h5> tag — this is a <p> (not a heading; see the pattern file's point 5
   for why), so the element style never reaches it. Read the same custom
   properties elements.h5 itself resolves from directly, matching the
   reference's measured 31.2px / -1.2px (docs/step-13b-counter-fixes.md)
   rather than leaving the paragraph at its body defaults. */
.idia-counter__title {
	margin: 0;
	line-height: var(--wp--custom--line-height--h-5);
	letter-spacing: var(--wp--custom--letter-spacing--h-5);
}

.idia-counter__description {
	margin: 0;
}

/* !important on both breakpoint rules below: WordPress prints this block's
   own grid-template-columns as generated per-instance CSS
   (.wp-container-core-group-is-layout-*) after every enqueued theme
   stylesheet — same specificity fight documented in marquee.css,
   gallery.css, and header.css. A plain class rule inside a media
   query still loses to that later, equal-specificity rule. */
@media (max-width: 991px) {

	.idia-counter__grid {
		grid-template-columns: repeat(2, 1fr) !important;
	}
}

@media (max-width: 767px) {

	.idia-counter__grid {
		grid-template-columns: 1fr !important;
	}
}

/* Reduced motion: counter-reel.js builds no reel columns at all when this is
   requested — .idia-counter__value renders at rest, exactly as it does with
   JavaScript off. Nothing to override here. */

/* ---- Stat card entrance — starting state ----
   Standard "Fade In" family (blur + rise + fade — same mechanism as the hero
   and CTA), applied to each card wrapper as a 0/200/300/400ms stagger down
   the row. This is a SEPARATE ScrollTrigger from the digit-reel tween above
   — counter-reel.js's own ScrollTrigger animates .idia-counter__reel-column
   (built at runtime); this one animates .idia-counter__stat (authored in the
   pattern) — the card fades in and its number spins on the same scroll
   trigger but as two unrelated animations, never merged into one timeline.
   See animation-map-remaining-sections.json, counter section. Opt-in only:
   scoped to prefers-reduced-motion: no-preference, so a reduced-motion
   visitor's cards render complete and settled immediately — counter-reel.js
   independently checks the same media query before running this tween.

   Scoped to `.idia-counter .idia-counter__stat`, NOT a bare
   `.idia-counter__stat` — that class is also reused unmodified by
   patterns/project-detail-body.php's own four-column stat grid, which does
   NOT sit inside `.idia-counter` and has no title-block or badge of its own.
   counter-reel.js's initCardReveal() only ever runs for sections matching
   `.idia-counter` (see initInstance()), so a bare selector would have left
   every stat card on that page permanently invisible with nothing to
   animate it back out — the exact leak documented in work.css for
   `.idia-work__card` on the Projects/project-detail pages. */
@media (prefers-reduced-motion: no-preference) {

	.idia-counter .idia-counter__stat {
		opacity: 0;
		transform: translateY(50px);
		filter: blur(5px);
	}
}
