/*
Theme Name: Akuma Creative Base
Theme URI: https://github.com/AkumaCreative/akuma-base-theme
Author: Jah Marsh
Description: The Akuma Creative base block theme. The standard every Akuma Creative site forks from. All design tokens are defined in theme.json.
Version: 0.2.19
Requires at least: 6.9
Tested up to: 7.0
Requires PHP: 7.4
License: GPL-2.0-or-later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Text Domain: akuma-base
Tags: block-theme, full-site-editing, custom-colors, custom-typography
*/

/* ==========================================================================
   12-column fluid grid
   ==========================================================================

   Every layout is solved here before any component CSS is written. Twelve
   fractional tracks at every width, no fixed widths, no horizontal scroll.

   There is no build step, so a span is declared as a custom property on the
   child and the grid reads it. Opt-in is preserved: an element is only laid out
   by the grid if it is a child of .akuma-grid.

   Breakpoints are expressed as container queries rather than viewport media
   queries, so a component responds to the space it has been given rather than
   to the size of the window. That makes the same component correct inside a
   full-width band and inside a narrow rail with no variant.

   min-width: 0 on the container and on every child is what actually prevents
   horizontal overflow. It is not optional.

   TOKEN EXCEPTION: the five breakpoint lengths appear as literals in the
   @container rules below. Neither container queries nor media queries accept
   custom properties, so this cannot be tokenised in CSS. They are declared once
   here and nowhere else, and the same values are mirrored in theme.json under
   custom.breakpoint for use by JavaScript and for documentation.
   ========================================================================== */

/*
 * Spans do not inherit, and declaring that is what makes nesting work.
 *
 * A custom property inherits by default, so a region declaring --span-laptop passed it down to
 * every descendant. A child of a grid nested inside that region would then resolve the laptop
 * tier against its parent region's value rather than its own — the nested grid read the value
 * meant for the region containing it. Two panels that should have shared a row each took nine
 * columns and wrapped onto their own, and the card row beneath them did the same. Nothing
 * errored; the grid simply obeyed a value it had been handed from above.
 *
 * The syntax is universal and no initial value is given, so an unset span stays the
 * guaranteed-invalid value and var() falls through to the tier below it. That is what the whole
 * cascade of tiers depends on, and a typed property with an initial value would break it by
 * making every tier resolve to something.
 *
 * This is the fix rather than resetting the properties on every grid child: a reset would work
 * only while it stayed above the span utilities in this file, and would fail silently the day
 * someone reordered it.
 */
@property --span         { syntax: "*"; inherits: false; }
@property --span-mobile  { syntax: "*"; inherits: false; }
@property --span-tablet  { syntax: "*"; inherits: false; }
@property --span-laptop  { syntax: "*"; inherits: false; }
@property --span-desktop { syntax: "*"; inherits: false; }
@property --span-wide    { syntax: "*"; inherits: false; }

.akuma-grid {
	display: grid;
	grid-template-columns: repeat(var(--wp--custom--grid--columns, 12), minmax(0, 1fr));
	gap: var(--wp--custom--grid--gap);
	min-width: 0;

	/* Establishes the query container its own children resolve spans against. */
	container-type: inline-size;
}

/*
 * A nested grid uses the same gap as the one containing it. A region is a way of grouping
 * columns, not a change of rhythm, and a smaller inner gap makes the grouping visible as
 * uneven gutters — panels inside a region sitting closer together than the region sits to its
 * neighbour. One gutter across the page is what makes the twelve columns read as one grid.
 *
 * Flush is the one variant, and it is the absence of a gutter rather than a different one.
 *
 * Some panels are joined: two halves of a single surface, sharing one border and one radius,
 * with the join itself carrying meaning. A gutter between them would draw the seam the design
 * exists to remove. That is a layout requirement like any other, and the grid is where layout
 * requirements are met — a component reaching for its own grid to avoid asking for zero would
 * be solving a layout problem outside the layout system, which is the thing this file exists
 * to prevent.
 *
 * It is a variant of the gutter, not a licence to pick one. There is the page gutter and there
 * is none; there is no third value, and a component that wants a gap of its own choosing is
 * still wrong.
 */
.akuma-grid--flush {
	gap: 0;
}

/*
 * Span resolution.
 *
 * --span is the base and is required in spirit: it defaults to a full row, which
 * is the mobile-first position. Each tier falls back to the tier below it, so
 * declaring --span-desktop alone gives twelve columns everywhere until desktop.
 *
 * The grid also owns the spacing between its children, and nothing else may contribute to it.
 * A grid container in a block theme is a group block, and a group block is flow layout — core
 * emits `:root :where(.is-layout-flow) > * { margin-block-start: <block gap> }`, which lands on
 * every grid child after the first. In a flow container that margin is the gap; in a grid
 * container it is a second gap the grid knows nothing about, pushing every column after the
 * first down the page. Zeroing it here is the fix rather than removing the block gap, which the
 * flow bands on the same page still need.
 */
.akuma-grid > * {
	min-width: 0;
	margin-block: 0;
	grid-column: span var(--span, 12);
}

@container (min-width: 480px) {
	.akuma-grid > * {
		grid-column: span var(--span-mobile, var(--span, 12));
	}
}

@container (min-width: 768px) {
	.akuma-grid > * {
		grid-column: span var(--span-tablet, var(--span-mobile, var(--span, 12)));
	}
}

@container (min-width: 1024px) {
	.akuma-grid > * {
		grid-column: span var(--span-laptop, var(--span-tablet, var(--span-mobile, var(--span, 12))));
	}
}

@container (min-width: 1280px) {
	.akuma-grid > * {
		grid-column: span var(--span-desktop, var(--span-laptop, var(--span-tablet, var(--span-mobile, var(--span, 12)))));
	}
}

@container (min-width: 1536px) {
	.akuma-grid > * {
		grid-column: span var(--span-wide, var(--span-desktop, var(--span-laptop, var(--span-tablet, var(--span-mobile, var(--span, 12))))));
	}
}

/*
 * Span resolution for a grid child that is not a direct child of .akuma-grid.
 *
 * The rules above resolve spans for direct children only, which is every layout region on a
 * page and was the whole of what the grid was asked for. A subgrid changes that: a row that
 * adopts its parent's tracks puts its own cells on those tracks, and those cells are grid
 * children two levels down. They resolve their spans against the same twelve columns and by
 * the same six-tier cascade, but no selector reached them.
 *
 * This is that cascade named rather than reimplemented. It is deliberately not tied to a
 * nesting depth: anything laid out on these tracks declares .akuma-col and gets the tiers,
 * whether it is a direct child, a subgrid cell, or something not yet built.
 *
 * A component that reimplemented the cascade for itself would be a second copy of the one
 * mechanism the whole layout system depends on, and the two would drift.
 */
.akuma-col {
	min-width: 0;
	grid-column: span var(--span, 12);
}

@container (min-width: 480px) {
	.akuma-col {
		grid-column: span var(--span-mobile, var(--span, 12));
	}
}

@container (min-width: 768px) {
	.akuma-col {
		grid-column: span var(--span-tablet, var(--span-mobile, var(--span, 12)));
	}
}

@container (min-width: 1024px) {
	.akuma-col {
		grid-column: span var(--span-laptop, var(--span-tablet, var(--span-mobile, var(--span, 12))));
	}
}

@container (min-width: 1280px) {
	.akuma-col {
		grid-column: span var(--span-desktop, var(--span-laptop, var(--span-tablet, var(--span-mobile, var(--span, 12)))));
	}
}

@container (min-width: 1536px) {
	.akuma-col {
		grid-column: span var(--span-wide, var(--span-desktop, var(--span-laptop, var(--span-tablet, var(--span-mobile, var(--span, 12))))));
	}
}

/*
 * Span utilities.
 *
 * Block markup cannot set an arbitrary custom property, so the spans a template needs are
 * exposed as classes that do nothing but declare one. This keeps the values in CSS with
 * every other token rather than as inline styles in markup.
 *
 * A component whose spans are its own — a table's columns, say — declares the properties on
 * its own classes in its own stylesheet instead. That is the same mechanism, not an exception
 * to it: the utilities exist because template markup cannot set a custom property, and a
 * stylesheet can.
 */
.span-3  { --span: 3; }
.span-4  { --span: 4; }
.span-6  { --span: 6; }
.span-8  { --span: 8; }
.span-9  { --span: 9; }
.span-12 { --span: 12; }

.span-mobile-3  { --span-mobile: 3; }
.span-mobile-4  { --span-mobile: 4; }
.span-mobile-6  { --span-mobile: 6; }
.span-mobile-8  { --span-mobile: 8; }
.span-mobile-9  { --span-mobile: 9; }
.span-mobile-12 { --span-mobile: 12; }

.span-tablet-3  { --span-tablet: 3; }
.span-tablet-4  { --span-tablet: 4; }
.span-tablet-6  { --span-tablet: 6; }
.span-tablet-8  { --span-tablet: 8; }
.span-tablet-9  { --span-tablet: 9; }
.span-tablet-12 { --span-tablet: 12; }

.span-laptop-3  { --span-laptop: 3; }
.span-laptop-4  { --span-laptop: 4; }
.span-laptop-6  { --span-laptop: 6; }
.span-laptop-8  { --span-laptop: 8; }
.span-laptop-9  { --span-laptop: 9; }
.span-laptop-12 { --span-laptop: 12; }

.span-desktop-3  { --span-desktop: 3; }
.span-desktop-4  { --span-desktop: 4; }
.span-desktop-6  { --span-desktop: 6; }
.span-desktop-8  { --span-desktop: 8; }
.span-desktop-9  { --span-desktop: 9; }
.span-desktop-12 { --span-desktop: 12; }

/*
 * Reading measure.
 *
 * This build has no fixed maximum width, so running text is constrained by
 * measure — a character count, which is what readability actually depends on.
 */
.akuma-measure {
	max-inline-size: var(--wp--custom--measure--prose);
}

/* ==========================================================================
   Base
   ========================================================================== */

/*
 * Nothing on the page may scroll the document sideways. If this ever triggers,
 * a grid child is missing min-width: 0 — the correct fix is there, not here.
 */
html {
	overflow-x: hidden;
}

/*
 * The page container.
 *
 * Every component in this project responds to the space it has been given rather than to the
 * size of the window, and until now the outermost band had nothing to ask. A band is a child
 * of the document, so there was no container above it and a @container rule written for one
 * would simply never have matched — which is the quiet way that kind of rule fails.
 *
 * This is the page itself declared as a container, so a band can tier the same way every
 * component inside it does. It is the whole viewport wide, so its tiers land where the
 * documented breakpoints say they do.
 *
 * It is not a new nearest container for anything that was already querying: every existing
 * @container rule in the theme and in the plugin resolves against a component that declares
 * its own — the grid, the bar, the hero, the ladder, the articles, the scoreboard. This one is
 * only ever reached by an element with nothing closer, which today is the band and nothing else.
 *
 * Inline-size containment only, so the block axis is still sized by the contents. The sticky
 * header is unaffected: containment does not create a scrollport and does not change which
 * element a sticky child is offset within.
 */
.wp-site-blocks {
	container-type: inline-size;
}

/* Media never exceeds its column. */
img,
video,
iframe,
svg {
	max-width: 100%;
	height: auto;
}

/* Tabular figures so a scoreline does not change width as it updates. */
.akuma-numeric {
	font-variant-numeric: tabular-nums;
}

/*
 * Visible focus on every interactive element, using the accent token. Removing
 * the outline without replacing it is an accessibility failure.
 */
:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
	outline: 2px solid var(--wp--preset--color--accent);
	outline-offset: 2px;
}

/* Screen-reader-only text that still occupies a layout box, so it counts as
   rendered text to crawlers as well as to assistive technology. */
.akuma-sr-only {
	position: absolute;
	width: 1px;
	height: 1px;
	padding: 0;
	margin: -1px;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
	border: 0;
}

/* ==========================================================================
   Site chrome
   ========================================================================== */

.site-header {
	position: sticky;
	top: 0;
	z-index: var(--wp--custom--z--sticky);
}

/* The header supplies its own gutters, so the global padding is cancelled here. */
.site-header > * {
	padding-inline: 0;
}

/*
 * A band that runs the full width of the viewport with its own ground.
 *
 * The gutter is declared here rather than inherited from the root padding. With
 * useRootPaddingAwareAlignments turned on, core moves the horizontal root padding off
 * .wp-site-blocks and onto .has-global-padding, a class it only adds to constrained and
 * inherited layouts — so a flow group never receives it and the page runs to the edge of the
 * screen with no error anywhere. Declaring it on our own band is the fix.
 *
 * One step on all four sides from tablet up. The space between the bottom of the scoreboard and
 * the top of the content is this band's own leading padding, so using the same step across
 * makes the page's margin one measurement rather than a generous one above and a thin one
 * beside — which reads as a single decision instead of two that happen to sit near each other.
 *
 * The phone is the exception, and it is the mobile-first base rather than an override. One
 * step is a generous margin on a display that has width to spare and a third of the screen on
 * one that has not: at 4rem a side, a 390px phone was left with 262px to hold a headline, a
 * crest and a scoreline. A page can always be scrolled further down; it cannot be made wider.
 * The inline gutter is therefore its own step on a phone and steps up with the page.
 *
 * The block padding is untouched. Height is the axis a phone is not short of, and the space
 * above the content is what separates it from the scoreboard rather than from the edge of the
 * screen.
 *
 * The background still spans the full viewport; only the contents are inset.
 */
.band {
	padding-block: var(--wp--preset--spacing--100);
	padding-inline: var(--wp--preset--spacing--50);
}

@container (min-width: 768px) {
	.band {
		padding-inline: var(--wp--preset--spacing--100);
	}
}

.band--tint {
	background: var(--wp--preset--color--grey-800);
}

.band--ink {
	background: var(--wp--preset--color--grey-000);
}

.band--ink .lvrl-section__title,
.band--ink .wp-block-heading {
	color: var(--wp--preset--color--white);
}

.band__title {
	font-size: var(--wp--preset--font-size--section-title);
	font-weight: 700;
	margin: 0 0 var(--wp--preset--spacing--60);
}

/*
 * Video facade. A YouTube embed loads a large third-party bundle and sets cookies before
 * anyone has asked to watch anything, so the poster is a link until it is clicked.
 */
.video-facade {
	position: relative;
	display: block;
	aspect-ratio: 16 / 9;
	border-radius: var(--wp--custom--radius--large);
	overflow: hidden;
	background: var(--wp--preset--color--grey-200);
	min-width: 0;
}

.video-facade__label {
	position: absolute;
	inset-block-end: var(--wp--preset--spacing--40);
	inset-inline-start: var(--wp--preset--spacing--40);
	color: var(--wp--preset--color--white);
	font-weight: 700;
	font-size: var(--wp--preset--font-size--small);
}
