/**
 * NextForLab — named components.
 *
 * Single responsibility: the reusable pieces that need real CSS rather than
 * Tailwind utilities — buttons, inputs, navigation, hero field, console,
 * marquee.
 *
 * Requires css/tokens.css and css/base.css to load first.
 */

/* ----------------------------------------------------------------- buttons */

/*
 * Buttons are deliberately square-cut: monospace label, hard corners, flat
 * fill. The default is the signal-red action; .btn-dark inverts for use on
 * an accent-filled surface.
 */
.btn {
    display: inline-flex;
    place-content: center;
    place-items: center;
    gap: 10px;
    width: max-content;
    padding: 14px 24px;
    color: var(--btn-color);
    background-color: var(--btn-bg);
    border: 1px solid transparent;
    font-family: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 0.8125rem;
    font-weight: 500;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    text-align: center;
    cursor: pointer;
    touch-action: manipulation;
    transition: background-color 0.2s ease, border-color 0.2s ease, color 0.2s ease, transform 0.2s ease;
}

.btn:hover {
    background-color: var(--btn-bg-hover);
}

.btn:active {
    transform: translateY(1px);
}

.btn:disabled {
    opacity: 0.55;
    cursor: not-allowed;
    transform: none;
}

/* Compact variant for the header, where the row is only 60px tall. */
.btn-slim {
    gap: 8px;
    padding: 8px 16px;
    font-size: 0.75rem;
}

/* The slim button lands at 36px tall, under the 44px both mobile platforms ask
   for. Only the padding grows, so the button looks unchanged. */
@media (max-width: 767px), (pointer: coarse) {
    .btn-slim {
        padding: 13px 16px;
    }
}

/* Near-black action for placement on the accent-filled hero. */
.btn-dark {
    color: var(--cream);
    background-color: #0f0c0a;
    border-color: #0f0c0a;
}

.btn-dark:hover {
    background-color: #241d19;
}

.btn-ghost {
    color: var(--text);
    background-color: transparent;
    border-color: var(--border);
}

.btn-ghost:hover {
    color: var(--text);
    background-color: var(--surface);
    border-color: var(--accent-500);
}

/* ------------------------------------------------------------------ inputs */

.input {
    width: 100%;
    padding: 12px 14px;
    color: var(--text);
    background-color: var(--input-bg);
    border: 1px solid var(--input-border);
    border-radius: 0;
    outline: none;
    transition: border-color 0.2s ease, box-shadow 0.2s ease;
}

.input::placeholder {
    color: var(--text-muted);
}

.input:hover {
    border-color: var(--text-muted);
}

.input:focus {
    border-color: var(--input-border-focus);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--input-border-focus) 20%, transparent);
}

.input[aria-invalid='true'] {
    border-color: var(--error);
}

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

.footer-link {
    width: fit-content;
    color: var(--footer-link);
    transition: color 0.2s ease;
}

.footer-link:hover {
    color: var(--footer-link-hover);
}

/*
 * On touch screens these links are the only navigation the site has, and at
 * their natural 20px line box they are well under the 44px Apple and Google
 * both recommend (WCAG 2.5.8 asks 24px). Growing the hit area rather than the
 * type keeps the footer looking identical while making it tappable.
 */
@media (max-width: 767px), (pointer: coarse) {
    .footer-link {
        display: flex;
        place-items: center;
        min-height: 44px;
    }
}

/* -------------------------------------------------------------------- hero */

/*
 * The accent field: a flat block of signal red with a faint dark ruled grid so
 * the surface reads as engineered rather than painted.
 */
.hero-field {
    background-color: var(--accent-500);
    background-image:
        linear-gradient(#0f0c0a12 1px, transparent 1px),
        linear-gradient(90deg, #0f0c0a12 1px, transparent 1px);
    background-size: 72px 72px;
}

/* Fine dot grid for the dark band beneath the accent field. */
.hero-surface {
    background-image: radial-gradient(circle at center, var(--dot-color) 1.1px, transparent 1.2px);
    background-size: 26px 26px;
    background-position: center top;
    background-repeat: repeat;
}

/*
 * Hero console. scripts/reveal.js writes --console-tilt / --console-scale on
 * scroll so the mockup straightens as it enters view. The defaults below are
 * the resting state used when JS or motion is unavailable.
 */
.console {
    --console-tilt: 0deg;
    --console-scale: 1;
    transform: perspective(1400px) rotateX(var(--console-tilt)) scale(var(--console-scale));
    transform-origin: center top;
    will-change: transform;
}

.caret::after {
    content: '';
    display: inline-block;
    width: 7px;
    height: 1.05em;
    margin-left: 4px;
    vertical-align: text-bottom;
    background-color: var(--accent-500);
    animation: caret-blink 1s steps(2, start) infinite;
}

@keyframes caret-blink {
    to { visibility: hidden; }
}

/* ----------------------------------------------------------------- marquee */

.marquee {
    display: flex;
    width: 100%;
    overflow: hidden;
    /* Fade the logo strip at both edges instead of cutting it off hard. */
    mask-image: linear-gradient(90deg, transparent, #000 12%, #000 88%, transparent);
    -webkit-mask-image: linear-gradient(90deg, transparent, #000 12%, #000 88%, transparent);
}

.marquee__track {
    display: flex;
    flex-shrink: 0;
    gap: 4rem;
    padding-right: 4rem;
    animation: marquee-scroll 34s linear infinite;
}

.marquee:hover .marquee__track,
.marquee:focus-within .marquee__track {
    animation-play-state: paused;
}

@keyframes marquee-scroll {
    from { transform: translateX(0); }
    to { transform: translateX(-100%); }
}

/*
 * At desktop widths a 4rem gap reads as a calm ticker. On a 390px screen the
 * same gap leaves barely two logos on screen with holes between them, so the
 * strip looks broken rather than sparse. Tighten the rhythm and pull the edge
 * fade in, which otherwise eats a quarter of the visible width.
 */
@media (max-width: 767px) {
    .marquee {
        mask-image: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent);
        -webkit-mask-image: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent);
    }

    .marquee__track {
        gap: 2.25rem;
        padding-right: 2.25rem;
    }

    .marquee__track li {
        width: 88px;
    }
}

/* ------------------------------------------------------------------ footer */

/* The one warm note in an otherwise monochrome footer: a small signal-red
   heartbeat next to the "Built with" credit line. */
.footer-heart {
    display: inline-block;
    color: var(--accent-500);
    animation: heart-pulse 1.8s ease-in-out infinite;
}

@media (prefers-reduced-motion: reduce) {
    .footer-heart {
        animation: none;
    }
}

@keyframes heart-pulse {
    0%, 100% { transform: scale(1); }
    50% { transform: scale(1.25); }
}

