/* ==========================================================================
   base.css — PromptingPress Design Foundation
   Design tokens, reset, typography, and base element styles.
   ========================================================================== */

/* ==========================================================================
   1. CSS Custom Properties (Design Tokens)
   Change these values to retheme the entire site.
   See ai-instructions/retheme.md for the full retheme workflow.
   ========================================================================== */

:root {
  /* Color — change all 8 to retheme */
  --color-bg:           #fcfdff;  /* color: Page background */
  --color-surface:      #f4f7fb;  /* color: Card / component backgrounds */
  --color-text:         #101828;  /* color: Primary text */
  --color-muted:        #5e6677;  /* color: Secondary text, captions, placeholders */
  --color-border:       #d9e0eb;  /* color: Dividers, outlines */
  --color-accent:       #3157f4;  /* color: Primary action — WCAG AA 4.7:1 on white */
  --color-accent-hover: #2447df;  /* color: Hover / active state for accent */
  --color-bg-inverted:  #0f172a;  /* color: Section variant: inverted bg (semantic opposite of --color-bg) */

  /* Derived colors — computed from the 8 above, used for premium treatments */
  --color-text-secondary:   #2d3648;  /* color: Body descriptions, slightly lighter than text */
  --color-accent-strong:    #2744b7;  /* color: Button gradient dark stop, strong accent borders */
  --color-border-accent:    #9dafee;  /* color: Accent-tinted borders for featured elements */
  --color-surface-accent:   #e8ecfe;  /* color: Accent-washed backgrounds, eyebrows */
  --color-accent-on-inverted:       #9dafee;  /* color: Link/accent on the inverted (dark) band — light accent tint, 8.33:1 on --color-bg-inverted (--color-accent's 3.23:1 fails AA there) */
  --color-accent-on-inverted-hover: #c1cdfc;  /* color: Hover state for on-inverted links — brighter tint, 11.4:1 on --color-bg-inverted */
  --color-accent-on-overlay:        #fafbff;  /* color: Link/accent on a bg-image band (dark rgba(0,0,0,.55) overlay over an ARBITRARY image). The name is the ROLE, not the hue: the worst case is the overlay over a pure-WHITE image (effective bg rgb(115,115,115)), whose contrast CEILING for any foreground is 4.74:1, so a near-white value is the only one that clears AA (4.5:1). #fafbff = 4.59:1 there. on-inverted (#9dafee) is tuned to the solid inverted bg, only ~2.2:1 here (#437 flagged a fixed tint can't be trusted over an arbitrary image). */
  --color-accent-on-overlay-hover:  #ffffff;  /* color: Hover state for on-overlay links — pure white, 4.74:1 (the ceiling) over the worst-case overlay-over-white composite */
  --color-muted-on-overlay:         #fafbff;  /* color: DE-EMPHASISED body ink on a bg-image band (cta body, stats label). A separate ROLE from --color-accent-on-overlay, which happens to share its value because the band leaves no other choice: over the worst-case composite rgb(115,115,115) the contrast CEILING is 4.74:1, full --color-bg reaches 4.658:1, and 4.5:1 needs luminance >= 0.9467 (about #f9f9f9 achromatic). The de-emphasis budget on this band is therefore about 0.07:1 — the previous `opacity: 0.85` spent a margin that does not exist and measured 3.87:1 (issue 577). #fafbff = 4.585:1. Reopen if the overlay lightens enough to buy real headroom; do NOT re-introduce an opacity literal. */

  /* Spacing — the layout scale */
  --space-xs:  0.25rem;   /* length: 4px */
  --space-sm:  0.5rem;    /* length: 8px */
  --space-md:  1rem;      /* length: 16px */
  --space-lg:  2rem;      /* length: 32px */
  --space-xl:  4rem;      /* length: 64px */
  --space-2xl: 7rem;      /* length: 112px */
  --space-3xl: 10rem;     /* length: 160px */

  /* Typography — replace both to change fonts */
  --font-body:    system-ui, sans-serif;  /* font-family: Body text */
  --font-heading: system-ui, sans-serif;  /* font-family: All headings */
  --font-weight-heading: 650;     /* number: Heading font weight */
  --line-height-body:    1.6;     /* number: Body text line height */
  --line-height-heading: 1.2;     /* number: Heading line height */
  --letter-spacing-heading: -0.03em;  /* length: Heading tracking (letter-spacing) — negative tightens */

  /* Button rhythm */
  --btn-padding-y: var(--space-sm);  /* length: Button vertical padding */
  --btn-padding-x: var(--space-lg);  /* length: Button horizontal padding */
  --btn-radius: 4px;                 /* length: Button corner radius — the authorable button shape; override to pill a CTA (e.g. 100px) without rounding cards, which follow --radius */

  /* Button color — the GLOBAL button surface (the color analog of --btn-radius). Three of
     the four are left `initial` (unset) so every consuming rule falls through to its own
     literal and an unset button is byte-identical; SET any of these at :root (via
     update_design_token) to restyle EVERY composed primary button site-wide — including the
     premium `main .btn` primary, which reaches them through these tokens (#458). Per-component
     slots (--cta-button-* / --cta-accent / --hero-accent) still win when set, ON THE BUTTON THE
     COMPONENT OWNS; --btn-* sits between those slots and the literal fallback. On any other
     composed button — a `.btn` an author hand-writes into a rich-text prop — the per-instance
     button slots are neutralised (#545) and --btn-* is the tier that reaches it. --btn-text keeps a concrete default because
     its value already equals the universal ink literal (--color-bg) every button rule falls
     back to, so it stays discoverable AND overridable. Effective unset defaults differ by
     rule: --btn-bg = --color-accent on the bare .btn / accent gradient on the composed
     primary; --btn-border-color = --color-accent (bare/.cta/.hero) / --color-accent-strong
     (premium); --btn-shadow = none (bare) / premium bevel (composed primary). See the .btn and
     `main .btn` rules in components.css and ai-instructions/retheme.md.

     HOVER (issue 539). --btn-hover-bg / --btn-hover-border-color are the hover twins of
     --btn-bg / --btn-border-color, and complete #530's rest/hover parity at the GLOBAL tier:
     before them, a site-wide fill or border retheme reverted to the theme's premium accent
     gradient the moment a pointer touched any button. They sit in the hover chains at exactly
     the position their resting counterparts occupy in the rest chains, and above the literal
     (with one exception: the overlay/cover ring chains carry neither knob — --btn-hover-border-color
     left in issue 564 and --btn-hover-bg in issue 565, so since #565 the "neither" is literal
     rather than approximate — see PHOTO-BAND CARVE-OUT below. The FILL chains are untouched:
     --btn-hover-bg still paints those buttons' hover fill.). Both are `initial`, so an unset
     button is byte-identical.

     Precedence, stated exactly, because "below the per-instance slots" is only half true.
     Each knob sits below the per-instance slots FOR ITS OWN PROPERTY and above everything
     else, mirroring rest:
       fill    --hero-button-hover-bg / --cta-button-hover-bg / --cta-button2-hover-bg
               -> --btn-hover-bg -> literal
       border  --*-hover-border (the per-instance BORDER slots) -> the BAND ACCENT
               (--hero-accent-hover / --cta-accent-hover, issue 564) -> --btn-hover-border-color
               -> the border-follows-fill link -> literal
     So --btn-hover-border-color DOES outrank the per-instance hover FILL slots in a border
     chain. That is deliberate and matches --btn-border-color at rest: an explicitly authored
     global ring should beat a ring merely INFERRED from someone's fill. The visible
     consequence is worth knowing — a component that sets only --cta-button-hover-bg loses its
     matching hover ring once a global --btn-hover-border-color is set, and takes the global
     ring instead. Set the per-instance --*-hover-border to opt back out.

     Deliberately NOT mirrored: hover INK and hover ELEVATION. --btn-shadow reaches no hover
     rule at all, so setting it to `none` flattens rest and the premium bevel grows back under
     the pointer. --btn-text is reachable on hover only on the two SECOND buttons (their
     [0,7,0] hover ink rules fall back through it); the bare .btn and premium primary hover ink
     are literals. Both are the same class of gap as this one, but routing --btn-shadow into
     hover would change rendered output for sites that already set it, so they are tracked as
     their own issues rather than riding along here.

     The hero's SECOND cta was once the exception here: its own chains routed neither --btn-bg
     nor this hover twin, so a site-wide retheme left it behind — and visibly, because the
     global knob still reached it through the SHARED premium rule, where it resolves the
     `background` shorthand to a flat colour and so CLEARS the gradient, while the cta2's own
     [0,7,0] background-color rule kept painting --color-accent. A rethemed hero rendered a
     FLAT ACCENT second button beside a brand-coloured primary. Issue 554 closed that: hero
     cta2 now routes --btn-bg / --btn-border-color / --btn-hover-bg / --btn-hover-border-color
     through its OWN chains in BOTH states, so no filled surface is carved out of this tier any
     more. (Issues 564 and 565 reintroduced ONE deliberate carve-out — the ring knobs AND the
     fill knobs, on the overlay/cover BORDER chains only — see PHOTO-BAND CARVE-OUT below.)
     "Not carved out" is not "always wins": these knobs sit BELOW the per-instance slots
     everywhere, so a hero that authors --hero-accent still takes the accent on BOTH its
     buttons and neither reads --btn-bg / --btn-border-color at all. That is the tier working
     as designed — authored beats global — and it is why the pair stays consistent either way.

     ORDER: within a border chain BOTH components rank the band accent (--hero-accent /
     --cta-accent) ABOVE --btn-border-color, and the same on hover. This block used to record
     the opposite for the cta family and warn against "unifying" the two components; issue 564
     reversed that. The old split was not harmless drift: because the cta ranked the global knob
     first, a site-wide ring retheme silently defeated an authored --cta-accent, and on photo
     bands it defeated --color-accent-on-overlay, the measured 4.59:1 separation role. The
     narrower authored role now wins on both components, each pair is still internally
     consistent, and the two families agree with each other. Pinned in css-lint and
     StyleSlotContractTest.

     PHOTO-BAND CARVE-OUT (issues 564 and 565): on `background_image` cta bands and `cover`
     heroes NO global knob is in the filled buttons' BORDER chains — not the two ring knobs
     (--btn-border-color / --btn-hover-border-color, removed in #564) and not the two fill
     knobs (--btn-bg / --btn-hover-bg, removed in #565, which reached the ring through the
     border-follows-fill link). Those chains bottom out at --color-accent-on-overlay, which
     is declared at :root below and therefore ALWAYS set, so a knob above it defeats a measured
     contrast guarantee and a knob below it is dead code. Removal was the only honest position.
     The per-instance ring slots remain above everything there as the escape hatch, and so do
     the per-instance FILL slots — that is what keeps #535's matching-ring promise alive for a
     fill an author aimed at THAT band, which is the scope the promise was written for.
     Note this is a real exception to the "no filled surface is carved out of this tier"
     sentence above, and note precisely how far it goes: the fill knobs still paint those
     buttons' FILL exactly as everywhere else. It is only the separation RING that they no
     longer reach, because only the ring carries a measured contrast guarantee. */
  --btn-bg:           initial;         /* color: Global button fill. Unset = each rule's own default (bare .btn: --color-accent; composed primary: the accent gradient). Set to recolor every button fill. */
  --btn-text:         var(--color-bg); /* color: Button label ink. Defaults to the PAGE BACKGROUND token, not a text token — buttons invert: a light page yields light text on the accent fill. Change --color-bg and button text follows unless pinned here. */
  --btn-border-color: initial;         /* color: Global button border. Unset = each rule's own default (--color-accent, or --color-accent-strong on the premium primary). Set to recolor every button border. */
  --btn-shadow:       initial;         /* shadow: Global button elevation. Unset = each rule's own default (bare .btn flat; composed primary keeps its premium bevel). Set a shadow preset (e.g. --shadow-md) or none to change every button's elevation. */
  --btn-hover-bg:           initial;   /* color: Global button HOVER fill — the hover twin of --btn-bg. Unset = each rule's own default (bare .btn: --color-accent-hover; composed primary: the premium hover gradient). Set alongside --btn-bg so a site-wide fill retheme survives the pointer. */
  --btn-hover-border-color: initial;   /* color: Global button HOVER border — the hover twin of --btn-border-color. Unset = each rule's own default (--color-accent-hover, or --color-accent on the premium primary). Set alongside --btn-border-color so a site-wide border retheme survives the pointer. */

  /* Shape & motion */
  --radius:     0.375rem;   /* length: 6px — increase for rounder corners */
  --max-width:  72rem;      /* length: 1152px — content column max width */
  --measure-body:      70ch;      /* length: Text body measure — section content, readable prose */
  --measure-body-wide: 75ch;      /* length: Wider measure — standalone text sections, centered intros */
  --measure-centered:  56rem;     /* length: Centered section body — preserves current layout width */
  --measure-heading:   40rem;     /* length: Band heading measure — display type, shorter than prose. Eight band components route their heading cap through this (hero and section are exempt: both are uncapped by design). Retune it to change every routed band heading in one write. */
  --transition: 150ms ease; /* raw: Default transition for interactive states */
  --overlay-bg: rgba(0, 0, 0, 0.55); /* color: Dark scrim over background images for text readability */

  /* Elevation — presets for the bounded `shadow` style-slot type */
  --shadow-none: none;                              /* shadow: No elevation */
  --shadow-sm:   0 1px 2px rgba(16, 24, 40, 0.06);  /* shadow: Subtle lift (cards, inputs) */
  --shadow-md:   0 4px 12px rgba(16, 24, 40, 0.10); /* shadow: Standard elevation (raised sections) */
  --shadow-lg:   0 12px 32px rgba(16, 24, 40, 0.16);/* shadow: Strong elevation (modals, hero callouts) */

  /* Typography roles — technical/secondary text surfaces beyond body/heading */
  --font-mono: ui-monospace, 'Cascadia Code', 'Source Code Pro', Menlo, Consolas, 'DejaVu Sans Mono', monospace; /* font-family: Mono / code text */
  --text-meta-size:      0.8125rem;        /* length: Meta text (timestamps, captions) */
  --text-meta-color:     var(--color-muted); /* color: Meta text color */
  --text-label-size:     0.8125rem;        /* length: Label text */
  --text-label-weight:   600;              /* number: Label font weight */
  --text-label-spacing:  0.01em;           /* length: Label letter spacing */
  --text-kicker-size:    0.75rem;          /* length: Kicker / eyebrow text */
  --text-kicker-weight:  700;              /* number: Kicker font weight */
  --text-kicker-spacing: 0.08em;           /* length: Kicker letter spacing */
  --text-kicker-color:   var(--color-accent); /* color: Kicker text color */
}

/* ==========================================================================
   Section band rhythm — the single source of section-level vertical spacing.
   Every band-level component (section, grid, cta, stats, faq, testimonials)
   routes its padding fallback through these properties, so the theme's section
   rhythm is defined ONCE here instead of copied per component per breakpoint
   (issue 431). Adding a new band component means consuming these, not pasting
   literals. Internal (not authored via update_design_token, so kept out of the
   first :root token block above); a whole-site rhythm retune changes only these.

   Symmetric rhythm: a band's top and bottom padding are equal, and a band that
   follows another band gets that SAME top, so every stacked band reads as a
   centered block regardless of background alternation (issue 430). The
   adjacent-top tier is kept as a live custom property so the per-component
   adjacent-top slot still routes through it (slot contract preserved), but its
   value is pinned to --pp-band-padding so it can never diverge from the band's
   own edges. The mobile override changes only --pp-band-padding; adjacent-top
   tracks it automatically. Consuming rules in components.css are untouched.

   Hero opts OUT of this shared rhythm on purpose: it carries its own larger,
   already-symmetric page-opening rhythm (--space-xl / --space-2xl, 64/112px)
   via the --hero-padding-* slots, so it is not retuned here.

   Band heading scale — the typography analog of the rhythm above (issue 436).
   Every band title (section, grid, cta, faq, stats, table, testimonials, logos,
   embed) routes its font-size fallback through --pp-band-heading-size, so the
   default heading step is defined ONCE and fluid at EVERY viewport instead of
   collapsing to body size below 768px (the old `font-size: var(--slot, inherit)`
   trap) or drifting per component. The clamp runs from a ~28px mobile floor
   (never body-size) to the ~42px ceiling of the prior desktop-only clamp; at
   1280px it resolves to ~38.4px, matching the previous desktop output for
   section/grid/faq. Internal like the rhythm props (not authored via
   update_design_token, kept out of the first :root token block); a whole-site
   heading-scale retune changes only this line. Hero keeps its own larger clamp
   (out of scope). Per-component --*-title-size / --*-heading-size slots still
   win at every breakpoint — this is only the fallback.
   ========================================================================== */
:root {
  --pp-band-padding:              clamp(4.25rem, 6vw, 5rem);
  --pp-band-padding-adjacent-top: var(--pp-band-padding);
  --pp-band-heading-size:         clamp(1.75rem, 1.48rem + 1.15vw, 2.62rem);
}

@media (max-width: 767px) {
  :root {
    --pp-band-padding: 3.35rem;
  }
}

/* Responsive breakpoints (reference — use in media queries):
   --breakpoint-sm: 640px   single-column stacking, nav collapses
   --breakpoint-md: 768px   2-col grid, nav links visible
   --breakpoint-lg: 1024px  full 3-col grid, full nav
   --breakpoint-xl: 1280px  max-width kicks in
*/

/* ==========================================================================
   2. CSS Reset
   ========================================================================== */

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

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

* {
  margin: 0;
  padding: 0;
}

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

body {
  min-height: 100vh;
  background-color: var(--color-bg);
  color: var(--color-text);
  font-family: var(--font-body);
  font-size: 1rem;
  line-height: var(--line-height-body);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

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

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

p,
h1,
h2,
h3,
h4,
h5,
h6 {
  overflow-wrap: break-word;
}

ul,
ol {
  list-style: none;
}

/* ==========================================================================
   3. Base Typography
   Modular scale: base 1rem, ratio ~1.25
   ========================================================================== */

h1,
h2,
h3,
h4,
h5,
h6 {
  font-family: var(--font-heading);
  font-weight: var(--font-weight-heading);
  line-height: var(--line-height-heading);
  color: var(--color-text);
  text-wrap: balance;
  letter-spacing: var(--letter-spacing-heading);
}

h1 { font-size: 2.375rem; }
h2 { font-size: 1.875rem; }
h3 { font-size: 1.375rem; }
h4 { font-size: 1.125rem; }
h5 { font-size: 1rem; }
h6 { font-size: 0.875rem; }

p {
  margin-bottom: var(--space-md);
}

p:last-child {
  margin-bottom: 0;
}

strong {
  font-weight: 700;
}

em {
  font-style: italic;
}

code,
pre {
  font-family: var(--font-mono);
  font-size: 0.9em;
}

pre {
  overflow-x: auto;
  padding: var(--space-md);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
}

blockquote {
  margin: 0 0 var(--space-md);
  padding-left: var(--space-md);
  border-left: 3px solid var(--color-accent);
  color: var(--color-muted);
  font-style: italic;
}

blockquote:last-child {
  margin-bottom: 0;
}

/* ==========================================================================
   4. Links
   ========================================================================== */

a {
  color: var(--color-accent);
  text-decoration: underline;
  text-underline-offset: 2px;
  transition: color var(--transition);
}

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

/* ==========================================================================
   5. Focus Ring
   Applied via :focus-visible — only shown for keyboard navigation.
   ========================================================================== */

:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
  border-radius: var(--radius);
}

/* Remove default outline when :focus-visible is supported */
:focus:not(:focus-visible) {
  outline: none;
}

/* ==========================================================================
   6. Screen Reader Only utility
   Visually hidden, but accessible to assistive technology.
   ========================================================================== */

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border-width: 0;
}

/* ==========================================================================
   7. Skip Link
   Visually hidden until focused — keyboard users see it, mouse users don't.
   ========================================================================== */

.skip-link.screen-reader-text {
  position: absolute;
  top: -100%;
  left: 0;
  z-index: 999;
  padding: var(--space-sm) var(--space-md);
  background: var(--color-accent);
  color: #fff;
  font-size: 0.875rem;
  text-decoration: none;
  clip: rect(0, 0, 0, 0);
}

.skip-link.screen-reader-text:focus {
  top: 0;
  clip: auto;
}

/* ==========================================================================
   8. Responsive breakpoint reference (CSS custom media — documentation only)

   Use standard @media queries in component / utility CSS:
     @media (min-width: 640px)  { ... }   sm
     @media (min-width: 768px)  { ... }   md
     @media (min-width: 1024px) { ... }   lg
     @media (min-width: 1280px) { ... }   xl
   ========================================================================== */
