/* ---------------------------------------------------------------------------
 * premium.css — refinement layer, loaded last.
 *
 * Everything here is an override. No markup depends on it and nothing else
 * imports it, so deleting the <link> in postbuild.mjs reverts the site exactly.
 *
 * HARD CONSTRAINT: this file introduces no font and no colour.
 * The only colour values below are #2562FF and #FFFFFF, both already global
 * tokens in the Elementor kit (post-6.css), plus neutral black used solely as
 * shadow alpha — which is what the existing shadows already use.
 *
 * !important appears deliberately and only where a theme rule would otherwise
 * win on specificity. Each instance is justified at its use site.
 * ------------------------------------------------------------------------ */

:root {
  /* Motion. The theme's dominant transition is `all .4s ease` (352 rules).
     `ease` front-loads its acceleration, which reads as cheap on interface
     elements; this curve decelerates hard and settles, so movement feels like
     it has mass. Durations are split because press feedback must beat the
     eye (~150ms) while hover settle can afford to be unhurried. */
  --pr-ease: cubic-bezier(.32, .72, 0, 1);
  --pr-fast: 150ms;
  --pr-base: 260ms;

  /* Elevation. The site has 412 box-shadow declarations spanning
     `0 0 3px #444` to `0 42px 60px rgba(0,0,0,.3)` — no consistent light
     source and no ramp. These four are one light source directly above, each
     step a tight contact shadow plus a wide ambient one. Alpha stays low;
     depth comes from blur radius, not opacity. */
  --pr-e1: 0 1px 2px rgba(0,0,0,.04), 0 2px 6px rgba(0,0,0,.04);
  --pr-e2: 0 2px 4px rgba(0,0,0,.04), 0 6px 16px rgba(0,0,0,.06);
  --pr-e3: 0 4px 8px rgba(0,0,0,.04), 0 14px 32px rgba(0,0,0,.08);
  --pr-e4: 0 8px 16px rgba(0,0,0,.05), 0 28px 56px rgba(0,0,0,.10);

  /* Accent-tinted lift for the primary CTA only. Not a new colour: the theme
     already ships `0 12px 36px rgba(37,98,255,.1)`, so this is that idea at
     the strength a hover state needs. */
  --pr-glow: 0 10px 28px rgba(37, 98, 255, .26);

  /* Anchor landing clearance. Measured in Chrome, not assumed: this site has
     no sticky or fixed header on any of the 229 pages, so there is nothing to
     duck under and a large offset would just strand the target mid-viewport.
     24px is the optical gap that stops a heading sitting flush against the
     top edge. Raise this to the header height if one is ever made sticky. */
  --pr-anchor-offset: 24px;
}

/* --------------------------------------------------------------- motion feel
 * Only the timing function is replaced. transition-property and
 * transition-duration are left untouched on purpose: several widgets animate
 * background-position or width in ways this layer cannot see, and narrowing
 * the property list would silently kill them. Swapping the curve alone cannot
 * change *what* moves, only how it moves — so this is unbreakable by
 * construction while still being the single biggest perceived-quality change.
 *
 * !important: the theme sets the curve via the `transition` shorthand, which
 * a later longhand only beats at equal-or-higher specificity. Many of those
 * rules are descendant selectors, so a flat class list here would lose. */
a, button, input, select, textarea, summary, [role="button"],
.elementor-button, .elementor-button-link,
.ekit-menu-nav-link, .elementskit-btn-link, .ekit-btn-wraper > a,
.elementor-icon, .elementor-social-icon,
.elementskit-card, .elementskit-card-header,
.elementor-widget-icon-box, .elementor-icon-box-wrapper,
.elementor-icon-list-item, .service-item, .dropdown-item {
  transition-timing-function: var(--pr-ease) !important;
}

/* ------------------------------------------------------------ press feedback
 * The site has hover states but no pressed state anywhere, so clicks feel
 * like they land on glass. A sub-2% scale is below conscious notice and reads
 * purely as physical response.
 *
 * No !important: several Elementor button skins own :hover transform for
 * slide/fill effects. Leaving these beatable means those skins keep working
 * and this rule applies only where nothing else claims it. */
.elementor-button:active,
.elementskit-btn-link:active,
.ekit-btn-wraper > a:active,
button[type="submit"]:active,
input[type="submit"]:active {
  /* .985 was too polite to register. Press feedback has to be felt without being seen
     as a size change, and the band where that happens is roughly .95–.98 — under .95
     the control visibly shrinks, over .98 nothing lands. .97 is the middle of it. */
  transform: scale(.97);
  box-shadow: var(--pr-e1);
  transition-duration: var(--pr-fast);
}

/* ----------------------------------------------------------------- surfaces
 * The service cards are white, 40px-radius, and sit on the #F7F8FD page
 * background with box-shadow: none. Two near-white planes with no elevation
 * between them means the card edge is doing all the separation work, which is
 * what makes an otherwise well-built grid read as flat. A resting shadow gives
 * them a plane; the hover step gives them a response.
 *
 * transform is deliberately NOT touched here. These cards carry a
 * scroll-linked reveal that writes translateY every frame (measured
 * mid-scroll at `matrix(1,0,0,1,0,599)`), and adding a hover translate would
 * either be silently discarded or fight the reveal. Shadow alone cannot
 * collide with it. */
.service-item {
  box-shadow: var(--pr-e2);
}

/* Gated. On a touch screen a tap fires :hover and leaves it applied until something
   else is tapped, so an ungated hover state means one card sits permanently lifted out
   of a grid of otherwise flat ones — it reads as a selection the user did not make. */
@media (hover: hover) and (pointer: fine) {
  .service-item:hover {
    box-shadow: var(--pr-e4);
  }
}

/* Buttons get elevation on hover only. A resting shadow would be wrong on the
 * ghost and text variants that share the .elementor-button class -- a shadow
 * under a transparent element looks like a rendering fault. On hover every
 * variant has a solid surface, so the lift is unambiguous. Pairs with the
 * press feedback below: shadow grows on approach, collapses on contact. */
@media (hover: hover) and (pointer: fine) {
  .elementor-button:hover,
  .elementskit-btn:hover,
  .ekit-btn-wraper > a:hover,
  button[type="submit"]:hover,
  input[type="submit"]:hover {
    box-shadow: var(--pr-e3);
  }
}

/* ------------------------------------------------------------- focus rings
 * Eight theme rules set `outline: 0` / `outline: none`, which removes the
 * only affordance a keyboard user has. :focus-visible restores it for
 * keyboard and assistive tech without showing a ring on mouse clicks — the
 * reason those rules were written in the first place.
 *
 * !important: the rules being undone are `:focus` at specificity 0,2,0 and up.
 * The double ring (accent + white) keeps the indicator legible on both the
 * light sections and the dark footer without introducing a colour. */
:where(a, button, input, select, textarea, summary, [tabindex], [role="button"]):focus-visible {
  outline: 2px solid #2562FF !important;
  outline-offset: 3px !important;
  box-shadow: 0 0 0 5px rgba(255, 255, 255, .85) !important;
  border-radius: 4px;

  /* The theme transitions `all` at .4s, and outline-width is animatable, so
     without this the ring grows in from 0 rather than appearing -- measured in
     Chrome as nine running CSSTransitions on focus, including outline-width,
     outline-offset and box-shadow. Tabbing quickly then leaves the indicator
     visibly trailing the caret, which is the one thing a focus indicator must
     never do.

     This is the only place the layer narrows transition-property, which is
     otherwise avoided on purpose (see the motion-feel block above). The blast
     radius is one element in one state: the listed properties are the ones the
     theme actually animates on links and buttons, so hover colour and movement
     still ease normally while the ring itself is instant. */
  transition-property: color, background-color, border-color, opacity, transform !important;
}

/* Mouse users keep the clean look the theme intended. */
:where(a, button, input, select, textarea, summary, [tabindex]):focus:not(:focus-visible) {
  outline: none !important;
}

/* --------------------------------------------------------------- anchor jumps
 * Applied to [id] rather than :target so it also covers scrollIntoView.
 *
 * `scroll-behavior: smooth` was tried here and removed. On this page it does
 * not merely fail, it breaks: something in the theme's scroll handling writes
 * to the scroll position every frame, which cancels the native smooth-scroll
 * animation before it advances. Measured in Chrome — setting scrollTop with
 * `smooth` left the page at 0, the identical call with `auto` reached 1200.
 * Wheel and touch scrolling are unaffected by the property, but every anchor
 * link would have quietly stopped working. Do not reintroduce it without
 * re-testing that. */
[id] {
  scroll-margin-top: var(--pr-anchor-offset);
}

/* ------------------------------------------------------- typographic metrics
 * No typeface changes — this is line-breaking only. `balance` stops a heading
 * dropping one orphaned word onto its own line, which is the single most
 * common thing that makes otherwise good typography look unconsidered.
 * `pretty` does the narrower job of preventing orphans in body copy.
 * Both are progressive: browsers without support ignore them entirely. */
h1, h2, h3,
.elementor-heading-title,
.elementor-icon-box-title {
  text-wrap: balance;
}

p,
.elementor-icon-box-description,
.elementor-widget-text-editor p {
  text-wrap: pretty;
}

/* Counters and stats sit in a proportional font, so digits jitter as they
   tick. Manrope ships tabular figures; this asks for them. Same typeface. */
.elementor-counter-number,
.ekit-counter-number,
.elementor-counter-number-prefix,
.elementor-counter-number-suffix {
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}

/* ------------------------------------------------- hero background video cover
 * This is the black band under the menu on the homepage.
 *
 * Elementor ships the background video as `position:absolute; top:50%; left:50%;
 * transform:translate(-50%,-50%); object-fit:cover` and then leaves the *size* to
 * JavaScript, which measures the container and writes inline width/height. Until that
 * runs, the element sits at the video's own 16:9 box. Measured on the live deploy at
 * 1440x900: the hero section is 921px tall and the video is 810px, centred -- so a 55px
 * strip of the section shows above the video and another below it. The section's own
 * ::before overlay is 70% #15161B, so those strips render as near-black. That is the
 * band, and it lasts until the video has metadata: ~5.9s on a throttled 4 Mbps load.
 *
 * Preloading the section's background image (postbuild's injectHeroPreload) made the
 * strips paint sooner but could not remove them -- a darkened strip is still a dark
 * strip. Sizing the element in CSS removes them outright, because there is no frame in
 * which the video is anything other than the full size of its container.
 *
 * `inset:0` + `transform:none` replaces the centring, and the existing `object-fit:
 * cover` does the cropping the JS was emulating -- so the settled appearance is
 * unchanged, it just starts that way. !important because the values being beaten are
 * inline styles written by Elementor's handler.
 *
 * Not scoped to the homepage: any section with a video background has the same gap. */
.elementor .elementor-background-video-hosted {
  inset: 0 !important;
  width: 100% !important;
  height: 100% !important;
  transform: none !important;
  object-fit: cover;
}

/* ------------------------------------------------------------------ selection
 * Default selection blue clashes with the brand blue on every page. Uses the
 * existing accent token. */
::selection {
  background: #2562FF;
  color: #FFFFFF;
}

/* --------------------------------------------------------------- reduced motion
 * The site's own CSS declares no prefers-reduced-motion block at all, so a
 * user who has asked the OS to stop animation still gets 354 transitions and
 * the marquee.
 *
 * The ask is less motion, not none. Flattening every duration also flattens the fades
 * and colour changes, which do not move and are exactly what tells a user their hover,
 * focus or tap registered — strip those and the site reads as broken rather than calm.
 * So duration is set per property: the ones that move collapse, the ones that do not
 * keep a normal 240ms.
 *
 * The moving properties stay in the list rather than being dropped from it, for the
 * reason the old comment gave: transitionend must still fire or a carousel waiting on
 * it stalls. .01ms fires it on the next frame. The two lists are positional — eleven
 * properties, eleven durations — so they have to be edited together. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-property: opacity, color, background-color, border-color, box-shadow, fill, stroke, transform, filter, width, height !important;
    transition-duration: 240ms, 240ms, 240ms, 240ms, 240ms, 240ms, 240ms, .01ms, .01ms, .01ms, .01ms !important;
  }
}

/* ===========================================================================
 * OPT-IN — not active. Both change a colour, which is out of scope by
 * instruction. Kept here because both are real findings from the audit, and
 * each is one uncomment away if that call ever changes.
 *
 * 1. Soft black body text. 143 declarations set text to pure #000. Pure black
 *    on a light background is the highest-contrast pair a screen can produce
 *    and reads as harsh; every premium editorial site steps back from it. The
 *    value below is the existing brand ink #15161B, so this borrows from the
 *    palette rather than adding to it.
 *
 * 2. Ink-tinted shadows. The elevation scale above uses neutral black because
 *    that is what the shadows it replaces used. Tinting them toward the brand
 *    ink is what makes depth look art-directed instead of default.
 *
 * body, p, li, span, td { color: #15161B; }
 *
 * :root {
 *   --pr-e1: 0 1px 2px rgba(21,22,27,.05), 0 2px 6px rgba(21,22,27,.05);
 *   --pr-e2: 0 2px 4px rgba(21,22,27,.05), 0 6px 16px rgba(21,22,27,.07);
 *   --pr-e3: 0 4px 8px rgba(21,22,27,.05), 0 14px 32px rgba(21,22,27,.09);
 *   --pr-e4: 0 8px 16px rgba(21,22,27,.06), 0 28px 56px rgba(21,22,27,.11);
 * }
 * ======================================================================== */
