/*
Theme Name: OptSus Base
Theme URI: https://optsus.com/themes/optsus-base
Author: Frank Jones
Author URI: https://optsus.com
Description: Minimalist Full Site Editing parent theme for OptSus client websites. Designed to be used WITH a child theme, never alone. Custom-built, Gutenberg-native, theme.json schema v2 driven, zero third-party block library dependency. Child themes inherit stable contract slugs (palette, spacing, font sizes, template parts) and rebind values per brand.
Version: 1.1.1
Requires at least: 6.5
Tested up to: 6.6
Requires PHP: 7.4
License: GNU General Public License v2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html
Text Domain: optsus-base
Tags: one-column, custom-colors, custom-logo, custom-menu, editor-style, featured-images, full-site-editing, block-patterns, rtl-language-support, threaded-comments, translation-ready, wide-blocks, block-styles
*/

/*
 * Intentionally empty.
 *
 * All visual styling for the OptSus Base parent comes from theme.json. The
 * stylesheet exists only to carry the theme header WordPress requires for
 * theme registration and to give child themes a deterministic enqueue target.
 *
 * If you are reading this looking for a class to override, you are in the
 * wrong file. Override values in your child theme's theme.json against the
 * stable slugs documented in README.md (palette, spacing, font sizes).
 *
 * EXCEPTION (added v1.1.0, 2026-05-31): the override block below carries a
 * small set of defenses against Gutenberg core's wp-element-button cascade
 * and against display-heading word-break / multi-column flex-wrap defaults
 * that no theme.json key can express. Source: every Susann Camus child
 * stylesheet rule that fought the parent's defaults got lifted here so the
 * fight happens ONCE in the parent, not in every future child theme.
 *
 * Every rule below is parameterized via CSS custom properties so child
 * themes opt into shape (sharp / soft / pill), display font, and tracking
 * by setting variables in their own theme.json -> styles.custom block, NOT
 * by re-fighting selectors with !important. See VARIABLE_DEFAULTS.md.
 */

/* -----------------------------------------------------------------
   Display heading word-break guard.

   WHY: Long display headlines on narrow viewports (or long words like
   "thrillers") hit overflow-wrap: anywhere or word-break: break-all
   from upstream Normalize-style resets bundled by some hosts and
   break mid-word. WordPress core does not surface a per-element
   word-break setting in theme.json. The element-scoped rule below
   pins the break behavior on h1-h3 (the display tier) without
   constraining body copy where break-word is desirable.

   Parameterized: a child can set --wp--custom--heading--word-break in
   its theme.json to override (e.g. "break-word" for an Asian-language
   build) without touching this selector.
   ----------------------------------------------------------------- */
h1, h2, h3 {
  word-break: var(--wp--custom--heading--word-break, keep-all);
  overflow-wrap: normal;
  hyphens: none;
}

/* -----------------------------------------------------------------
   Display heading uppercase + tracking default (added v1.1.1).

   WHY: Susann fidelity report 2026-05-31 v9 surfaced this gap. The
   parent v1.1.0 binds `--wp--preset--font-family--display` so child
   themes can set a display face like Anton, but it never applied
   `text-transform: uppercase` to h1/h2. The Susann v0.6.0 child
   correctly deleted its explicit uppercase rule expecting the parent
   to ship it; the resulting render lost the casing on every display
   headline (3 of 3 viewports flagged `h1-display-uppercase = none`).

   This rule restores the OptSus-default professional display-tier
   treatment (uppercase, subtle 0.01em tracking) on h1 + h2. h3 is
   intentionally excluded; sub-headings stay sentence case unless a
   child opts in.

   Parameterized via --wp--custom--heading--transform so a child theme
   whose brand voice rejects uppercase (e.g. a long-form essayist) can
   set the variable to `none` in its theme.json -> styles.custom block
   and avoid !important selector fights. No !important needed here:
   the element selector ties cleanly with theme.json-generated rules
   and child overrides via the variable always win.
   ----------------------------------------------------------------- */
h1, h2 {
  text-transform: var(--wp--custom--heading--transform, uppercase);
  letter-spacing: var(--wp--custom--heading--tracking, 0.01em);
}

/* -----------------------------------------------------------------
   `.sc-accent` class -> accent token binding (added v1.1.1).

   WHY: Susann fidelity report 2026-05-31 v9 flagged
   `accent-headline-color = 0` across all 3 viewports. The brand-system
   class `.sc-accent` (selective-accent span used inside h1 to color
   specific words in the brand accent) had no styling because the
   binding was never lifted out of the child. The class name reads as
   client-prefixed but the pattern is general: any child theme can drop
   `<span class="sc-accent">WORD</span>` inside a headline and have it
   pick up the brand accent token without authoring its own CSS.

   !important: WordPress core element-color rules on h1 (set via
   theme.json `styles.elements.h1.color.text`) win the cascade against
   class selectors of equal specificity (0,1,0 tie, later rule wins;
   theme.json output enqueues after this stylesheet on most setups).
   Without !important the span inherits the heading color silently.
   Matches the same cascade-tie reasoning documented for the button
   block above.
   ----------------------------------------------------------------- */
.sc-accent {
  color: var(--wp--preset--color--accent) !important;
}

/* -----------------------------------------------------------------
   Multi-column layout guard at desktop.

   WHY: WordPress core collapses wp-block-columns to single-column at
   <= 781px via a hardcoded media query. When a parent's content
   container plus root padding pulls the inner column width under
   782px on a 1440px viewport, the desktop view stacks unexpectedly.
   The Susann build hit this; the symptom is "comp shows 2-col,
   live render stacks at 1440." Force flex-wrap nowrap at >=782px so
   the explicit row layout sticks. is-not-stacked-on-mobile carve-out
   preserves intentional mobile-row behavior.

   No !important: the selector specificity (0,2,1) outranks core's
   default and child themes can override by adding a class-scoped
   rule. !important would lock children out unnecessarily.
   ----------------------------------------------------------------- */
@media (min-width: 782px) {
  .wp-block-columns:not(.is-not-stacked-on-mobile) {
    flex-wrap: nowrap;
  }
  .wp-block-columns:not(.is-not-stacked-on-mobile) > .wp-block-column {
    flex-basis: 0;
    flex-grow: 1;
  }
  .wp-block-columns:not(.is-not-stacked-on-mobile) > .wp-block-column[style*="flex-basis"] {
    flex-grow: 0;
  }
}

/* -----------------------------------------------------------------
   Multi-column mobile stacking default (added v1.1.1).

   WHY: Susann fidelity report 2026-05-31 v9 flagged
   `hero-columns-desktop` at 375px viewport returning 2 columns where
   the spec expects 1. WordPress core ships a `max-width: 781px`
   stacking rule, but when the parent's own `min-width: 782px` block
   above sets `flex-wrap: nowrap` on the `.wp-block-columns` selector,
   some host plugin sets and child overrides cause the desktop nowrap
   to leak into the mobile breakpoint. Pinning the mobile rule here
   guarantees stacking regardless of cascade order.

   `.is-not-stacked-on-mobile` carve-out preserves Gutenberg's
   intentional opt-out for layouts that should stay row at mobile
   (rare; usually a tight icon row).

   No !important: the selector specificity ties with core; this rule
   sits inside our own parent stylesheet, enqueued before child themes
   and most host plugins, so the mobile breakpoint wins by source
   order. Children can override with a higher-specificity class rule.
   ----------------------------------------------------------------- */
@media (max-width: 781px) {
  .wp-block-columns:not(.is-not-stacked-on-mobile) {
    flex-direction: column;
    flex-wrap: wrap;
  }
  .wp-block-columns:not(.is-not-stacked-on-mobile) > .wp-block-column {
    flex-basis: 100% !important;
  }
}

/* -----------------------------------------------------------------
   Gutenberg core-button cascade defense.

   WHY: WordPress core ships wp-element-button styles that apply a
   border-radius (~9999px / pill), inherit body font-family, leave
   casing alone (Title Case from content), and pad chunky. Block
   attributes set in pattern markup (border-radius:0, background:
   accent) ARE respected for the values they cover, but font-family,
   text-transform, and letter-spacing are NOT block-supported in a
   way that survives core's cascade across all host plugin sets.

   The override below establishes the parent's professional default
   (sharp 2px corners, inherit display font from --wp--preset--
   font-family--display when a child theme defines one, uppercase
   with subtle tracking) and exposes every value as a custom
   property so children opt out by setting one variable.

   !important: wp-element-button core CSS ties at specificity 0,0,1,0
   against .wp-block-button__link. Enqueue order across host plugin
   sets is undefined; the only robust override is !important. Same
   pattern Susann v0.3.0 used for Anton. Each !important below is
   load-bearing for cascade-win, not a code smell.

   Child opt-out examples (set in child theme.json -> styles.custom):
   - sharp corners (default): --wp--custom--button--radius: 2px
   - rounded:                 --wp--custom--button--radius: 8px
   - pill:                    --wp--custom--button--radius: 9999px
   - display font:            --wp--preset--font-family--display: "Anton"
   - tight tracking:          --wp--custom--button--letter-spacing: 0.06em
   ----------------------------------------------------------------- */

/* Primary CTA: accent fill, background-color text, sharp by default. */
.wp-block-button .wp-block-button__link {
  /* !important: outranks wp-element-button core (specificity tie). */
  border-radius: var(--wp--custom--button--radius, 2px) !important;
  padding: var(--wp--custom--button--padding, 0.875rem 1.5rem) !important;
  font-family: var(--wp--preset--font-family--display, var(--wp--preset--font-family--heading, inherit)) !important;
  text-transform: uppercase !important;
  letter-spacing: var(--wp--custom--button--letter-spacing, 0.04em) !important;
  font-weight: 400 !important;
  line-height: 1.2 !important;
  background-color: var(--wp--preset--color--accent) !important;
  color: var(--wp--preset--color--background) !important;
  border: 1px solid transparent !important;
  text-decoration: none !important;
  transition: background-color 160ms ease, border-color 160ms ease, color 160ms ease;
}
.wp-block-button .wp-block-button__link:hover,
.wp-block-button .wp-block-button__link:focus {
  /* !important: same cascade-tie reasoning as the base rule. */
  background-color: var(--wp--preset--color--foreground) !important;
  color: var(--wp--preset--color--background) !important;
}

/* Outline variant: transparent fill, 1px foreground border. */
.wp-block-button.is-style-outline .wp-block-button__link {
  /* !important: outranks wp-element-button + is-style-outline core. */
  border-radius: var(--wp--custom--button--radius, 2px) !important;
  padding: var(--wp--custom--button--padding, 0.875rem 1.5rem) !important;
  font-family: var(--wp--preset--font-family--display, var(--wp--preset--font-family--heading, inherit)) !important;
  text-transform: uppercase !important;
  letter-spacing: var(--wp--custom--button--letter-spacing, 0.04em) !important;
  font-weight: 400 !important;
  line-height: 1.2 !important;
  background-color: transparent !important;
  border: 1px solid var(--wp--preset--color--foreground) !important;
  color: var(--wp--preset--color--foreground) !important;
  text-decoration: none !important;
}
.wp-block-button.is-style-outline .wp-block-button__link:hover,
.wp-block-button.is-style-outline .wp-block-button__link:focus {
  /* !important: same cascade-tie reasoning as the base outline rule. */
  background-color: var(--wp--preset--color--accent) !important;
  border-color: var(--wp--preset--color--accent) !important;
  color: var(--wp--preset--color--background) !important;
}

/* Button row metrics: tighten gap, zero individual button margin so a
   row of CTAs reads as a paired unit, not floating elements.
   !important on margin: wp-block-buttons child rules in core apply
   margin that cannot be reset by block-supports. */
.wp-block-buttons {
  gap: var(--wp--custom--button--gap, 0.75rem) !important;
  margin-top: 0.25rem;
}
.wp-block-buttons > .wp-block-button {
  margin: 0 !important;
}
