/**
 * YARDLINE — composable field blocks.
 *
 * HARD CEILING: 280 LINES. Currently 246.
 *
 * A plugin stylesheet is allowed only for what an attribute structurally cannot
 * reach. If this file passes the ceiling, the design has leaked back out of the
 * editor and into CSS, which is the exact failure this architecture corrects.
 * (The ceiling moved 200 → 280 on 2026-08-26 for two new CATEGORIES that meet
 * the same test — un-addressable wrappers and runtime STATE classes — not for
 * design values. Audit every raise against the list below.)
 *
 * Deliberately tiny, and it must stay that way.
 *
 * A field block renders ONE element carrying ONE value, so everything about it
 * that a buyer might want to change — size, colour, weight, spacing, radius,
 * shadow — is a Stepfox attribute on that element and belongs in the theme's
 * generator, not here. The only things in this file are the ones an attribute
 * genuinely cannot express:
 *
 *   · fitting an <img> inside the box the buyer sized
 *   · tabular figures on a ticking clock
 *   · a link inheriting the colour set on its parent field
 *   · the provider's un-addressable .sfgi-loop-grid wrapper (README-audit §a1)
 *   · runtime state classes the renderer stamps per request — .is-empty,
 *     .is-pending, .is-winner, .is-cover — which no attribute can select on
 *
 * If this file starts growing flex, grid or colour rules, the design has leaked
 * back out of the editor and into a stylesheet, which is the exact failure this
 * whole architecture exists to correct.
 */

/* ---------------------------------------------------------------- images --
 * The theme sizes the FIELD (a div). WordPress prints width/height attributes
 * on the <img> from the attachment, so without this the crest renders at its
 * natural 600px inside a 128px box, or at some arbitrary intrinsic size.
 * `contain` rather than `cover`: a crest must never be cropped. */
.sfgi-f-crest,
.sfgi-f-champ-crest,
.sfgi-f-player-photo {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	overflow: hidden;
}

.sfgi-f-crest img,
.sfgi-f-crest a,
.sfgi-f-champ-crest img,
.sfgi-f-champ-crest a,
.sfgi-f-player-photo img,
.sfgi-f-player-photo a {
	display: block;
	width: 100%;
	height: 100%;
}

.sfgi-f-crest img,
.sfgi-f-champ-crest img {
	object-fit: contain;
}

/* A player portrait fills its square and is anchored on the face, which sits
 * above centre in the 600px source tile. */
.sfgi-f-player-photo img {
	object-fit: cover;
	object-position: 50% 22%;
}

/* ----------------------------------------------------------------- links --
 * A field's colour is set on the field. Core gives descendant links their own
 * colour, so without this a linked club name ignores the buyer's choice — the
 * `isLink` lesson, one level down. */
.sfgi-f a {
	color: inherit;
	text-decoration: none;
}

.sfgi-f a:hover {
	color: inherit;
}

/* ------------------------------------------------------------- countdown --
 * gridiron/game-kickoff in countdown format renders ONE element containing
 * one string ("6d 09h"), which is exactly the one-element rule working as
 * intended: its size, face and colour are the theme's responsiveStyles, not
 * this file's business. An earlier version of this stylesheet styled
 * .sfgi-cd-cell tiles that the block never emits — dead rules that matched
 * nothing, the same class of drift this architecture exists to prevent.
 * Tabular figures are the one thing an attribute cannot set, so that a
 * ticking clock does not jitter as the digits change. */
.sfgi-f-kickoff.is-countdown {
	font-variant-numeric: tabular-nums;
}

/* ------------------------------------------------------- empty and loops --
 * A field with nothing to say must take up no room, or a card grows a gap
 * wherever a game has no broadcaster or a club has no seed. */
.sfgi-f.is-empty {
	display: none;
}

/* …except the jersey number, which is an alignment COLUMN rather than a fact
 * about one player. A roster is a list of rows that must line up, so a player
 * with no number still needs the cell: collapsing it pulled the whole row 38px
 * left (the 26px cell plus its gap), dropping the headshot into the number
 * column and breaking the name and college alignment for that row alone.
 *
 * `visibility` rather than a width, so this reserves space only where the
 * author actually sized the cell; an unsized empty number is still 0 wide. */
.sfgi-f-player-number.is-empty {
	display: block;
	visibility: hidden;
}

/* Loop items are transparent by design: the CARD inside them is the thing the
 * buyer styles, so the wrapper must not add a box of its own. */
.sfgi-loop-item {
	display: contents;
}

/* …except when the loop itself is the flex rail (the ticker), where the item
 * has to remain a real flex child. */
.sfgi-loop--sides > .sfgi-loop-item,
.sfgi-scroll > .sfgi-loop-item {
	display: block;
}

/* A knockout bracket's rounds rail. The provider's .sfgi-loop-grid wrapper is
 * the one element no theme attribute can address (README-audit §a1), and a
 * bracket needs its later rounds VERTICALLY CENTRED against the first — which
 * floats, the theme's reach-through workaround, cannot express. This rule is
 * structural only: it makes the wrapper a wrapping flex rail so the round
 * columns become flex items, and every DESIGN decision — widths, gutters and
 * the centring itself (align_self on the round column) — stays a Stepfox
 * attribute in the theme. Floats a theme still sets on the columns are inert
 * here, and keep the old left-to-right layout if this rule is ever absent. */
.sfgi-loop--rounds > .sfgi-loop-grid {
	display: flex;
	flex-wrap: wrap;
}

/* The whole-card game link (gridiron/game-link with cover on). A card full of
 * club anchors cannot itself be an anchor — nested <a> is invalid and browsers
 * split it — so the block renders an empty anchor and these rules stretch it
 * over the nearest positioned ancestor: the card, which sets position:relative
 * as an ordinary Stepfox attribute. Purely structural — where the cover
 * reaches is decided by which block carries the position, in the editor. */
.sfgi-f-link.is-cover {
	position: absolute;
	inset: 0;
}

.sfgi-f-link.is-cover > a {
	position: absolute;
	inset: 0;
	z-index: 1;
}

/* Club and player links inside a covered card stay clickable above the cover.
 * The list has to name every field that renders its own anchor, or that anchor
 * sits UNDER the cover and the cover's destination wins the click — which is
 * how a club crest inside a player card would start opening the player. */
.sfgi-f-crest > a,
.sfgi-f-champ-crest > a,
.sfgi-f-name > a,
.sfgi-f-player-name > a,
.sfgi-f-player-team > a {
	position: relative;
	z-index: 2;
}

/* The cover itself: same contract as .sfgi-f-link, for the two entity links. */
.sfgi-f-player-link.is-cover,
.sfgi-f-team-link.is-cover {
	position: absolute;
	inset: 0;
}

.sfgi-f-player-link.is-cover > a,
.sfgi-f-team-link.is-cover > a {
	position: absolute;
	inset: 0;
	z-index: 1;
}

/* Before kick-off `game-score` prints an em-dash (`.is-pending`, its own state
 * class contract). Dimmed so a scheduled face-off reads "no score yet", not as
 * a nil-nil draw sitting at full weight. */
.sfgi-f-score.is-pending {
	opacity: 0.35;
}

/* A final's winning score carries `.is-winner` — a state no attribute can
 * target. Additive warm glow only (the monolithic game hero's treatment);
 * the theme keeps ownership of the colour itself. */
.sfgi-f-score.is-winner {
	text-shadow: 0 0 26px rgba(255, 201, 60, 0.5);
}

/* A chip whose value field resolved empty is a caption over nothing — the
 * masthead's "Line" pill on a final, a "TV" pill with no broadcaster. The
 * field already hides itself (`.is-empty` above); this folds away the shell
 * around it. !important because the chip's own Stepfox layout rule arrives as
 * `#block_x{display:flex}` — an id selector this class rule cannot outrank. */
.sfgi-tile:has(> .sfgi-f.is-empty) {
	display: none !important;
}

/* The competition card rail. `.sfgi-loop-grid` is the wrapper the provider emits
 * and no attribute can reach; with no rule at all it is a plain block box, so the
 * theme's only way to put cards side by side is a float on the CARD — and floated
 * cards cannot share a height. On /gridiron/ the first row ends ragged because one
 * cup has no champion yet and its champion strip is missing.
 *
 * Structural only. Making the wrapper a wrapping flex rail turns the cards into
 * flex items, where the float is inert, and the initial `align-items: stretch`,
 * named here for the reader, gives every card on a line the same height. Every
 * DESIGN value stays a Stepfox attribute: the card's own flex-basis, gutters and
 * gaps all outrank the fallback below.
 *
 * The fallback gives `--sfgi-cols` a meaning — it is the block's `columns`
 * attribute — so a loop the theme has not given a width to still gets one card per
 * column. At `--sfgi-cols:1` (the /tournaments/ and competition-archive loops) that
 * is 100%, i.e. exactly the full-width stack those two pages render today. */
.sfgi-loop--competitions > .sfgi-loop-grid {
	display: flex;
	flex-wrap: wrap;
	align-items: stretch;
}

.sfgi-loop--competitions > .sfgi-loop-grid > .sfgi-loop-item > * {
	flex-basis: calc(100% / var(--sfgi-cols, 1));
}

/* A shell whose every field resolved empty: the competition card's champion strip
 * on a cup nobody has won yet, left as a hairline rule over a dead band once both
 * fields hide themselves (`.sfgi-f.is-empty` above). `.sfgi-tile` folds away for
 * exactly this reason, but a tile brings a padding box and a ring with it; this is
 * the same contract with no look of its own, for a shell the theme styles itself.
 *
 * Opt-in, so the plugin decides nothing: the theme adds `sfgi-fold-empty` to the
 * group. `:has(> .sfgi-f)` keeps it off a shell holding no field at all, and the
 * `:not(:has(…))` folds it only when NOT ONE of its fields has a value — a champion
 * with a name but no crest still shows. !important because the shell's own Stepfox
 * layout rule arrives as `#block_x{display:flex}`, an id selector this class rule
 * cannot outrank. */
.sfgi-fold-empty:has(> .sfgi-f):not(:has(> .sfgi-f:not(.is-empty))) {
	display: none !important;
}

/* ------------------------------------------------------ editor preview --
 * In the canvas a field is wrapped by useBlockProps and then by the span the
 * preview injects, so the size the buyer sets lands on the OUTER div while the
 * crest inside stays at its intrinsic size — the block looked correct on the
 * front end and tiny in the editor. display:contents removes the span from the
 * box tree so the field is sized by the block it belongs to. */
.sfgi-ed-field > span {
	display: contents;
}

/* Only a MEDIA field needs this box. The wrapper exists so the size the buyer
 * set lands somewhere the image can fill, which is a crest or a photo — nothing
 * else in the set has an intrinsic size to centre. Applying it to a TEXT field
 * shrank the field to its content and centred it, so a team name read as centred
 * in the canvas while the front end left it at the start of its line. That gap
 * between editor and site is the bug; the front end never had these rules.
 *
 * The selectors reach THROUGH the preview span (which is display:contents), so
 * they are descendant combinators. A child combinator cannot match here — the
 * span is still in the DOM even though it is out of the box tree. */
.sfgi-ed-field:has(.sfgi-f-crest),
.sfgi-ed-field:has(.sfgi-f-champ-crest),
.sfgi-ed-field:has(.sfgi-f-player-photo) {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: 1em;
	min-height: 1em;
}

.sfgi-ed-field > .sfgi-f-crest,
.sfgi-ed-field > .sfgi-f-player-photo {
	width: 100%;
	height: 100%;
}

/* ------------------------------------------------------- editor: loop rows --
 * The loop's own responsiveStyles — grid-template-columns, gap, flex-direction —
 * land on the loop element. On the front end the CARDS are its grid items,
 * because each .sfgi-loop-item between them is display:contents. The canvas has
 * two wrappers in the same position: the block-list layout div holding the live
 * card, and one preview div per extra row. Both must vanish from the box tree
 * for the same reason, or the whole loop collapses into a single block-level
 * column and a two-column grid of cards renders as one card per line.
 *
 * This is also why the extra rows must start at item 2. With these wrappers
 * transparent, a preview of item 1 alongside the live item 1 would put both
 * copies' fields on the SAME flex line — which is exactly what "No No data data
 * for for this this field field" was, in an earlier attempt at this. */
.sfgi-ed-loop-inner,
.sfgi-ed-row {
	display: contents;
}

/* A read-only preview row must read like the front end, and the front end simply
 * omits a field with nothing to say. "No data for this field yet" is a message
 * for the person editing the LIVE card — it tells them the block is there and
 * which row has no value — so it stays on that one and is dropped from the
 * copies, where nine of them would be noise. */
.sfgi-ed-row .sfgi-ed-empty {
	display: none;
}

.sfgi-ed-loading,
.sfgi-ed-empty {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	font-size: 11px;
	color: var( --wp--preset--color--muted, #8b97ad );
}

/* ------------------------------------------------------------ name fields --
 * A club or player name must never break INSIDE the word.
 *
 * `min-width: 0` is the standard flex trick that lets a sibling scroll
 * container work, and it is correct on a container. Applied to a text field in
 * a narrow table cell it lets the box shrink to nothing, and the browser then
 * breaks the only word it has — "Patriots" rendered as eight stacked letters in
 * the cup group table. No attribute can express "wrap between words but never
 * inside one", so it lives here, once, for every name field. */
.sfgi-f-name,
.sfgi-f-player-name {
	overflow-wrap: normal;
	word-break: keep-all;
	hyphens: none;
}

/*
 * EDITOR PREVIEWS ARE NOT CLICKABLE.
 *
 * A preview injects the real front-end markup, so a club card carries a real
 * link. The editor does not manage markup it did not create, so those anchors
 * stayed live and clicking a card navigated the canvas away from the template
 * being edited, stranding the author on an error page.
 *
 * `href` is already renamed to `data-sfgi-href` by stepfox_gi_preview_inert()
 * on the preview routes; this covers anything that route does not reach and
 * makes the preview transparent to the pointer, so the click lands on the
 * block wrapper and SELECTS the block — what an author clicking a card wants.
 *
 * `sfgi-ed-*` wrappers only exist in the editor, so this is inert on the
 * published site.
 */
/* The block wrapper class is the editor-only scope: it never exists on the
 * published site, so these rules cannot reach a real visitor's links. Both
 * the preview wrapper (sfgi-ed-*) and the rendered component itself (sfgi-*)
 * are covered, because not every field wrapper carries the sfgi-ed- class,
 * and !important is needed to beat a component that sets pointer-events of
 * its own (the full-card cover link does). */
.block-editor-block-list__block [class^="sfgi-"] a,
.block-editor-block-list__block [class*=" sfgi-"] a,
.block-editor-block-list__block a[data-sfgi-href],
[class*="sfgi-ed-"] a,
[class*="sfgi-ed-"] button,
[class*="sfgi-ed-"] input,
[class*="sfgi-ed-"] select,
[class*="sfgi-ed-"] textarea,
[class*="sfgi-ed-"] label {
	pointer-events: none !important;
}
