/*
 * Nexora — project styles.
 *
 * AUTHORED. `creation.projectPlugin` writes this file once and never
 * regenerates it; the build proves that by reporting it as skipped on a second
 * run. Hand edits survive. Delete the file to have a stub recreated.
 *
 * WHAT BELONGS HERE, AND WHY IT IS NOT ELSEWHERE.
 *
 * Element CSS goes on the element, through `css` in the IR, where Elementor
 * scopes it with `selector` and a person finds it in the Advanced tab. The Kit
 * holds tokens. This file holds the third thing: rules that are genuinely
 * global and have no single element to live on.
 *
 *  - @keyframes. Animation names are global, so `compileElementCss` throws on a
 *    keyframes block authored on an element — correctly. `nx-flow` is
 *    referenced by `animation:nx-flow 3s infinite` on the ai-connector and
 *    `animation:nx-flow 4s infinite` on the scene-flow rule. WITHOUT THE BLOCK
 *    BELOW BOTH ARE INERT: the element css parses, the animation name resolves
 *    to nothing, and the marker simply never moves.
 *  - :focus-visible, which is a document-wide accessibility rule.
 *  - the skip link, which is markup outside any band.
 *  - the four --nx-* spacing variables.
 *  - the link reset, which answers the THEME's reset. See below.
 */

/* --------------------------------------------------------------------------
 * Link colour — the one reset the theme forces us to write.
 *
 * MEASURED, on the live homepage: every one of its 39 anchors computes
 * rgb(204, 51, 102), and 509 anchors across the seventeen pages do. The source
 * is the theme's own reset, which is enqueued on every page whether or not an
 * Elementor template replaces the markup:
 *
 *     hello-elementor/assets/css/reset.css
 *       a{background-color:transparent;color:#c36;text-decoration:none}
 *       a:active,a:hover{color:#336}
 *
 * The design's reset is the opposite — `a{color:inherit;text-decoration:none}`
 * — and `inherit` is the whole point: a Nexora link takes the colour of the
 * band it sits in, white on the dark ones and ink on the light ones. That is
 * why this is NOT the Kit's `link_normal_color`, which publishes ONE colour for
 * every link on the site and cannot express either state without breaking the
 * other. And it is not element CSS either: the elements that render crimson are
 * the footer's links, the wordmark and PRIVACY / TERMS, which belong to two
 * Theme Builder templates and every page that renders them — a reset with no
 * single element to live on, which is exactly what this file is for.
 *
 * ORDER, not specificity, is what wins this: both rules are (0,0,1) and
 * (0,1,1), and the live document head loads the theme's three stylesheets
 * first and every Elementor-hooked stylesheet after them — this file is
 * enqueued on `elementor/frontend/after_enqueue_styles`, so it lands in the
 * second group. If a later WordPress ever reorders that, the symptom is this
 * whole block going quiet at once rather than one rule of it.
 *
 * The hover pair is not optional: without it, hello's `a:hover{color:#336}`
 * turns every link navy on hover while the resting state is correct, which is
 * a bug that only shows under a cursor.
 * ----------------------------------------------------------------------- */
a{
  color: inherit;
  text-decoration: none;
}
a:hover,
a:focus,
a:active{
  color: inherit;
}

/* --------------------------------------------------------------------------
 * Spacing scale.
 *
 * These mirror `src/tokens.mjs`. The generator inlines the resolved clamp into
 * each control rather than emitting `var(--nx-s3)`, because a control value has
 * to be a value the encoder can classify — so NOTHING in the seventeen
 * generated documents references these four names today. They are declared for
 * hand-authored CSS and for the header and footer templates of B4, and that is
 * the only reason they are here. If B4 ends without using them, delete them
 * rather than leaving four variables nothing reads.
 * ----------------------------------------------------------------------- */
:root{
  --nx-s1: clamp(1rem, 1.4vw, 1.5rem);
  --nx-s2: clamp(2rem, 4vw, 4.5rem);
  --nx-s3: clamp(5rem, 9vw, 10rem);
  --nx-gap: clamp(20px, 2vw, 32px);
}

/* --------------------------------------------------------------------------
 * Motion.
 *
 * The prototype names this `flow`. It is renamed `nx-flow` because keyframe
 * names share one global namespace with every plugin and theme on the site, and
 * `flow` is a name something else will eventually want.
 *
 * The moving element is absolutely positioned inside a relative parent; `left`
 * is animated rather than `transform` because the prototype animates `left` and
 * the travel is expressed as a percentage of a parent whose width varies.
 * ----------------------------------------------------------------------- */
@keyframes nx-flow{
  from{ left: 0; }
  to{ left: 72%; }
}

/* There is no entrance animation in this design (decision D5): zero elements
 * carry `.reveal`, and the reveal observer is deliberately absent from
 * project.js. This rule is the safety net for the other direction — a plugin
 * or theme that ships opacity:0 + IntersectionObserver must not be able to
 * leave a Nexora band invisible. */
@media (prefers-reduced-motion: reduce){
  *, *::before, *::after{
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
}

/* --------------------------------------------------------------------------
 * Focus.
 *
 * The Kit global is named first with the prototype's literal as the fallback,
 * so the outline still draws if the Kit has not been applied yet, and follows
 * the palette once it has. A bare #4965ff here would be a colour the Kit does
 * not own — exactly what assertion S4 refuses inside the IR.
 * ----------------------------------------------------------------------- */
:focus-visible{
  /* `primary`, not `accent`. The brand colour claims Elementor's PRIMARY
   * system slot; the accent slot has no Nexora role and keeps Elementor's
   * stock #61CE70, so `--e-global-color-accent` would draw a green focus
   * ring the moment the Kit was applied — and the #4965ff fallback would
   * hide it right up until then. */
  outline: 2px solid var(--e-global-color-primary, #4965ff);
  outline-offset: 5px;
}

/* AND THE SAME RING AGAIN, SPELLED THE THEME'S WAY, BECAUSE THE BARE PSEUDO
 * CLASS NEVER DREW.
 *
 * MEASURED after a real Tab onto a real control: `:focus-visible` matched, and
 * the computed outline was `2px solid rgb(0,0,0)` at offset 2px — black, not the
 * contract's #4965ff at offset 5px — on every focusable element on the site.
 * `hello-elementor/assets/css/reset.css` ships
 *
 *   [tabindex]:not([tabindex="-1"]):focus-visible, a:focus-visible,
 *   button:focus-visible, input:focus-visible, select:focus-visible,
 *   textarea:focus-visible
 *     {box-shadow:0 0 0 4px #fff;outline:2px solid #000;outline-offset:2px}
 *
 * which is (0,3,0) on its first branch and (0,1,1) on the others. The rule above
 * is (0,1,0), so it lost on SPECIFICITY and no amount of load order could have
 * saved it — this is the same failure mode as a Kit @media rule dying under a
 * (0,3,0) control, arriving from the other direction.
 *
 * So the six branches are restated with `:root ` in front, which adds (0,1,0)
 * and clears both — (0,4,0) and (0,2,1) — with no `!important` anywhere. The
 * bare rule above is kept for anything focusable that none of these six match.
 *
 * `box-shadow:none` is not tidiness: without it the theme's 4px WHITE ring stays
 * drawn inside our blue one, which on the light bands is invisible and on the
 * dark bands is a white halo the design does not have. */
:root [tabindex]:not([tabindex="-1"]):focus-visible,
:root a:focus-visible,
:root button:focus-visible,
:root input:focus-visible,
:root select:focus-visible,
:root textarea:focus-visible{
  outline: 2px solid var(--e-global-color-primary, #4965ff);
  outline-offset: 5px;
  box-shadow: none;
}

/* --------------------------------------------------------------------------
 * Skip link. Off-screen until focused, then pinned to the top-left.
 * `transform` rather than `display` so it stays in the focus order.
 * ----------------------------------------------------------------------- */
.skip-link{
  position: fixed;
  z-index: 100;
  left: 16px;
  top: 12px;
  padding: .7rem 1rem;
  background: var(--e-global-color-ink, #080b12);
  color: #fff;
  transform: translateY(-150%);
}
.skip-link:focus{ transform: none; }

/* `scroll-padding-top` clears the fixed header when a skip link or an in-page
 * anchor scrolls to a target. 100px is the prototype's value against its 78px
 * header; B4 confirms it against the built header height. */
html{ scroll-padding-top: 100px; }

/* --------------------------------------------------------------------------
 * State classes project.js sets. The script only ever toggles a class; every
 * visual consequence is declared here or on the element, so a page with
 * JavaScript disabled still renders its content.
 * ----------------------------------------------------------------------- */
.faq-item .faq-answer{ max-height: 0; overflow: hidden; transition: max-height .35s cubic-bezier(.2,.72,.22,1); }
.faq-item.open .faq-answer{ max-height: 240px; }

/* --------------------------------------------------------------------------
 * The planner's step visibility, and why BOTH halves of it are here.
 *
 * `components/planner.mjs` used to write `display:none` onto steps 2-4 as
 * element css. Elementor scopes element css as
 * `.elementor-29 .elementor-element-<id>`, so that rule landed at (0,3,0) in the
 * post stylesheet while `.planner-step.active` below is (0,2,0). MEASURED:
 * forcing `active` onto step 2 in the DOM still computed `display:none` and
 * height 0. Steps 2-4 could not be shown by any correct script, and step 1 only
 * ever showed because nothing hid it — not because it was `.active`.
 *
 * So the whole state machine is two class rules in ONE stylesheet, where the
 * cascade between them is decidable, and the IR seeds `active` on step one so a
 * browser with JavaScript off still renders the first question. The
 * `:first-of-type` fallback that used to sit here is GONE: it was (0,2,0) too
 * and later in the file, so once the script advanced the planner it kept step 1
 * on screen underneath step 2.
 *
 * `block` AND NOT `var(--display)`, which is the container's own `flex`.
 * MEASURED on the live page before this change: step 1 computes `display:block`,
 * because this rule has always won over `.e-con{display:var(--display)}` — so
 * block flow, with the children's own margins doing the spacing, is what the
 * built page has always rendered and what design QA compared against. Restoring
 * the container's flex here would silently insert the step's `--gap` between the
 * label, the heading, the choices and the controls on top of those margins. The
 * step's gap is stated 0 in the IR for the same reason: a control with no effect
 * is a number that will be believed later.
 * ----------------------------------------------------------------------- */
.planner-step{ display: none; }
.planner-step.active{ display: block; }

/* The result panel ships with the `hidden` attribute and project.js removes it.
 * The rule is needed because Elementor's `.e-con{display:var(--display)}` is a
 * declaration, and a declaration beats the UA stylesheet's `[hidden]` no matter
 * what the attribute says — the panel would be permanently open without this.
 * `(0,1,1)` clears `.e-con`'s `(0,1,0)`. */
.result-panel[hidden]{ display: none; }

.project-item[hidden]{ display: none; }

/* --------------------------------------------------------------------------
 * `.text-link` — the underlined inline link.
 *
 *   style.css  .text-link{display:inline-flex;gap:.65rem;align-items:center;
 *                         padding:.35rem 0;border-bottom:1px solid}
 *
 * The declared border has NO colour, so it is `currentColor`, and that is what
 * makes it one rule instead of one per surface: the link is ink on the light
 * pages and inherits whatever the band sets anywhere else.
 *
 * IT LIVES HERE AND NOT ON AN ELEMENT because the three places it occurs —
 * `hello@nexora.com` on Contact, Privacy and Terms — are `<a>` tags inside the
 * inline HTML of three DIFFERENT components' text widgets. An anchor written
 * into a widget's content has no control of its own, and scoping the rule to
 * each of `contact-aside` and `chapter` would style the two components rather
 * than the link. A class shared by unrelated elements is exactly what the
 * shared stylesheet is for.
 *
 * WRITTEN AS THREE LONGHANDS, not `border-bottom: 1px solid currentColor`: a
 * shorthand is what the CSSOM expands before a check reads it, and a check
 * that compares declared text against a computed longhand reports every one of
 * them as a difference.
 *
 * THIS RULE WAS HELD BACK ONE ROUND ON PURPOSE. Until the project plugin was
 * active, every `<a>` on the site still computed the blocked plugin's
 * `#cc3366`, and `currentColor` would have drawn three pink rules under three
 * mailto links. Measured after activation: 0 of 31 anchors on `/services/`
 * render #cc3366, so `currentColor` is now the page's own ink.
 * ----------------------------------------------------------------------- */
.text-link{
  display: inline-flex;
  gap: .65rem;
  align-items: center;
  padding: .35rem 0;
  border-bottom-width: 1px;
  border-bottom-style: solid;
  border-bottom-color: currentColor;
}
