/* ============================================================
   Studio — "The Method" (evolves .eng), "The Ratchet" (evolves
   .opt), "What We Refuse" (new .refuse-)
   Steward: S9 Engineering   Page: about.html
   Sprint 4 signature experience + two quiet supporting experiences.
   Additive, deletable unit. Loaded after style.css/shell.css —
   extends the existing .eng-/.opt- base chrome (fragment field,
   core/ring/orb, bar rows) defined there rather than duplicating
   it; only new interaction/state rules live here, per the Sprint 4
   spec's "evolve in place" directive.

   Motion: ratified grammar, cubic-bezier(0.22, 1, 0.36, 1) as the
   default easing, GPU-only (transform/opacity). The Method's own
   per-movement durations are deliberately NON-uniform (handcrafted
   pacing, not a metronome) — see inline comments per movement.
   Nothing in The Method moves until the visitor applies a step.
   ============================================================ */

/* The site-wide fixed .mobile-sticky-cta would otherwise sit on
   top of The Method's own "Apply" control on mobile, since the
   card is tall and the control lives near its bottom edge.
   studio.js hides it (via .studio-hide-sticky on <body>) while
   #eng is in view, same pattern as Home's hero fix in Sprint 3. */
.studio-hide-sticky .mobile-sticky-cta {
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.25s ease;
}

.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* --- Hero soft cue (replaces the old dual hero CTAs) --- */
.studio-soft-cue {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 0.85rem;
    font-weight: 500;
    color: var(--text-secondary);
    text-decoration: none;
    transition: color 0.2s ease, gap 0.2s ease;
}

.studio-soft-cue:hover,
.studio-soft-cue:focus-visible {
    color: var(--text-primary);
    gap: 9px;
}

.studio-soft-cue i {
    width: 15px;
    height: 15px;
}

/* --- Framing passage --- */
.studio-frame {
    max-width: 620px;
    margin: 0 auto;
    text-align: center;
}

.studio-frame p {
    font-size: 1.02rem;
    line-height: 1.7;
    color: var(--text-secondary);
    margin-bottom: 10px;
}

.studio-frame p:last-child {
    margin-bottom: 0;
    color: var(--text-primary);
    font-weight: 500;
}

/* ============================================================
   THE METHOD (evolves #eng)
   ============================================================ */

/* Idle state: fragments hidden until movement 1 is applied.
   (style.css never defines an initial opacity for .eng-frag, so
   this is additive, not an override of prior behaviour.) */
.eng-frag {
    opacity: 0;
    transform: translate(-50%, -50%) translate(var(--x), var(--y)) rotate(var(--r)) scale(0.75);
}

/* Movement 1 — Map it honestly. Reveal is deliberately the
   slowest, most unhurried movement (there's a lot to see, and
   honesty takes time): per-fragment transition-delay is set by
   studio.js from a hand-authored, non-uniform array — never a
   linear stagger. Total reveal ≈ 2.1s. */
.eng.mv-1 .eng-frag,
.eng.mv-2 .eng-frag,
.eng.mv-3 .eng-frag,
.eng.mv-4 .eng-frag,
.eng.mv-5 .eng-frag {
    opacity: 1;
    transform: translate(-50%, -50%) translate(var(--x), var(--y)) rotate(var(--r)) scale(1);
    transition: opacity 0.6s cubic-bezier(0.22, 1, 0.36, 1),
                transform 0.6s cubic-bezier(0.22, 1, 0.36, 1);
}

/* Movement 2 — Remove what shouldn't exist. The five .is-cut
   fragments strike through fast and decisive (a confident
   engineer doesn't hesitate on an obvious deletion): a brief
   held strike (~200ms), then a fast vanish (~300ms). Total ≈
   0.5s — deliberately the FASTEST movement in the sequence. */
.eng-frag.is-cut {
    transition: opacity 0.6s cubic-bezier(0.22, 1, 0.36, 1),
                transform 0.6s cubic-bezier(0.22, 1, 0.36, 1),
                text-decoration-color 0.15s ease;
    text-decoration: line-through;
    text-decoration-color: transparent;
}

.eng.mv-2 .eng-frag.is-cut {
    text-decoration-color: var(--danger);
}

.eng.mv-2 .eng-frag.is-cut.is-gone,
.eng.mv-3 .eng-frag.is-cut,
.eng.mv-4 .eng-frag.is-cut,
.eng.mv-5 .eng-frag.is-cut {
    opacity: 0;
    transform: translate(-50%, -50%) translate(var(--x), var(--y)) scale(0.4);
    transition: opacity 0.3s ease, transform 0.3s ease;
}

/* Movement 3 — Make one source of truth. The surviving 13
   fragments travel to the core and dissolve into it. This is
   the most DELIBERATE movement — unifying scattered things
   shouldn't feel instant. Duration set specifically longer than
   the base transition (≈ 1.9s), with a light per-fragment stagger
   authored by studio.js so a few arrive slightly ahead of others. */
.eng.mv-3 .eng-frag:not(.is-cut),
.eng.mv-4 .eng-frag:not(.is-cut),
.eng.mv-5 .eng-frag:not(.is-cut) {
    opacity: 0;
    transform: translate(-50%, -50%) scale(0.28);
    transition: opacity 1.9s cubic-bezier(0.22, 1, 0.36, 1),
                transform 1.9s cubic-bezier(0.22, 1, 0.36, 1);
}

.eng.mv-3 .eng-core,
.eng.mv-4 .eng-core,
.eng.mv-5 .eng-core {
    opacity: 1;
    transform: translate(-50%, -50%) scale(1);
}

/* Movement 4 — Give the boring work to the machine. A short task
   list appears near the core; each line ticks off with an
   organic (non-uniform) stagger set inline by studio.js. Medium
   pace — snappier than Unify, calmer than Remove. */
.eng-tasks {
    position: absolute;
    left: 50%;
    bottom: 6%;
    transform: translateX(-50%);
    display: flex;
    flex-direction: column;
    gap: 5px;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.4s ease;
}

.eng.mv-4 .eng-tasks,
.eng.mv-5 .eng-tasks {
    opacity: 1;
}

.eng-task {
    font-size: 0.68rem;
    color: var(--text-muted);
    white-space: nowrap;
    display: flex;
    align-items: center;
    gap: 7px;
    transition: color 0.35s ease, opacity 0.35s ease;
}

.eng-task::before {
    content: "";
    width: 11px;
    height: 11px;
    border-radius: 4px;
    border: 1.5px solid var(--border);
    flex-shrink: 0;
    transition: background-color 0.3s ease, border-color 0.3s ease;
}

.eng-task.is-done {
    color: var(--text-muted);
    text-decoration: line-through;
    opacity: 0.6;
}

.eng-task.is-done::before {
    background: var(--success);
    border-color: var(--success);
}

/* Movement 5 — Make it think. The loop lights Detect -> Understand
   -> Decide -> Execute with DELIBERATELY uneven pauses between
   stages, timed entirely in studio.js (not CSS) — including one
   held silent beat before "Understand" lights, the moment meant
   to read as genuine thought, not a slideshow tick. */
.eng-loop {
    display: flex;
    gap: 8px;
    margin-top: 10px;
    opacity: 0;
    transition: opacity 0.4s ease;
}

.eng.mv-5 .eng-loop {
    opacity: 1;
}

.eng-loop-stage {
    font: 600 0.6rem/1 ui-monospace, SFMono-Regular, Menlo, monospace;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--text-muted);
    padding: 4px 8px;
    border: 1px solid var(--border-hairline);
    border-radius: 100px;
    transition: color 0.3s ease, border-color 0.3s ease, background-color 0.3s ease;
}

.eng-loop-stage.is-lit {
    color: var(--accent-text);
    border-color: var(--accent);
    background: var(--accent-soft);
}

/* Final resolved state (end of movement 5): reuse the ratified
   .eng-ring breathe animation already defined in style.css for
   the old "s-os" end-state, now triggered by mv-5 + is-live */
.eng.mv-5.is-live .eng-ring {
    animation: eng-breathe 3.2s ease-in-out infinite;
    border-color: rgba(16, 185, 129, 0.4);
    box-shadow: 0 0 0 4px rgba(16, 185, 129, 0.12);
}

.eng.mv-5.is-live .eng-orb {
    opacity: 1;
}

/* --- Control: the visitor advances one movement at a time.
   Nothing here animates ambiently — it is deliberately still
   between applications. No countdown, no pulsing hint. --- */
.eng-control {
    margin-top: 18px;
    padding-top: 16px;
    border-top: 1px solid var(--border-hairline);
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    flex-wrap: wrap;
}

.eng-principle {
    margin: 0;
    max-width: 460px;
}

.eng-principle-n {
    font: 700 0.6rem/1 ui-monospace, SFMono-Regular, Menlo, monospace;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--accent-text);
}

.eng-principle-n b {
    font-feature-settings: "tnum";
}

.eng-principle-t {
    display: block;
    margin-top: 3px;
    font-size: 0.84rem;
    color: var(--text-secondary);
    line-height: 1.5;
    min-height: 3em;
}

.eng-apply {
    -webkit-appearance: none;
    appearance: none;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    gap: 8px;
    background: var(--text-primary);
    color: var(--bg-page);
    border: none;
    border-radius: 100px;
    padding: 10px 18px;
    font-size: 0.82rem;
    font-weight: 600;
    white-space: nowrap;
    flex-shrink: 0;
    transition: opacity 0.2s ease, transform 0.2s ease;
}

.eng-apply [data-eng-apply-txt] {
    display: inline-block;
    transition: opacity 0.14s ease;
}

.eng-apply [data-eng-apply-txt].is-swapping {
    opacity: 0;
}

.eng-apply:hover {
    opacity: 0.88;
}

.eng-apply:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 3px;
}

.eng-apply:active {
    transform: scale(0.97);
}

.eng-apply[disabled] {
    opacity: 0.4;
    cursor: default;
}

/* Reduced motion: the resolved architecture, statically. No
   transitions anywhere in the experience; the sr-only method list
   (in the HTML, always present) carries the five movements and
   their principles regardless of motion preference. */
@media (prefers-reduced-motion: reduce) {
    .eng-frag,
    .eng-frag.is-cut,
    .eng-core,
    .eng-tasks,
    .eng-task,
    .eng-loop,
    .eng-loop-stage,
    .eng-ring {
        transition: none !important;
        animation: none !important;
    }
}

@media (max-width: 640px) {
    .eng-control {
        flex-direction: column;
        align-items: stretch;
    }
    .eng-apply {
        justify-content: center;
    }
}

/* ============================================================
   THE RATCHET (evolves #opt) — quiet supporting experience
   ============================================================ */

.studio-support-head {
    max-width: 560px;
    margin: 0 auto 20px;
    text-align: center;
}

.studio-support-head .section-desc {
    margin-top: 4px;
}

/* ============================================================
   WHAT WE REFUSE (new .refuse-) — quiet supporting experience,
   deliberately static: no JS, no motion beyond the sitewide
   reveal-on-scroll fade already used for calm sections.
   ============================================================ */

.refuse-list {
    list-style: none;
    margin: 0 auto;
    padding: 0;
    max-width: 620px;
    display: flex;
    flex-direction: column;
}

.refuse-item {
    padding: 16px 0;
    border-bottom: 1px solid var(--border-hairline);
    display: flex;
    flex-direction: column;
    gap: 3px;
}

.refuse-item:last-child {
    border-bottom: none;
}

.refuse-what {
    font-size: 0.92rem;
    font-weight: 600;
    color: var(--text-primary);
}

.refuse-why {
    font-size: 0.82rem;
    color: var(--text-muted);
    line-height: 1.6;
}

/* --- Final CTA --- */
.studio-cta {
    max-width: 560px;
    margin: 0 auto;
    text-align: center;
}
