/**
 * Vastworx - L2 Components
 *
 * var() references ONLY. No hex, no raw font-size, no raw radius, no raw
 * duration. Those live in tokens.css. A literal here fails CI.
 *
 * Every transition enumerates its properties. The blanket "all" keyword is
 * banned: it animates whatever a future edit adds, including layout
 * properties, and makes performance unauditable. The theme this replaces
 * used it in 19 of its 27 transitions.
 */

/* --- Base ---------------------------------------------------------------- */

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

body {
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

/* Anchored headings clear the sticky header instead of hiding under it. The
   classic theme solved this with an 80px magic number inside a jQuery handler. */
:where(h1, h2, h3, h4, h5, h6, [id]) {
    scroll-margin-top: var(--wp--preset--spacing--80);
}

::selection {
    background-color: var(--vw-accent);
    color: var(--vw-accent-ink);
}

/* --- Focus: one ring, everywhere ----------------------------------------- */

/* :focus-visible, never :focus. Mouse users get no ring, keyboard users always
   do. outline (not box-shadow) so the ring follows border-radius and stays
   visible on an accent fill - which is why --vw-focus is its own role rather
   than an alias of --vw-accent. */
:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
    outline: 2px solid var(--vw-focus);
    outline-offset: 2px;
    border-radius: var(--vw-radius-sm);
}

.skip-link {
    position: absolute;
    left: -9999px;
    top: 0;
    z-index: 100;
    padding: var(--wp--preset--spacing--30) var(--wp--preset--spacing--40);
    background-color: var(--vw-accent);
    color: var(--vw-accent-ink);
    border-radius: var(--vw-radius-sm);
}

.skip-link:focus {
    left: var(--wp--preset--spacing--40);
    top: var(--wp--preset--spacing--40);
}

/* --- Icons --------------------------------------------------------------- */

.vw-icon {
    display: inline-block;
    vertical-align: middle;
    flex-shrink: 0;
    fill: none;
    stroke: currentColor;
}

/* --- Card: ONE treatment, replacing six ---------------------------------- */

/* Hover moves the card UP THE ELEVATION LADDER, which is semantically what
   hover means. No translateY, no shadow, no scale: shadows do not read on a
   near-black canvas, a lift without a shadow is motion without cause, and the
   lift is the defining gesture of the bubbly-SaaS grid this replaces. */
.is-style-vw-card {
    background-color: var(--vw-surface);
    border: var(--vw-border-width) solid var(--vw-border);
    border-radius: var(--vw-radius-md);
    padding: var(--wp--preset--spacing--50);
    transition:
        background-color var(--vw-dur-fast) var(--vw-ease-out),
        border-color     var(--vw-dur-fast) var(--vw-ease-out);
}

.is-style-vw-card:hover {
    background-color: var(--vw-raised);
    border-color: var(--vw-border-strong);
}

.is-style-vw-card:focus-within {
    outline: 2px solid var(--vw-focus);
    outline-offset: 2px;
}

.is-style-vw-card-featured {
    background-color: var(--vw-raised);
    border: var(--vw-border-width) solid var(--vw-accent);
    border-radius: var(--vw-radius-md);
    padding: var(--wp--preset--spacing--50);
}

/* Replaces the 80x80 gradient-filled circle, which was declared at 60x60
   flat-fill in one file and 80x80 gradient in another. On a feature card the
   icon is a scanning aid, not an illustration; an 80px filled circle
   out-weighs the title it introduces and inverts the hierarchy. */
.vw-feature-icon {
    color: var(--vw-accent-hover);
    margin-bottom: var(--wp--preset--spacing--30);
}

/* --- Eyebrow: the one place mono appears outside code -------------------- */

.is-style-vw-eyebrow {
    font-family: var(--wp--preset--font-family--mono);
    font-size: var(--wp--preset--font-size--2xs);
    font-weight: 500;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--vw-text-muted);
}

/* --- Check list ---------------------------------------------------------- */

.is-style-vw-check-list {
    list-style: none;
    padding-left: 0;
}

.is-style-vw-check-list li {
    position: relative;
    padding-left: var(--wp--preset--spacing--60);
    margin-bottom: var(--wp--preset--spacing--30);
    color: var(--vw-text-secondary);
}

.is-style-vw-check-list li::before {
    content: "";
    position: absolute;
    left: 0;
    top: 0.45em;
    width: 10px;
    height: 6px;
    border-left: 2px solid var(--vw-success);
    border-bottom: 2px solid var(--vw-success);
    transform: rotate(-45deg);
}

/* --- Separator ----------------------------------------------------------- */

.is-style-vw-hairline {
    border: 0;
    border-top: var(--vw-border-width) solid var(--vw-border);
    opacity: 1;
    width: 100%;
}

/* --- Table --------------------------------------------------------------- */

.wp-block-table {
    overflow-x: auto;
}

.wp-block-table table {
    width: 100%;
    border-collapse: separate;
    border-spacing: 0;
}

.wp-block-table th,
.wp-block-table td {
    padding: var(--wp--preset--spacing--30) var(--wp--preset--spacing--40);
    border-bottom: var(--vw-border-width) solid var(--vw-border);
    text-align: start;
}

.wp-block-table thead th {
    background-color: var(--vw-raised);
    font-size: var(--wp--preset--font-size--2xs);
    font-weight: 500;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--vw-text-secondary);
}

.wp-block-table tbody tr:last-child td {
    border-bottom: 0;
}

.wp-block-table tbody tr {
    transition: background-color var(--vw-dur-fast) var(--vw-ease-out);
}

.wp-block-table tbody tr:hover {
    background-color: var(--vw-raised);
}

/* Numeric columns never jitter between rows. A throughput or latency figure
   that shifts horizontally undermines the claim it is making. */
.vw-numeric {
    font-family: var(--wp--preset--font-family--mono);
    font-variant-numeric: tabular-nums;
    text-align: end;
}

.is-style-vw-comparison table {
    background-color: var(--vw-surface);
    border: var(--vw-border-width) solid var(--vw-border);
    border-radius: var(--vw-radius-md);
    overflow: hidden;
}

.is-style-vw-comparison td:not(:first-child),
.is-style-vw-comparison th:not(:first-child) {
    text-align: center;
}

/* --- Code ---------------------------------------------------------------- */

.wp-block-code {
    position: relative;
}

.wp-block-code pre,
.wp-block-code code {
    overflow-x: auto;
    white-space: pre;
    tab-size: 2;
}

:where(:not(pre) > code) {
    background-color: var(--vw-raised);
    border: var(--vw-border-width) solid var(--vw-border);
    border-radius: var(--vw-radius-sm);
    padding: 2px 6px;
    font-family: var(--wp--preset--font-family--mono);
    font-size: 0.9em;
    color: var(--vw-text-primary);
}

/* Defined once, here. In the classic theme this button was styled only inside
   the showcase page template while main.js injected it onto every pre > code
   site-wide, so it rendered unstyled on every other page. */
.vw-copy-code {
    position: absolute;
    top: var(--wp--preset--spacing--20);
    inset-inline-end: var(--wp--preset--spacing--20);
    display: inline-flex;
    align-items: center;
    gap: var(--wp--preset--spacing--10);
    height: var(--vw-control-sm);
    padding: 0 var(--wp--preset--spacing--30);
    background-color: transparent;
    color: var(--vw-text-secondary);
    border: var(--vw-border-width) solid transparent;
    border-radius: var(--vw-radius-sm);
    font-family: var(--wp--preset--font-family--body);
    font-size: var(--wp--preset--font-size--2xs);
    font-weight: 500;
    cursor: pointer;
    opacity: 0;
    transition:
        opacity          var(--vw-dur-fast) var(--vw-ease-out),
        background-color var(--vw-dur-fast) var(--vw-ease-out),
        border-color     var(--vw-dur-fast) var(--vw-ease-out),
        color            var(--vw-dur-fast) var(--vw-ease-out);
}

.wp-block-code:hover .vw-copy-code,
.vw-copy-code:focus-visible {
    opacity: 1;
}

.vw-copy-code:hover {
    background-color: var(--vw-raised);
    border-color: var(--vw-border-strong);
    color: var(--vw-text-primary);
}

/* Marks a sample as illustrative rather than a published interface. */
.vw-code-note {
    display: block;
    margin-top: var(--wp--preset--spacing--20);
    font-family: var(--wp--preset--font-family--mono);
    font-size: var(--wp--preset--font-size--2xs);
    color: var(--vw-text-muted);
}

/* --- Forms --------------------------------------------------------------- */

/* border-control is a separate token because WCAG 1.4.11 requires 3:1 for
   interactive boundaries. The classic theme's two border tokens shared a hex
   and neither met it, which is why its inputs had no perceptible edge. Inputs
   sit on canvas or surface only, never raised, which keeps 3.23:1 valid. */
input[type="text"],
input[type="email"],
input[type="url"],
input[type="password"],
input[type="search"],
input[type="number"],
input[type="tel"],
select,
textarea,
.wp-block-search__input {
    width: 100%;
    min-height: var(--vw-control-md);
    padding: var(--wp--preset--spacing--30) var(--wp--preset--spacing--40);
    background-color: var(--vw-surface);
    color: var(--vw-text-primary);
    border: var(--vw-border-width) solid var(--vw-border-control);
    border-radius: var(--vw-radius-sm);
    font-family: var(--wp--preset--font-family--body);
    font-size: var(--wp--preset--font-size--xs);
    transition:
        border-color     var(--vw-dur-fast) var(--vw-ease-out),
        background-color var(--vw-dur-fast) var(--vw-ease-out);
}

::placeholder {
    color: var(--vw-text-muted);
    opacity: 1;
}

input:hover,
select:hover,
textarea:hover {
    border-color: var(--vw-text-muted);
}

input:focus-visible,
select:focus-visible,
textarea:focus-visible {
    border-color: var(--vw-accent);
    outline: 2px solid var(--vw-focus);
    outline-offset: 1px;
}

input:disabled,
select:disabled,
textarea:disabled {
    background-color: var(--vw-canvas);
    color: var(--vw-text-muted);
    cursor: not-allowed;
}

[aria-invalid="true"] {
    border-color: var(--vw-danger);
}

/* --- Badge / chip -------------------------------------------------------- */

.vw-badge {
    display: inline-flex;
    align-items: center;
    gap: var(--wp--preset--spacing--10);
    height: 22px;
    padding: 2px var(--wp--preset--spacing--20);
    background-color: var(--vw-raised);
    color: var(--vw-text-secondary);
    border: var(--vw-border-width) solid var(--vw-border);
    border-radius: var(--vw-radius-sm);
    font-size: var(--wp--preset--font-size--2xs);
    font-weight: 500;
    letter-spacing: 0.02em;
    white-space: nowrap;
}

.vw-badge--accent {
    background-color: color-mix(in oklab, var(--vw-accent) 12%, transparent);
    color: var(--vw-accent-hover);
    border-color: color-mix(in oklab, var(--vw-accent) 30%, transparent);
}

.vw-badge--success {
    background-color: var(--vw-success-bg);
    color: var(--vw-success);
    border-color: color-mix(in oklab, var(--vw-success) 30%, transparent);
}

/* The --vw-radius-full allowlist: this component and .vw-avatar. Nothing else. */
.vw-status-dot {
    width: 8px;
    height: 8px;
    border-radius: var(--vw-radius-full);
    background-color: currentColor;
    flex-shrink: 0;
}

.vw-avatar {
    border-radius: var(--vw-radius-full);
}

/* --- Header / navigation ------------------------------------------------- */

.vw-header {
    border-bottom: var(--vw-border-width) solid var(--vw-border);
    /* Never wrap a token in an rgba() or hsla() call: a token holds a hex,
       not channel triplets, so the declaration is invalid and silently drops.
       That bug is live in the theme this replaces, at style.css:248. */
    background-color: color-mix(in oklab, var(--vw-canvas) 88%, transparent);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
}

.wp-block-navigation .wp-block-navigation-item__content {
    padding: var(--wp--preset--spacing--20) var(--wp--preset--spacing--30);
    border-radius: var(--vw-radius-sm);
    transition:
        color            var(--vw-dur-fast) var(--vw-ease-out),
        background-color var(--vw-dur-fast) var(--vw-ease-out);
}

.wp-block-navigation .wp-block-navigation-item__content:hover {
    background-color: var(--vw-surface);
    color: var(--vw-text-primary);
}

.wp-block-navigation .current-menu-item > .wp-block-navigation-item__content {
    color: var(--vw-text-primary);
}

.wp-block-navigation__submenu-container {
    background-color: var(--vw-overlay);
    border: var(--vw-border-width) solid var(--vw-border-strong);
    border-radius: var(--vw-radius-md);
    box-shadow: var(--vw-shadow-overlay);
    padding: var(--wp--preset--spacing--20);
}

/* --- Section bands ------------------------------------------------------- */

/* Adjacent bands must not share a background. Alternating canvas/surface is
   the only page-level separation mechanism; there are no hr dividers. */
.vw-band {
    padding-block: var(--wp--preset--spacing--80);
}

.vw-band-hero {
    padding-block: var(--wp--preset--spacing--90);
}

@media (min-width: 782px) {
    .vw-band          { padding-block: var(--wp--preset--spacing--90); }
    .vw-band-hero    { padding-block: var(--wp--preset--spacing--100); }
    .vw-band-compact { padding-block: var(--wp--preset--spacing--80); }
}

/* --- Figures ------------------------------------------------------------- */

/* A figure is either entirely HTML or entirely SVG, never an SVG overlay
   positioned over HTML. The classic theme's editor mock used flex-positioned
   divs with an absolutely-positioned svg on top whose fixed coordinates could
   not track them, so its connector lines detached at every breakpoint. */
.vw-figure {
    display: block;
    width: 100%;
    height: auto;
    border: var(--vw-border-width) solid var(--vw-border);
    border-radius: var(--vw-radius-lg);
    background-color: var(--vw-surface);
}

.vw-figure text {
    font-family: var(--wp--preset--font-family--mono);
}

/* --- Back to top --------------------------------------------------------- */

/* Real markup in footer.html, not JS-injected. Being injected is precisely why
   .back-to-top had no styles in the classic theme and rendered as a raw
   browser button pinned in the document flow. */
.vw-to-top {
    position: fixed;
    inset-block-end: var(--wp--preset--spacing--50);
    inset-inline-end: var(--wp--preset--spacing--50);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: var(--vw-control-md);
    height: var(--vw-control-md);
    background-color: var(--vw-overlay);
    color: var(--vw-text-secondary);
    border: var(--vw-border-width) solid var(--vw-border-strong);
    border-radius: var(--vw-radius-sm);
    box-shadow: var(--vw-shadow-overlay);
    cursor: pointer;
    opacity: 0;
    visibility: hidden;
    transform: translateY(8px);
    transition:
        opacity    var(--vw-dur-base) var(--vw-ease-out),
        transform  var(--vw-dur-base) var(--vw-ease-out),
        visibility var(--vw-dur-base) var(--vw-ease-out),
        color      var(--vw-dur-fast) var(--vw-ease-out);
}

.vw-to-top.is-visible {
    opacity: 1;
    visibility: visible;
    transform: translateY(0);
}

.vw-to-top:hover {
    color: var(--vw-text-primary);
}

/* --- Theme toggle -------------------------------------------------------- */

.vw-theme-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: var(--vw-control-sm);
    height: var(--vw-control-sm);
    background-color: transparent;
    color: var(--vw-text-secondary);
    border: var(--vw-border-width) solid transparent;
    border-radius: var(--vw-radius-sm);
    cursor: pointer;
    transition:
        color            var(--vw-dur-fast) var(--vw-ease-out),
        background-color var(--vw-dur-fast) var(--vw-ease-out),
        border-color     var(--vw-dur-fast) var(--vw-ease-out);
}

.vw-theme-toggle:hover {
    background-color: var(--vw-surface);
    border-color: var(--vw-border-strong);
    color: var(--vw-text-primary);
}

/* Icon swap is CSS keyed on the [data-theme] attribute, not a className
   rewrite from JS. Dark is the default, so the sun (switch to light) shows. */
.vw-theme-toggle .vw-icon--moon { display: none; }
.vw-theme-toggle .vw-icon--sun  { display: block; }

[data-theme="light"] .vw-theme-toggle .vw-icon--moon { display: block; }
[data-theme="light"] .vw-theme-toggle .vw-icon--sun  { display: none; }

/* --- Scroll reveal ------------------------------------------------------- */

/* The initial hidden state is added by JS, never declared here. If it lived in
   the stylesheet, a visitor with JS disabled or without IntersectionObserver
   would see permanently invisible content - a live bug in the theme this
   replaces, where .animate-on-scroll sets opacity:0 in CSS. */
.vw-reveal {
    opacity: 0;
    transform: translateY(8px);
    transition:
        opacity   300ms var(--vw-ease-out),
        transform 300ms var(--vw-ease-out);
}

.vw-reveal.is-revealed {
    opacity: 1;
    transform: translateY(0);
}

/* --- Reduced motion ------------------------------------------------------ */

@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;
    }

    html {
        scroll-behavior: auto;
    }

    /* Belt and braces: the reveal script already skips adding .vw-reveal under
       reduced motion, but if it ever ran anyway the content must still show. */
    .vw-reveal {
        opacity: 1;
        transform: none;
    }
}

/* --- Buttons: the secondary variant ---------------------------------------- */

/* Core's is-style-outline is transparent with a currentColor border, which on
   this canvas renders as a bright white outline -- louder than the primary
   button it is meant to sit beside. The design system's secondary button is a
   surface fill with a quiet border, so emphasis is carried by colour rather
   than by weight.
   This was specified from the start but only ever implemented in the preview
   harness; the real theme was falling through to core's default. */
.wp-block-button.is-style-outline > .wp-element-button,
.wp-block-button .wp-element-button.is-style-outline {
    background-color: var(--vw-surface);
    color: var(--vw-text-primary);
    border: var(--vw-border-width) solid var(--vw-border-strong);
    transition:
        background-color var(--vw-dur-fast) var(--vw-ease-out),
        border-color     var(--vw-dur-fast) var(--vw-ease-out),
        color            var(--vw-dur-fast) var(--vw-ease-out);
}

.wp-block-button.is-style-outline > .wp-element-button:hover,
.wp-block-button .wp-element-button.is-style-outline:hover {
    background-color: var(--vw-raised);
    border-color: var(--vw-border-control);
    color: var(--vw-text-primary);
}

/* The only transform on a button. */
.wp-element-button:active {
    transform: translateY(1px);
}

.wp-element-button:disabled,
.wp-element-button[aria-disabled="true"] {
    opacity: 0.45;
    cursor: not-allowed;
    pointer-events: none;
}

/* --- Site branding ---------------------------------------------------------- */

/* The header carries both a Site Logo and a Site Title block, because a block
   template is static HTML and cannot ask whether a logo has been uploaded.
   Left alone that renders the logo AND the name side by side, which is
   redundant when the logo is a lockup that already contains the name.
   WordPress omits the Site Logo block entirely when no logo is set, so :has()
   can do the branching that the template cannot: logo present, show the logo;
   no logo, fall back to the site name. Browsers without :has() show both,
   which is the old behaviour rather than a broken one. */
.wp-block-site-logo:has(img) ~ .wp-block-site-title {
    display: none;
}

/* Constrain the logo by HEIGHT, not width. A square mark and a wide wordmark
   lockup need very different widths; both sit correctly at a fixed height.
   A hardcoded pixel width in the block squashed a 360x96 lockup to 32px wide
   and made it unreadable. */
.wp-block-site-logo img {
    height: 28px;
    width: auto;
    max-width: 220px;
    object-fit: contain;
}

@media (max-width: 781px) {
    .wp-block-site-logo img {
        height: 22px;
        max-width: 150px;
    }
}
