/* ==========================================================================
   CocoSeller — Utilities
   Single-purpose helpers and motion primitives. Prefix: .u-
   Keep this file small: if a pattern needs three utilities, make a component.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Theme inversion — re-declares semantic tokens for dark sections
   -------------------------------------------------------------------------- */

.u-theme-dark {
    --color-bg:             var(--coco-green-900);
    --color-bg-subtle:      var(--coco-green-800);
    --color-bg-muted:       var(--coco-green-800);
    --color-surface:        var(--coco-green-800);
    --color-text:           var(--coco-green-100);
    --color-text-strong:    var(--coco-cream-50);
    --color-text-muted:     var(--coco-green-200);
    --color-text-subtle:    var(--coco-green-300);
    --color-heading:        var(--coco-cream-50);
    --color-brand:          var(--coco-green-300);
    --color-brand-strong:   var(--coco-cream-50);
    --color-brand-soft:     var(--coco-green-800);
    --color-brand-contrast: var(--coco-green-900);
    --color-link:           var(--coco-green-200);
    --color-link-hover:     var(--coco-white);
    --color-border:         var(--color-border-inverse);
    --color-border-subtle:  rgba(255, 255, 255, 0.10);
    --color-border-strong:  rgba(255, 255, 255, 0.30);
    --color-border-brand:   var(--coco-green-400);

    background-color: var(--color-bg);
    color: var(--color-text);
}

/* Warm substrate ground — for material/product storytelling sections */
.u-theme-coir {
    --color-bg:            var(--coco-coir-50);
    --color-bg-subtle:     var(--coco-coir-100);
    --color-bg-muted:      var(--coco-coir-200);
    --color-border:        var(--coco-coir-200);
    --color-border-subtle: var(--coco-coir-100);
    --color-brand:         var(--coco-coir-700);

    background-color: var(--color-bg);
}

/* --------------------------------------------------------------------------
   2. Reveal animations — driven by assets/js/reveal.js
   The hidden state only applies when JS is running (html.js), so content is
   always visible if JavaScript fails or is disabled.
   -------------------------------------------------------------------------- */

.js [data-reveal] {
    opacity: 0;
    will-change: opacity, transform;
    transition:
        opacity var(--reveal-duration) var(--reveal-easing) var(--reveal-delay, 0ms),
        transform var(--reveal-duration) var(--reveal-easing) var(--reveal-delay, 0ms),
        clip-path var(--reveal-duration) var(--reveal-easing) var(--reveal-delay, 0ms);
}

.js [data-reveal="up"]    { transform: translateY(var(--reveal-distance)); }
.js [data-reveal="down"]  { transform: translateY(calc(var(--reveal-distance) * -1)); }
.js [data-reveal="left"]  { transform: translateX(var(--reveal-distance)); }
.js [data-reveal="right"] { transform: translateX(calc(var(--reveal-distance) * -1)); }
.js [data-reveal="fade"]  { transform: none; }
.js [data-reveal="scale"] { transform: scale(0.97); }

/*
 * Image mask reveal.
 *
 * THE CLIP GOES ON THE CHILDREN, NOT ON THE OBSERVED ELEMENT. This is not a
 * style preference; it is the difference between the reveal working and the
 * element being invisible for ever.
 *
 * reveal.js reveals on IntersectionObserver. A `clip-path` that hides the
 * element clips it to ZERO AREA, and an element of zero area never intersects
 * anything: Chromium reports intersectionRect 0x0 and isIntersecting false,
 * even at threshold 0, while boundingClientRect is still full size. So the
 * element hid itself in a way that guaranteed it could never be told to stop
 * hiding — a deadlock, not a race. It was permanent, on every viewport, and it
 * silently applied to every mask and mask-left element on the site.
 *
 * Clipping the children instead leaves the observed element at full area, so it
 * intersects and reveals normally, and the wipe looks identical because the
 * children are what carries the picture. Verified with the observer itself:
 * clipped 0x0 / not intersecting, unclipped 993x473 / ratio 0.67.
 */
.js [data-reveal="mask"],
.js [data-reveal="mask-left"] {
    opacity: 1;
}

.js [data-reveal="mask"] > *,
.js [data-reveal="mask-left"] > * {
    transition: clip-path var(--reveal-duration) var(--reveal-easing) var(--reveal-delay, 0ms);
}

.js [data-reveal="mask"] > *      { clip-path: inset(0 0 100% 0); }
.js [data-reveal="mask-left"] > * { clip-path: inset(0 100% 0 0); }

.js [data-reveal="mask"].is-revealed > *,
.js [data-reveal="mask-left"].is-revealed > * {
    clip-path: inset(0 0 0 0);
}

.js [data-reveal].is-revealed {
    opacity: 1;
    transform: none;
    clip-path: inset(0 0 0 0);
}

/* Cleared by the script once the transition finishes. */
.js [data-reveal].is-reveal-done { will-change: auto; }

/* --------------------------------------------------------------------------
   3. Text utilities
   -------------------------------------------------------------------------- */

.u-text-center  { text-align: center; }
.u-text-left    { text-align: left; }
.u-text-right   { text-align: right; }
.u-text-balance { text-wrap: balance; }

.u-text-muted   { color: var(--color-text-muted); }
.u-text-brand   { color: var(--color-brand); }
.u-text-strong  { color: var(--color-text-strong); }

.u-lead {
    font-size: var(--text-lg);
    line-height: var(--leading-normal);
    color: var(--color-text-muted);
}

.u-measure        { max-width: var(--measure); }
.u-measure-narrow { max-width: var(--measure-narrow); }
.u-measure-wide   { max-width: var(--measure-wide); }

.u-uppercase {
    text-transform: uppercase;
    letter-spacing: var(--tracking-widest);
}

/* --------------------------------------------------------------------------
   4. Spacing utilities — use sparingly; prefer .l-flow
   -------------------------------------------------------------------------- */

.u-mt-0  { margin-block-start: 0; }
.u-mt-sm { margin-block-start: var(--space-sm); }
.u-mt-md { margin-block-start: var(--space-md); }
.u-mt-lg { margin-block-start: var(--space-lg); }
.u-mt-xl { margin-block-start: var(--space-xl); }

.u-mb-0  { margin-block-end: 0; }
.u-mb-sm { margin-block-end: var(--space-sm); }
.u-mb-md { margin-block-end: var(--space-md); }
.u-mb-lg { margin-block-end: var(--space-lg); }
.u-mb-xl { margin-block-end: var(--space-xl); }

.u-mx-auto { margin-inline: auto; }

/* --------------------------------------------------------------------------
   5. Display & visibility
   -------------------------------------------------------------------------- */

.u-block        { display: block; }
.u-inline-block { display: inline-block; }
.u-flex         { display: flex; }
.u-hidden       { display: none; }

@media (max-width: 47.99em) {
    .u-hide-mobile { display: none !important; }
}

@media (min-width: 48em) {
    .u-show-mobile { display: none !important; }
}

@media (max-width: 61.99em) {
    .u-hide-tablet-down { display: none !important; }
}

/* Hide only from assistive tech (decorative elements) */
.u-aria-hidden { pointer-events: none; }

/* --------------------------------------------------------------------------
   6. Misc
   -------------------------------------------------------------------------- */

.u-relative { position: relative; }
.u-full     { width: 100%; }
.u-no-scroll { overflow: hidden; }

.u-divider {
    border: 0;
    border-top: var(--border-hairline);
    margin-block: var(--space-xl);
}
