/* HOME·TRY (104) — "Try together": age-scoped technique carousel.
 *
 * SINGLE SOURCE for the .twg-* prefix (card-dev mirror, check 16) — imported by BOTH
 * web/index.html and workbench/home/try-together.html.
 *
 * ─────────────────────────────────────────────────────────────────────────────
 * ⚠️ WHY THIS CARD IS NOT JUST A CAROUSEL.
 *
 * Two rules land here that land nowhere else on home:
 *
 * 1. IT IS A **PUSH** SURFACE (D-490). Nothing here was asked for. So age-scope and
 *    scope apply HARD: a technique outside the baby's band is not shown, full stop.
 *    (Search is where a parent may still find it — we never refuse a typed question.)
 *
 * 2. 🔴 EVERY CARD IS AN **ANIMATION**, AND THAT IS THE DANGEROUS PART.
 *    The corpus tags 264 items `animated`, 10 of them GATE-CRITICAL. A parent WATCHES
 *    the video and SKIPS THE CAPTION — the tagging note says it plainly: "the anim must
 *    show the gate, video beats text."
 *
 *    So a "Try together" card that autoplays SWADDLING to a parent whose baby has
 *    started trying to roll is not a UX bug. A swaddled baby who rolls onto her front
 *    cannot free her arms.
 *
 *    ∴ A HARD-GATE technique whose gate has fired IS NEVER PUSHED HERE. It does not
 *    appear with a warning. IT DOES NOT APPEAR. The warning is for the parent who went
 *    looking; the silence is for the parent who didn't.
 * ─────────────────────────────────────────────────────────────────────────────
 */

/* ── THE CAROUSEL IS A DRAGGED STRIP, NOT A SCROLLER (D-513 · D-458 one-at-a-time) ──
 * It used to be `overflow-x: auto` + `scroll-snap-type: x mandatory`. That looked correct
 * and was not: **mandatory snap chooses the nearest snap point AFTER MOMENTUM HAS RUN.**
 * A gentle swipe advanced one card; a hard flick sailed through two or three and landed
 * wherever the fling ran out. The parent asked to see the next technique and was shown the
 * fourth — and on a PUSH surface of animations, "wherever the fling ran out" is not a
 * navigation model.
 *
 * A transform strip has no momentum to argue with: one gesture moves exactly one card, or
 * springs back. `touch-action: pan-y` keeps the page itself scrollable under the thumb —
 * we take the horizontal axis and leave the vertical one alone, because a parent holding a
 * baby one-handed must never find the page stuck. */
.twg-slider { overflow: hidden; }
.twg-track { display: flex; touch-action: pan-y; transition: transform var(--duration-300) var(--ease-in-out); }

/* ⚠️ `will-change` ONLY WHILE THE THUMB IS DOWN — never at rest.
 * Declaring it permanently promotes the strip to its own GPU layer for the entire life of
 * the page, and the visual baseline caught what that costs: the poster gets RE-RASTERISED
 * on the compositor with different filtering, so 15,000 pixels of the photograph changed
 * without a single pixel of LAYOUT moving. A hint meant to make one gesture smooth was
 * quietly re-sampling the artwork on every screen, forever.
 * Promote on `mousedown`, drop it on release. That is what the hint is for. */
.twg-track.twg-drag { transition: none; will-change: transform; }

.twg-card { flex: 0 0 100%; padding: 0 var(--rhythm-inset); cursor: pointer; }
.twg-poster { position: relative; aspect-ratio: 16/10; border-radius: var(--radius-12); overflow: hidden; background: var(--surface-sunken); }
.twg-poster img { width: 100%; height: 100%; object-fit: cover; display: block; }
.twg-mark { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: var(--dim-44); height: var(--dim-44); border-radius: var(--radius-round); background: var(--overlay-scrim); color: var(--text-on-dark); display: flex; align-items: center; justify-content: center; }
/* ⚠️ --nudge-2, NOT --space-4 (D-511). The play triangle is mathematically centred and
 * LOOKS 2px left, because its visual mass sits left of its bounding box. This 2px is not
 * a GAP — it compensates for a SHAPE, so the grid does not govern it. Snapping it to 4px
 * makes the button look worse, which is the whole reason the nudge scale exists: a
 * STANDARD exception, with its own name, so it can't be used as a loophole for spacing. */
.twg-mark svg { width: var(--size-18); height: var(--size-18); display: block; margin-left: var(--nudge-2); }
.twg-dur { position: absolute; bottom: var(--space-8); right: var(--space-8); font-family: var(--font-label); font-size: var(--size-10); font-weight: var(--weight-600); color: var(--text-on-dark); background: var(--overlay-scrim); border-radius: var(--radius-pill); padding: var(--space-4) var(--space-8); }

/* 🔴 NO ARTWORK ⇒ NO PICTURE (D-516). The frame and the play mark, and nothing else.
 * The old fallback silently substituted an unrelated illustration, so "How to swaddle safely"
 * could be shown illustrated with a baby lying on her FRONT. That is not a missing asset —
 * it is a wrong instruction on a safety-tiered item, in the channel the corpus says parents
 * actually read. This reads as "coming soon", which is true, rather than as a technique,
 * which would be a lie. */
.twg-poster.twg-noart { background: var(--surface-sunken); }
.twg-poster.twg-noart .twg-mark { background: var(--cream-500); color: var(--text-tertiary); }

.twg-body { padding: var(--rhythm-body) 0 0; }
.twg-kind { display: block; font-family: var(--font-label); font-size: var(--size-10); font-weight: var(--weight-700); letter-spacing: var(--tracking-05); text-transform: uppercase; color: var(--kind-watch-icon); margin-bottom: var(--space-4); }
/* 🔴 RESERVE TWO LINES. (D-547)
 * With no reserve, a one-line title made a 245px card and a two-line title a 267px one — and a
 * carousel stretches to its tallest card, so ONE long title made every card in the rail taller and
 * shifted the page under a thumb already reaching for something. Nobody saw it because every
 * technique title we happen to have is short. */
.twg-name { min-height: calc(2 * var(--leading-130, var(--leading-140)) * var(--size-16)); display: block; font-family: var(--font-display); font-size: var(--size-16); font-weight: var(--weight-600); color: var(--text-primary); line-height: var(--leading-130, var(--leading-140)); }

/* ⚠️ THE SAFETY NOTE — for a BOUNDED technique (D-500), not a HARD-GATE one.
 * A HARD-GATE technique whose gate has fired is NOT SHOWN AT ALL, so it never reaches
 * this style. This is for the boundary that must be respected but does not warrant
 * withholding the card — e.g. "stop when she shows signs of rolling", shown BEFORE she
 * does. It sits ON the poster, not under it: a caption below the video is a caption the
 * parent has already scrolled past. */
.twg-gate { position: absolute; left: 0; right: 0; bottom: 0; display: flex; gap: var(--space-8); align-items: flex-start; padding: var(--space-8) var(--space-12); background: var(--overlay-scrim); }
/* margin-top is optical too — nudging a 14px glyph onto the cap-height of the text beside it. */
.twg-gate svg { flex: none; width: var(--size-14); height: var(--size-14); color: var(--text-on-dark); margin-top: var(--nudge-2); }
.twg-gate span { font-family: var(--font-label); font-size: var(--size-11); font-weight: var(--weight-600); color: var(--text-on-dark); line-height: var(--leading-140); }

.twg-dots { display: flex; justify-content: center; gap: var(--space-8); padding: var(--rhythm-foot) 0 0; }
.twg-dots[hidden] { display: none; }
.twg-dot { width: var(--dim-6); height: var(--dim-6); border-radius: var(--radius-round); background: var(--cream-500); border: 0; padding: 0; cursor: pointer; transition: width var(--duration-200) var(--ease-in-out), background var(--duration-200) var(--ease-in-out), border-radius var(--duration-200) var(--ease-in-out); }
.twg-dot.twg-on { width: var(--dim-16); border-radius: var(--radius-pill); background: var(--accent); }


/* ── LOADING SKELETON (D-516) ──────────────────────────────────────────────────
 * ⚠️ THE POINT IS NOT POLISH — IT IS NOT LYING FOR A BEAT.
 * The list is resolved from fetched content, so without this the module renders the EMPTY
 * state ("nothing new to try together this week") while the data is still in flight. To a
 * parent for whom there IS plenty this week, that is a false statement about their baby. It
 * happens to be brief. It is still false.
 *
 * No shimmer animation: a pulsing gradient on a home screen a parent opens at 3am, one-handed,
 * is a moving thing competing for attention with nothing to say. Still, calm, and gone. */
.twg-sk-box { background: var(--surface-sunken); }
.twg-sk-line { display: block; border-radius: var(--radius-4); background: var(--surface-sunken); }
.twg-sk-kind { width: 30%; height: var(--size-10); margin-bottom: var(--space-8); }
.twg-sk-name { width: 72%; height: var(--size-16); }
.twg-sk { pointer-events: none; }

/* 🔴 THERE IS NO .twg-empty (D-517). "Empty can't happen — one per week, hard rule" (Andrew).
 * The old empty state told a parent "nothing new to try together this week." That sentence is
 * now UNSAYABLE by construction: the invariant is enforced by a build-time test across all 52
 * weeks × every feeding mode × the rolling gate. If it is ever violated anyway, the renderer
 * returns null and the SHELL DROPS THE WHOLE MODULE — a missing card is honest; a heading with
 * nothing under it is not. */

/* ── PRESS + FOCUS (D-422 floor) ───────────────────────────────────────────────
 * The card is tappable and the dots are buttons, so both must SAY SO. A parent holding
 * a baby one-handed, thumbing at a screen in the dark, gets no other confirmation that
 * the tap landed.
 * :focus-visible (not :focus) so a mouse click doesn't paint a ring nobody asked for —
 * but a keyboard or switch user always sees where they are. */
.twg-card:active .twg-poster { opacity: 0.86; transition: opacity var(--duration-100) var(--ease-standard); }
.twg-card:focus-visible { outline: var(--focus-ring); outline-offset: var(--focus-offset); border-radius: var(--radius-12); }
.twg-dot:active { opacity: 0.7; }
.twg-dot:focus-visible { outline: var(--focus-ring); outline-offset: var(--focus-offset); }
