/*
Theme Name: Acini Builder
Theme URI: https://r2k.co.il/acini-builder
Author: Acini
Author URI: https://r2k.co.il
Description: A component-based starter framework for WordPress. Developers register components (PHP, CSS, JS) with a full field library; editors assemble pages, terms, archives and global regions from those components through a meta box builder. Zero build step.
Version: 0.1.0
Requires at least: 6.5
Tested up to: 6.8
Requires PHP: 8.0
License: GPL-2.0-or-later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Text Domain: acini-builder
Tags: custom-menu, featured-images, translation-ready, full-width-template
*/

/* ==========================================================================
   Design tokens
   Neutral defaults. A site re-skins the framework by redefining these in its
   child theme's style.css (which loads after this file); components consume
   the variables rather than hardcoding values, so no component CSS changes.
   Every name a component may use is declared here, so a child theme only
   overrides what its brand needs.
   ========================================================================== */

:root {
	/* Colour — surfaces */
	--acini-bg: #ffffff;
	--acini-bg-subtle: #f4f5f7;
	--acini-bg-tint: #eef4fb;              /* a pale band */
	--acini-bg-accent-subtle: #eaf1fd;     /* accent-tinted fill, e.g. an active row */
	--acini-bg-inverse: #111418;           /* dark band, footer */
	--acini-bg-inverse-raised: #1d2128;    /* dark button, dark panel */
	--acini-bg-hero: #111418;              /* a dark hero's base */

	/* Colour — text */
	--acini-text: #1a1d21;
	--acini-text-soft: #2e3238;
	--acini-text-muted: #5f6670;
	--acini-text-inverse: #ffffff;
	--acini-text-inverse-muted: #c4c8ce;
	--acini-text-inverse-accent: #dbe7fc;  /* accent label on a dark band */
	--acini-icon-accent: #9fbff5;          /* accent icon on a dark band */

	/* Colour — lines */
	--acini-border: #dcdfe4;
	--acini-border-inverse: rgb(255 255 255 / 0.12);
	--acini-border-inverse-strong: rgb(255 255 255 / 0.3);

	/* Scrollbars: thin, no track, a dark thumb */
	--acini-scrollbar-size: 0.4rem;
	--acini-scrollbar-thumb: #3a3f46;
	--acini-scrollbar-thumb-inverse: rgb(255 255 255 / 0.3); /* on a dark panel */

	/* Colour — accent */
	--acini-accent: #1f5fd1;
	--acini-accent-hover: #164aa6;
	--acini-accent-soft: #cfdffa;          /* pill hover fill */
	--acini-accent-deep: #0d2a5e;          /* hero gradient start */
	--acini-accent-band: #e3ecfb;          /* band gradient end */
	--acini-accent-contrast: #ffffff;
	--acini-accent-text: #1a52b5;          /* accent text on light */
	--acini-mesh-violet: #1f5fd1;          /* moving hero background: base fill */
	--acini-mesh-lilac: #7aa6ee;           /* moving hero background: light blobs */
	--acini-focus: #1f5fd1;

	/* Colour — data */
	--acini-positive: #1a8a55;
	--acini-negative: #d33a3a;

	/* Gradients */
	--acini-gradient-hero: linear-gradient(to left bottom, var(--acini-accent-deep) 0%, var(--acini-accent-deep) 50%, var(--acini-bg-inverse) 100%);
	--acini-gradient-band: linear-gradient(var(--acini-bg), var(--acini-accent-band));

	/* Typography */
	--acini-font-body: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
	--acini-font-heading: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
	--acini-font-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

	--acini-text-xs: 1.2rem;
	--acini-text-13: 1.3rem;
	--acini-text-sm: 1.4rem;
	--acini-text-18: 1.8rem;
	--acini-text-base: 1.6rem;
	--acini-text-lg: 2rem;
	--acini-text-xl: 2.4rem;
	--acini-text-2xl: 2.8rem;
	--acini-text-3xl: 3.2rem;
	--acini-text-4xl: 5.2rem;
	--acini-text-5xl: 8rem;

	/* Display sizes: headline and numeral steps; px in the name, as with --acini-text-13. */
	--acini-text-40: 4rem;
	--acini-text-48: 4.8rem;
	--acini-text-64: 6.4rem;
	--acini-text-96: 9.6rem;
	--acini-text-97: 9.7rem;
	--acini-text-160: 16rem;
	--acini-text-200: 20rem;
	--acini-text-232: 23.2rem;

	--acini-weight-regular: 400;
	--acini-weight-medium: 500;
	--acini-weight-semibold: 600;
	--acini-weight-bold: 700;

	--acini-leading-tight: 1.2;
	--acini-leading-normal: 1.5;

	/* Spacing scale */
	--acini-space-2xs: 0.4rem;
	--acini-space-xs: 0.8rem;
	--acini-space-sm: 1.2rem;
	--acini-space-md: 1.6rem;
	--acini-space-lg: 2.4rem;
	--acini-space-2lg: 3.2rem;
	--acini-space-xl: 4rem;
	--acini-space-2xl: 6.4rem;
	--acini-space-3xl: 9.6rem;
	--acini-space-4xl: 12.8rem;

	/* Layout */
	--acini-container: 118.4rem;
	--acini-container-wide: 129.6rem;
	--acini-container-narrow: 70.4rem;
	--acini-container-xl: 140.8rem;
	--acini-container-max: 166.4rem;       /* the widest a band's content grows */
	--acini-gutter: var(--acini-space-md);
	/* Side padding of a full-width band: stepped at 768 and 1024 (below), not fluid. */
	--acini-gutter-section: var(--acini-space-lg);
	--acini-gutter-header: clamp(1.6rem, 5vw, 12.8rem);
	--acini-gutter-footer: clamp(2.4rem, 5vw, 6.4rem);
	--acini-gutter-page: var(--acini-gutter-header);
	--acini-gutter-home: clamp(2.4rem, 5vw, 12.8rem);
	/* Space a dark hero leaves for a fixed header. */
	--acini-header-clearance: 8.6rem;

	/* Radius */
	--acini-radius: 0.4rem;
	--acini-radius-md: 0.8rem;
	--acini-radius-lg: 1rem;
	--acini-radius-xl: 1.6rem;
	--acini-radius-2xl: 2.4rem;
	--acini-radius-32: 3.2rem;
	--acini-radius-3xl: 4rem;
	--acini-radius-pill: 999.9rem;

	/* Elevation */
	--acini-shadow-soft: 0 0.2rem 0.5rem rgb(20 25 30 / 0.06), 0 0.5rem 2rem rgb(20 25 30 / 0.12);
	--acini-shadow-card: 0 1.8rem 4.8rem rgb(20 25 30 / 0.18);

	/* Motion */
	--acini-transition: 180ms ease;
	--acini-ease-out: cubic-bezier(0.22, 1, 0.36, 1);
	--acini-ease-slide: cubic-bezier(0.16, 1, 0.3, 1);
	--acini-duration-reveal: 0.7s;
}

/* Opt-in only: set data-acini-theme="dark" on <html> to use it. It is not
   applied from the visitor's OS setting — the design has no dark scheme, and
   an automatic one would invert the page against the brand. These values
   predate the design and have not been reviewed. */
:root[data-acini-theme="dark"] {
	--acini-bg: #14161a;
	--acini-bg-subtle: #1c1f25;
	--acini-text: #e8eaed;
	--acini-text-muted: #a2abb8;
	--acini-border: #2c313a;
}

@media (min-width: 48em) {
	:root {
		--acini-gutter-section: calc(var(--acini-space-xl) + var(--acini-space-xs)); /* 48px */
	}
}

@media (min-width: 64em) {
	:root {
		--acini-gutter-section: var(--acini-space-4xl); /* 128px */
	}
}

/* ==========================================================================
   Minimal reset
   ========================================================================== */

*,
*::before,
*::after {
	box-sizing: border-box;
}

body,
h1, h2, h3, h4, h5, h6,
p, figure, blockquote, dl, dd {
	margin: 0;
}

/* Units: rem on a 10px root, for every length (font-size, spacing, sizes, radii, gutters).
   62.5% of the browser default is 10px, so 1rem = 10px: 14px = 1.4rem, 24px = 2.4rem.
   A percentage, not 10px, so a visitor's own browser font-size setting still scales the site.
   body sets 1.6rem below so running text stays 16px. px is kept only for 1-2px hairlines
   (borders, outlines). Media queries stay in em: they are measured against the browser's
   16px default, not this root, so 64em is 1024px whatever the root is. */
html {
	font-size: 62.5%;
	-webkit-text-size-adjust: 100%;
}

body {
	background: var(--acini-bg);
	color: var(--acini-text);
	font-family: var(--acini-font-body);
	font-size: var(--acini-text-base);
	line-height: var(--acini-leading-normal);
	min-height: 100vh;
}

h1, h2, h3, h4, h5, h6 {
	font-family: var(--acini-font-heading);
	line-height: var(--acini-leading-tight);
	text-wrap: balance;
}

p {
	text-wrap: pretty;
}

img,
picture,
video,
canvas,
svg {
	display: block;
	max-width: 100%;
	height: auto;
}

input,
button,
textarea,
select {
	font: inherit;
	color: inherit;
}

a {
	color: var(--acini-accent);
}

/* ==========================================================================
   Accessibility primitives
   ========================================================================== */

/* Visible focus everywhere. Never remove this without a replacement. */
:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
	outline: 2px solid var(--acini-focus);
	outline-offset: 2px;
	border-radius: 2px;
}

/* Scrollbars, as in the design: thin, no track, a dark rounded thumb — the page's and every
   scrolling box's. A dark box sets --acini-scrollbar to a light thumb. Chromium and Safari draw
   the ::-webkit-scrollbar parts; Firefox, which has none, gets the standard properties. Those
   stay out of Chromium, where they would replace the 4px bar with its own thin one. */
::-webkit-scrollbar {
	width: var(--acini-scrollbar-size);
}

::-webkit-scrollbar-track {
	background: transparent;
}

::-webkit-scrollbar-thumb {
	background: var(--acini-scrollbar, var(--acini-scrollbar-thumb));
	border-radius: calc(var(--acini-scrollbar-size) / 2);
}

@supports not selector(::-webkit-scrollbar) {
	* {
		scrollbar-width: thin;
		scrollbar-color: var(--acini-scrollbar, var(--acini-scrollbar-thumb)) transparent;
	}
}

/* Screen-reader-only text, matching core's admin class name. */
.screen-reader-text {
	position: absolute !important;
	width: 1px;
	height: 1px;
	padding: 0;
	margin: -1px;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
	border: 0;
}

/* Skip link — becomes visible on focus. Logical properties throughout so it
   lands on the correct side in RTL locales. */
.acini-skip-link {
	position: absolute;
	inset-block-start: 0;
	inset-inline-start: 0;
	z-index: 100000;
	padding: var(--acini-space-xs) var(--acini-space-md);
	background: var(--acini-bg);
	color: var(--acini-text);
	text-decoration: none;
	transform: translateY(-150%);
}

.acini-skip-link:focus {
	transform: translateY(0);
}

/* Site logo: uploaded image, or the placeholder text wordmark. */
.acini-logo {
	display: inline-flex;
	align-items: center;
	color: inherit;
	text-decoration: none;
}

.acini-logo__img {
	display: block;
	width: auto;
	max-height: 4rem;
}

/* Both versions printed: stacked in one cell, the white one hidden until the
   header says it is over a hero (site-header/style.css). */
.acini-logo--auto {
	display: inline-grid;
}

.acini-logo--auto .acini-logo__img {
	grid-area: 1 / 1;
	transition: opacity var(--acini-transition);
}

.acini-logo--auto .acini-logo__img--inverse {
	opacity: 0;
}

@media (prefers-reduced-motion: reduce) {
	.acini-logo--auto .acini-logo__img {
		transition: none;
	}
}

.acini-logo__wordmark {
	font-family: var(--acini-font-heading);
	font-size: var(--acini-text-xl);
	font-weight: var(--acini-weight-bold);
	line-height: var(--acini-leading-tight);
}

/* Interactive targets meet WCAG 2.2 2.5.8 (24x24 minimum). */
:where(a, button, [role="button"], input[type="checkbox"], input[type="radio"]) {
	min-height: 2.4rem;
}

/* In-page anchor links (#research, a TOC entry…) glide instead of jumping. Arriving with
   a #hash in the address is handled by the head script in functions.php. */
@media (prefers-reduced-motion: no-preference) {
	html {
		scroll-behavior: smooth;
	}
}

@media (prefers-reduced-motion: reduce) {
	*,
	*::before,
	*::after {
		animation-duration: 0.01ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: 0.01ms !important;
		scroll-behavior: auto !important;
	}
}

/* ==========================================================================
   Layout helpers used by the shipped components
   ========================================================================== */

.acini-container {
	width: 100%;
	max-width: var(--acini-container);
	margin-inline: auto;
	padding-inline: var(--acini-gutter);
}

.acini-container--narrow {
	max-width: var(--acini-container-narrow);
}

.acini-container--wide {
	max-width: var(--acini-container-wide);
}

.acini-builder > * + * {
	margin-block-start: 0;
}

/* ==========================================================================
   Scroll reveal
   .acini-float fades up; .acini-words reveals word by word (the words are
   wrapped server-side by acini_words(), so no JS splits text). assets/js/reveal.js
   adds data-shown when an element enters the viewport. Content is hidden only
   under html.acini-reveal, a class set by a tiny inline script that removes it again
   if reveal.js has not started within 3 seconds, so a blocked script, or no JS, can
   never leave text invisible. --acini-delay is set inline for staggered choreography.
   ========================================================================== */

@keyframes acini-word-in {
	from {
		opacity: 0;
		transform: translateY(4.2rem);
	}

	to {
		opacity: 1;
		transform: none;
	}
}

/* The word wrapper is inline-block so each word can move; it must exist
   whether or not the reveal is active, or the spaces between words collapse. */
.acini-word {
	display: inline-block;
}

html.acini-reveal .acini-float {
	opacity: 0;
	transform: translateY(2.8rem);
	transition:
		opacity var(--acini-duration-reveal) var(--acini-ease-out),
		transform var(--acini-duration-reveal) var(--acini-ease-out);
	transition-delay: var(--acini-delay, 0s);
}

html.acini-reveal .acini-float[data-shown] {
	opacity: 1;
	transform: none;
}

html.acini-reveal .acini-word {
	opacity: 0;
	transform: translateY(4.2rem);
}

html.acini-reveal .acini-words[data-shown] .acini-word {
	animation: acini-word-in 0.6s var(--acini-ease-out) both;
	animation-delay: var(--acini-delay, 0s);
}

/* Same specificity as the hiding rules above, so it wins: with reduced motion the
   content is simply there, with none of the staggered delays. */
@media (prefers-reduced-motion: reduce) {
	html.acini-reveal .acini-float,
	html.acini-reveal .acini-word,
	html.acini-reveal .acini-words[data-shown] .acini-word {
		opacity: 1;
		transform: none;
		transition: none;
		animation: none;
	}
}


/* Editors assemble arbitrary trees, so components own their own vertical
   rhythm rather than relying on a global sibling selector. */
