/* ============================================================
   features/tabs/tabs.css — process tabs (redesign · P2 s3 reskin)
   ------------------------------------------------------------
   Reskin only: the JS contract (.process-tab[data-tab],
   .process-tab-pane[data-pane], .active) is unchanged. tabs.js
   adds the ARIA tablist/tab/tabpanel roles + roving tabindex at
   runtime, so the markup stays as-is.

   Soft-dreamy language: tinted squircle pills instead of chunky
   white cards; the active pill fills with the coral gradient + glow
   and is marked by the brand dot ("you are here"); the panel sits on
   a warm gradient wash. Layout consumes tokens.
   ============================================================ */

.process-tabs {
    max-width: var(--container-narrow);
    margin: 0 auto;
}

.process-tabs.production {
    max-width: 100%;
    display: flex;
    gap: var(--space-7);
}

.process-tabs-nav {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: var(--space-3);
    margin-bottom: var(--space-8);
}

.process-tabs-nav.production {
    grid-template-columns: repeat(1, 1fr);
    gap: var(--space-3);
    margin-bottom: 0;
    display: flex;
    flex-direction: column;
    width: 22%;
}

.process-tab {
    position: relative;
    background: var(--surface-tint);
    border: 1.5px solid transparent;
    padding: var(--space-4) var(--space-5);
    border-radius: var(--radius-lg);
    font-family: var(--font-body);
    font-size: clamp(17px, 1.6vw, 20px);
    font-weight: 700;
    letter-spacing: var(--tracking-tight);
    cursor: pointer;
    text-align: center;
    width: 100%;
    color: var(--text-soft);
    transition: color var(--dur-base) var(--ease-dreamy),
        border-color var(--dur-base) var(--ease-dreamy),
        background var(--dur-base) var(--ease-dreamy),
        box-shadow var(--dur-base) var(--ease-dreamy),
        transform var(--dur-base) var(--ease-dreamy);
}

.process-tab:hover {
    border-color: var(--accent);
    background: var(--coral-100);
    color: var(--text);
    transform: translateY(-3px);
    box-shadow: var(--shadow-sm);
}

.process-tab:focus-visible {
    outline: 2px solid var(--focus-ring);
    outline-offset: 2px;
}

.process-tab.active {
    background: var(--grad-coral);
    color: var(--text-on-coral);
    border-color: transparent;
    box-shadow: var(--shadow-glow);
}

.process-tab.active:hover {
    color: var(--text-on-coral);
    transform: translateY(-3px);
}

/* The dot blooms on hover and marks the active step, where it gently
   pulses — the brand's signature "dot bloom" interaction. Its space is
   reserved on every tab so blooming never reflows the label. */
.process-tab::before {
    content: "";
    display: inline-block;
    width: 0.5em;
    height: 0.5em;
    border-radius: 50%;
    background: var(--accent);
    margin-right: 0.55em;
    vertical-align: 0.1em;
    transform: scale(0);
    transition: transform var(--dur-base) var(--ease-dreamy),
        background var(--dur-base) var(--ease-dreamy);
}

.process-tab:hover::before {
    transform: scale(1);
}

.process-tab.active::before {
    background: currentColor;
    /* white on the coral fill */
    transform: scale(1);
    animation: ddTabDotPulse 2.2s var(--ease-soft) infinite;
}

@keyframes ddTabDotPulse {

    0%,
    100% {
        transform: scale(1);
    }

    50% {
        transform: scale(1.3);
    }
}

/* ============================================
   AUTO-CYCLE (#105) — opt-in via [data-dd-autocycle]
   --------------------------------------------
   A splotch of ink is dropped in at the left of the active pill and drifts
   across it; where it leaves, the next pill takes over. tabs.js advances on
   that drift's `animationend`, so the animation isn't a decoration running
   alongside a timer — it IS the timer, and pausing it pauses the cycle.

   The ink is the whole effect. An earlier pass also washed the swept portion
   of the pill, but a wash has to end somewhere, and its boundary travelling
   across read as a vertical line racing the ink. Better to show nothing than
   an edge.
   ============================================ */

/* The ink echoes the aura scene's coral-ink-in-water — inverted here, light
   ink in coral water. Four offset lobes rather than one disc, because a
   perfect circle reads as an object travelling over the pill; an uneven mass
   that also turns and swells as it goes reads as something diffusing through
   it. Every stop ends transparent and the whole thing is blurred on top, so
   it has no edge anywhere. */
.process-tab::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 0;
    width: 3.4em;
    height: 3.4em;
    margin: -1.7em 0 0 -1.7em;
    pointer-events: none;
    opacity: 0;
    background:
        radial-gradient(circle 1.15em at 44% 47%, rgba(255, 255, 255, 0.28), rgba(255, 255, 255, 0) 100%),
        radial-gradient(circle 0.95em at 63% 57%, rgba(255, 255, 255, 0.21), rgba(255, 255, 255, 0) 100%),
        radial-gradient(circle 0.75em at 51% 33%, rgba(255, 255, 255, 0.17), rgba(255, 255, 255, 0) 100%),
        radial-gradient(circle 0.85em at 34% 62%, rgba(255, 255, 255, 0.14), rgba(255, 255, 255, 0) 100%);
    filter: blur(6px);
}

/* Two animations on one element: the drift carries it across at a constant
   rate (it is the progress read, so it must not ease), while the bloom
   swells and turns it independently. */
.process-tabs.is-cycling .process-tab.active::after {
    animation:
        ddTabInkDrift var(--dd-cycle-dur, 8000ms) linear forwards,
        ddTabInkBloom var(--dd-cycle-dur, 8000ms) var(--ease-soft) forwards;
}

/* Stays clear of the pill's ends, which is what lets the whole effect run
   unclipped. Cropping it to the pill was the obvious way to let it enter and
   leave, but `overflow: hidden` clips to the PADDING box and the pill carries
   a 1.5px transparent border — so the coral painted under that border stayed
   un-inked and read as a pink outline tracing the pill. Nothing to clip,
   nothing to fringe. */
@keyframes ddTabInkDrift {
    from {
        left: 1.2em;
    }

    to {
        left: calc(100% - 1.2em);
    }
}

/* Dropped in, opening out as it crosses, dissolved by the time it lands —
   so it materialises and disperses rather than sliding in past an edge. */
@keyframes ddTabInkBloom {
    0% {
        opacity: 0;
        transform: scale(0.55) rotate(0deg);
    }

    18% {
        opacity: 1;
    }

    78% {
        opacity: 0.85;
    }

    100% {
        opacity: 0;
        transform: scale(1.35) rotate(24deg);
    }
}

/* Hover, focus, off-screen or a hidden tab: hold the ink exactly where it is.
   It resumes from there rather than restarting, so leaving and coming back
   doesn't cost the reader the pane they were halfway through. */
.process-tabs.is-cycling.is-paused .process-tab.active::after {
    animation-play-state: paused;
}

/* "Up next" — the dot half-blooms on the pill the sweep is heading for. */
.process-tabs.is-cycling .process-tab.is-next::before {
    transform: scale(0.5);
    opacity: 0.5;
}

.process-tabs.is-cycling .process-tab.is-next:hover::before {
    transform: scale(1);
    opacity: 1;
}

.process-tabs-content {
    position: relative;
    overflow: hidden;
    /* Stack every pane in one grid cell so the panel is always as tall as the
       LARGEST tab — its size no longer jumps when switching tabs. */
    display: grid;
    /* white base (not the warm grad-soft) so the drifting coral/peach
       mesh reads with real contrast instead of pink-on-pink */
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    padding: clamp(var(--space-6), 5vw, var(--space-10));
    box-shadow: var(--shadow-md);
    transition: border-color var(--dur-base) var(--ease-dreamy),
        box-shadow var(--dur-base) var(--ease-dreamy);
}

/* A soft coral/peach glow mesh drifting slowly behind the body — the
   design-language "mesh of glow-coral + glow-peach blobs". Oversized so
   the drift never reveals an edge; clipped by the panel's overflow. */
.process-tabs-content::before {
    content: "";
    position: absolute;
    inset: -30%;
    z-index: 0;
    pointer-events: none;
    background:
        radial-gradient(38% 50% at 22% 28%, rgba(255, 170, 168, 0.28), transparent 72%),
        radial-gradient(42% 55% at 80% 72%, rgba(255, 217, 194, 0.30), transparent 75%),
        radial-gradient(32% 42% at 62% 20%, rgba(255, 139, 136, 0.16), transparent 70%);
    animation: ddTabsMesh 24s var(--ease-soft) infinite;
}

@keyframes ddTabsMesh {
    0% {
        transform: translate3d(-3%, -2%, 0) scale(1.05);
    }

    50% {
        transform: translate3d(3%, 2%, 0) scale(1.12);
    }

    100% {
        transform: translate3d(-3%, -2%, 0) scale(1.05);
    }
}

.process-tabs-content:hover {
    border-color: var(--coral-200);
    box-shadow: var(--shadow-lg);
}

.process-tabs-content.production {
    width: 78%;
}

.process-tab-pane {
    /* All panes share one cell (stacked); only the active one is shown. Using
       visibility (not display:none) keeps every pane measured so the panel
       holds the tallest pane's height — no resize on tab switch. */
    grid-area: 1 / 1;
    z-index: 1;
    visibility: hidden;
    opacity: 0;
    transform: translateY(16px);
    pointer-events: none;
    transition: opacity var(--dur-base) var(--ease-dreamy),
        transform var(--dur-base) var(--ease-dreamy),
        visibility var(--dur-base) var(--ease-dreamy);
}

.process-tab-pane.active {
    visibility: visible;
    opacity: 1;
    transform: translateY(0);
    pointer-events: auto;
}

/* One size for the whole pane. An earlier pass gave the opening line its own
   larger scale, which just read as a stray heading — the copy carries the
   confidence, so the type only has to stop being timid: a notch up from
   --fs-body and a step darker than muted, applied evenly. */
.process-tab-pane p {
    font-size: clamp(17px, 1.15vw, 19px);
    line-height: var(--lh-body);
    color: var(--text-soft);
    margin-bottom: var(--space-4);
}

.process-tab-pane p:last-child {
    margin-bottom: 0;
}

/* Every pane shares one grid cell, so the panel is as tall as the LONGEST of
   them — which left a short pane's footnote stranded mid-air with dead space
   under it. Making the pane a flex column lets the footnote take `margin-top:
   auto` and sit on the floor of the panel instead.

   Scoped with :has() to panes that actually carry a footnote, so the pricing
   panes — which borrow this class for the calculator's cards — keep block
   layout. Where :has() is unsupported the footnote simply isn't pinned. */
.process-tab-pane:has(.process-tab-note) {
    display: flex;
    flex-direction: column;
}

/* Footnote — the asterisked caveat at the foot of a pane. Divided off by a
   hairline and set smaller and quieter than the body, so it reads as an aside
   rather than another point. The asterisk hangs into the margin, which keeps
   wrapped lines aligned under the sentence instead of under the marker.
   Needs the element in the selector to outweigh `.process-tab-pane p`. */
.process-tab-pane p.process-tab-note {
    /* Pinned to the foot; collapses to 0 in the tallest pane, where the
       preceding paragraph's own 16px still keeps the rule off the text. */
    margin-top: auto;
    padding-top: var(--space-4);
    border-top: 1px solid var(--border);
    padding-left: 1em;
    text-indent: -1em;
    font-size: var(--fs-small);
    line-height: var(--lh-snug);
    color: var(--text-muted);
}

.process-tab-pane em {
    color: var(--accent-strong);
    font-style: normal;
    font-weight: 600;
}

.tab-link {
    color: var(--link);
    font-weight: 600;
    cursor: pointer;
    text-decoration: underline;
    text-underline-offset: 3px;
    text-decoration-thickness: 1.5px;
    transition: color var(--dur-fast) var(--ease-soft);
}

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

/* The last item only carries its own 12px, which left a list sitting tighter
   to the line under it than two paragraphs sit to each other (16px). This
   gives the block a little room to close on. */
.process-tab-pane ul,
.process-tab-pane ol {
    margin-left: 2.5em;
    margin-bottom: var(--space-3);
    color: var(--text-muted);
}

.process-tab-pane li {
    font-size: clamp(17px, 1.15vw, 19px);
    margin-bottom: var(--space-3);
    line-height: var(--lh-snug);
}

/* ============================================
   RESPONSIVE
   ============================================ */

@media (max-width: 1264px) {
    .process-tabs-nav {
        grid-template-columns: repeat(2, 1fr);
    }
}

@media (max-width: 1024px) {
    .process-tabs-nav {
        grid-template-columns: repeat(2, 1fr);
    }
}

@media (max-width: 767px) {
    .process-tabs-content {
        padding: var(--space-6) var(--space-5);
    }
}

/* Reduced motion: keep state changes instant, drop the lift + rise. */
@media (prefers-reduced-motion: reduce) {

    .process-tab,
    .process-tabs-content,
    .process-tab-pane,
    .process-tab::before {
        transition: none;
    }

    .process-tab:hover,
    .process-tab.active:hover {
        transform: none;
    }

    .process-tab-pane {
        transform: none;
    }

    .process-tab.active::before,
    .process-tabs-content::before {
        animation: none;
    }

    /* tabs.js already declines to arm the cycle under reduced motion; this
       makes the drift impossible rather than merely unrequested. */
    .process-tabs.is-cycling .process-tab.active::after {
        animation: none;
        opacity: 0;
    }
}
