/* Riptide Labs — reset + primitives shared across every page.
   Tokens come from colors_and_type.css (enqueued first). */

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

/* scroll-padding-top keeps in-page anchor jumps (#pures, #coa, #shop, #science)
   from landing under the sticky nav. */
html { scroll-behavior: smooth; scroll-padding-top: 72px; }

html, body {
    background: var(--paper);
    color: var(--ink);
    font-family: var(--font-body);
    /* `clip`, not `hidden`: hidden on the root makes html/body a scroll
       container, which on iOS Safari can disable vertical touch-scrolling and
       can break `position: sticky` (the nav). `overflow-x: clip` contains the
       wide marquee/ticker without creating a scroll container, so vertical
       scrolling and the sticky nav keep working everywhere. */
    overflow-x: clip;
}

body { cursor: default; }

/* Lock background scroll while the mobile menu or cart drawer is open. */
body.rt-menu-open,
body.rt-drawer-open { overflow: hidden; }

img { display: block; max-width: 100%; }

button {
    font: inherit;
    cursor: pointer;
    border: none;
    background: none;
    color: inherit;
}

a { color: inherit; text-decoration: none; }

/* ---------- Primitives ---------- */
.cap { font-weight: 500; font-size: 11px; letter-spacing: .22em; text-transform: uppercase; color: var(--ink); }
.cap-sm { font-weight: 500; font-size: 10px; letter-spacing: .22em; text-transform: uppercase; }
.mono { font-family: var(--font-mono); font-size: 11px; letter-spacing: .04em; }

.axis { display: flex; align-items: center; gap: 12px; font-weight: 500; font-size: 11px; letter-spacing: .22em; text-transform: uppercase; }
.axis::before, .axis::after { content: ''; flex: 1; height: 1px; background: currentColor; opacity: .55; }
.axis .d { width: 6px; height: 6px; border-radius: 50%; background: currentColor; }

.axis-left { display: flex; align-items: center; gap: 12px; font-weight: 500; font-size: 11px; letter-spacing: .22em; text-transform: uppercase; }
.axis-left::after { content: ''; flex: 1; height: 1px; background: currentColor; opacity: .55; }
.axis-left .d { width: 6px; height: 6px; border-radius: 50%; background: currentColor; }

.dot-trail { display: inline-flex; gap: 10px; align-items: center; }
.dot-trail i { width: 4px; height: 4px; border-radius: 50%; background: currentColor; display: block; }

.display { font-family: var(--font-display); font-weight: 600; text-transform: uppercase; letter-spacing: -.03em; line-height: .92; }
.body-wide { font-weight: 500; font-size: 12px; line-height: 1.75; letter-spacing: .22em; text-transform: uppercase; text-align: justify; }

.btn {
    font-weight: 500; font-size: 11px; letter-spacing: .22em; text-transform: uppercase;
    padding: 15px 24px;
    background: var(--ink); color: var(--paper);
    display: inline-flex; align-items: center; gap: 12px;
    transition: background .22s var(--ease-standard);
    border: 1px solid var(--ink);
}
.btn:hover { background: var(--n-1000); }
.btn.ghost { background: transparent; color: var(--ink); }
.btn.ghost:hover { background: var(--ink); color: var(--paper); }
.btn .arr { display: inline-block; transition: transform .22s var(--ease-standard); }
.btn:hover .arr { transform: translateX(4px); }

/* Reveal — progressive enhancement.
   The `.has-reveal-js` class is added to <html> by home.js once the
   IntersectionObserver hooks up. If the script fails to load (e.g. in
   an environment missing a dependency), the reveal styles never apply
   and content stays visible instead of being permanently invisible. */
.has-reveal-js [data-reveal] { opacity: 0; transform: translateY(24px); transition: opacity .8s var(--ease-out), transform .8s var(--ease-out); }
.has-reveal-js [data-reveal].in { opacity: 1; transform: none; }
.has-reveal-js [data-reveal-stagger] > * { opacity: 0; transform: translateY(18px); transition: opacity .8s var(--ease-out), transform .8s var(--ease-out); }
.has-reveal-js [data-reveal-stagger].in > * { opacity: 1; transform: none; }
[data-reveal-stagger].in > *:nth-child(1) { transition-delay: 0ms; }
[data-reveal-stagger].in > *:nth-child(2) { transition-delay: 60ms; }
[data-reveal-stagger].in > *:nth-child(3) { transition-delay: 120ms; }
[data-reveal-stagger].in > *:nth-child(4) { transition-delay: 180ms; }
[data-reveal-stagger].in > *:nth-child(5) { transition-delay: 240ms; }
[data-reveal-stagger].in > *:nth-child(6) { transition-delay: 300ms; }

/* Sold-out state — replaces the "Add" button when a product is out of stock
   (catalog held unpurchasable while the store is live but not yet selling). */
.add.sold-out {
    pointer-events: none;
    cursor: not-allowed;
    opacity: .55;
    color: var(--ink-3);
    background: transparent;
    border-color: var(--hairline);
}

/* ---------- Reduced motion ----------
   The homepage runs several perpetual animations (ticker, marquee, testimonial
   track, hero bottle float, pulse, scroll-cue) plus reveal transitions. Honor
   a visitor's reduced-motion preference by neutralizing animation/transition
   duration site-wide — content still appears, it just stops moving. */
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: .001ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: .001ms !important;
    }
    html { scroll-behavior: auto !important; }
}
