/* ==========================================================================
   Utilities
   Deliberately few. Reach for a component or a layout primitive first; this
   file is not a utility framework.
   ========================================================================== */

/* Available to assistive technology, removed from the visual layer. */
.visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

/* --------------------------------------------------------------------------
   Skip link
   Hidden until focused, then anchored to the top of the viewport so keyboard
   users can bypass the header (DESIGN.md 37).
   -------------------------------------------------------------------------- */

.skip-link {
    position: absolute;
    top: var(--space-2);
    left: var(--space-2);
    z-index: var(--z-toast);
    padding: var(--space-3) var(--space-5);
    background-color: var(--color-surface);
    color: var(--color-text-primary);
    border: var(--border-emphasis);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-md);
    text-decoration: none;
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-medium);
    /* Off-screen rather than display:none, so it remains focusable. */
    transform: translateY(calc(-100% - var(--space-4)));
    transition: transform var(--transition-fast);
}

/* :focus rather than :focus-visible. The link sits off-screen, so it cannot be
   reached by pointer, and :focus-visible heuristics do not fire for
   programmatic focus — which would leave the link invisible exactly when a
   screen reader or a script moved focus to it. */
.skip-link:focus {
    transform: translateY(0);
}

/* --------------------------------------------------------------------------
   Section reveal
   The hidden state is scoped to .reveal-ready, a class the reveal module adds
   only once it has an IntersectionObserver running. If the script fails, is
   blocked, or the user prefers reduced motion, the class never lands and every
   section is simply visible — content is never gated behind an animation.
   -------------------------------------------------------------------------- */

.reveal-ready [data-reveal] {
    opacity: 0;
    transform: translateY(1.75rem);
    transition: opacity var(--duration-editorial) var(--ease-out),
        transform var(--duration-editorial) var(--ease-out);
}

.reveal-ready [data-reveal].is-revealed {
    opacity: 1;
    transform: none;
}

/* Printing never scrolls, so the observer never fires. Content must not be
   able to vanish from a printed page. */
@media print {
    .reveal-ready [data-reveal] {
        opacity: 1;
        transform: none;
    }
}

/* --------------------------------------------------------------------------
   Scroll lock while the mobile panel is open
   -------------------------------------------------------------------------- */

body.is-nav-open {
    overflow: hidden;
}
