/* ================================================================
   "Tanz 67" — the dancing-president Easter egg (US-013)
   ================================================================
   Markup: templates/fragments/tanz67.html. Behaviour: static/js/tanz67.js.

   Rules this file keeps, each for a reason:

   - EVERY animation sits inside @media (prefers-reduced-motion:
     no-preference). The unanimated markup is a complete static pose —
     the six-seven held, 6 and 7 both visible — so a user who has asked
     their OS to stop motion still gets the joke, just not the movement.
     Tanz67WiringTest brace-matches the guard and fails the build on any
     animation outside it.
   - Only transform and opacity are animated. They never trigger layout,
     so the dance cannot jank the chat or block the main thread.
   - Nothing flashes. The sunburst turns once every 48 s and no colour
     changes faster than that (WCAG 2.3.1: no more than three flashes a
     second).
   - Colours come from the theme tokens; the few figure colours below are
     sampled from the portrait so the drawn body matches the photo head.
   - No flag backdrop. The Merah-Putih is not a prop for a comedy dance
     (UU 24/2009 on the dignity of the flag); red and white appear as
     festive accents only.
   ================================================================ */

.tanz67 {
    --tanz67-beat:     670ms;           /* ten beats = the 6.7 s run */
    --tanz67-duration: 6700ms;          /* overwritten from tanz67.js */

    --tanz67-suit:       #1b1a1f;       /* portrait jacket, #151318 lifted a touch */
    --tanz67-lapel:      #34323b;
    --tanz67-shirt:      #eeedf0;
    --tanz67-tie:        #962a3b;       /* portrait tie #8e3041 */
    --tanz67-skin:       #c58278;       /* sampled from the cheek */
    --tanz67-skin-shade: #ac7067;       /* sampled from the neck */
    --tanz67-shoe:       #0b0b0d;

    /* A modal <dialog> ships with UA margins, max sizes and a border;
       all of them go, so it covers the viewport edge to edge. */
    position: fixed;
    inset: 0;
    width: 100%;
    height: 100vh;
    height: 100dvh;                     /* mobile toolbars never hide the controls */
    max-width: none;
    max-height: none;
    margin: 0;
    border: 0;
    padding: env(safe-area-inset-top) env(safe-area-inset-right)
             env(safe-area-inset-bottom) env(safe-area-inset-left);
    overflow: hidden;
    color: var(--text-primary);
    background:
        radial-gradient(ellipse at 50% 42%, rgba(255, 255, 255, 0.96) 0 26%, rgba(255, 255, 255, 0) 64%),
        var(--bg-secondary);
}

/* Only when open: an unconditional display would override the UA's
   dialog:not([open]) { display: none } and show the overlay on load. */
.tanz67[open] {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.75rem;
}

.tanz67::backdrop { background: transparent; }   /* the dialog itself is full-bleed */

/* ---- Sunburst: a festive ground that is not the flag ---- */
.tanz67::before {
    content: "";
    position: absolute;
    inset: -50%;                        /* oversized so turning never shows a corner */
    background: repeating-conic-gradient(from 0deg at 50% 50%,
        rgba(31, 111, 191, 0.08) 0deg 9deg, rgba(31, 111, 191, 0) 9deg 18deg);
    pointer-events: none;
}

/* ---- Close control ---- */
.tanz67-close {
    position: absolute;
    top: calc(env(safe-area-inset-top) + 0.75rem);
    right: calc(env(safe-area-inset-right) + 0.75rem);
    width: 44px;                        /* WCAG 2.5.5 target size */
    height: 44px;
    font-size: var(--text-xl);
    background: var(--bg-primary);
    color: var(--text-primary);
    box-shadow: var(--shadow-md);
    z-index: 2;
}

/* ---- Stage ---- */
.tanz67-stage {
    position: relative;
    z-index: 1;
    display: grid;
    place-items: center;
    pointer-events: none;               /* a tap on the dancer dismisses (tanz67.js) */
}

.tanz67-dancer {
    display: block;
    height: min(58vh, 520px);
    height: min(58dvh, 520px);
    width: auto;
    aspect-ratio: 240 / 360;
    max-width: 92vw;
    overflow: visible;                  /* the raised palms swing past the viewBox */
}

/* ---- Figure paint ---- */
.tanz67-shadow     { fill: rgba(24, 20, 14, 0.14); }
.tanz67-suit       { fill: var(--tanz67-suit); }
.tanz67-shirt      { fill: var(--tanz67-shirt); }
.tanz67-lapel      { fill: none; stroke: var(--tanz67-lapel); stroke-width: 2; stroke-linecap: round; }
.tanz67-tie        { fill: var(--tanz67-tie); }
.tanz67-button     { fill: var(--tanz67-lapel); }
.tanz67-pin-red    { fill: var(--merah); }
.tanz67-pin-white  { fill: #ffffff; }
.tanz67-skin       { fill: var(--tanz67-skin); }
.tanz67-skin-shade { fill: var(--tanz67-skin-shade); }
.tanz67-shoe       { fill: var(--tanz67-shoe); }

.tanz67-sleeve {
    fill: none;
    stroke: var(--tanz67-suit);
    stroke-width: 17;
    stroke-linecap: round;
    stroke-linejoin: round;
}
.tanz67-cuff {
    fill: none;
    stroke: var(--tanz67-shirt);
    stroke-width: 14;
}

.tanz67-head-rim {
    fill: none;
    stroke: #ffffff;
    stroke-width: 3;
}

.tanz67-num {
    font-family: var(--font-display);
    font-size: 40px;
    font-weight: 700;
    text-anchor: middle;
    fill: var(--biru-deep);
    stroke: #ffffff;
    stroke-width: 6px;
    stroke-linejoin: round;
    paint-order: stroke;                /* white halo, legible on any ground */
    transform-box: fill-box;
    transform-origin: center;
}

/* ---- Pivots, in viewBox units (transform-box defaults to view-box for
        SVG, the same convention sepeda.css uses for the wheels) ---- */
.tanz67-upper       { transform-origin: 120px 250px; }
.tanz67-head        { transform-origin: 120px 130px; }
.tanz67-arm--left   { transform-origin: 80px 154px; }
.tanz67-arm--right  { transform-origin: 160px 154px; }
.tanz67-leg--left   { transform-origin: 104px 240px; }
.tanz67-leg--right  { transform-origin: 136px 240px; }
.tanz67-shadow      { transform-origin: 120px 344px; }

/* The static pose: left palm up, right palm down — the six-seven, held. */
.tanz67-arm { transform: rotate(12deg); }

/* ---- Caption ---- */
.tanz67-caption {
    position: relative;
    z-index: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.5rem;
    max-width: min(92vw, 30rem);
    padding: 0.85rem 1.4rem 1rem;
    text-align: center;
    background: var(--bg-primary);       /* solid, so text contrast never depends on the sunburst */
    border: 1px solid var(--surface-border);
    border-radius: var(--radius-xl);
    box-shadow: var(--shadow-lg);
}

.tanz67-title {
    font-family: var(--font-display);
    font-size: var(--display-2xl);
    font-weight: 700;
    line-height: 1.1;
    color: var(--biru);                  /* 6.82:1 on white */
}

.tanz67-label {
    font-size: var(--text-sm);
    color: var(--text-secondary);
}

.tanz67-back {
    font-size: var(--text-md);
    padding: 0.65rem 1.2rem;
    min-height: 44px;
}

/* ---- Progress: how long until the chat comes back ---- */
.tanz67-progress {
    display: none;                       /* shown only where it can move */
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 5px;
    background: linear-gradient(90deg, var(--langit), var(--biru-deep));
    transform-origin: left center;
    z-index: 2;
}

/* ---- Confetti ---- */
.tanz67-confetti {
    display: none;                       /* shown only where it can move */
    position: absolute;
    inset: 0;
    overflow: hidden;
    pointer-events: none;
}
.tanz67-confetti i {
    position: absolute;
    top: 0;
    left: var(--x);
    width: 8px;
    height: 14px;
    border-radius: 2px;
    background: var(--c);
    transform: translateY(-10vh);
}
.tanz67-confetti i:nth-child(1)  { --x:  6%; --c: var(--langit);  --d: 3.4s; --delay: -0.2s; }
.tanz67-confetti i:nth-child(2)  { --x: 14%; --c: var(--biru);   --d: 4.1s; --delay: -2.3s; }
.tanz67-confetti i:nth-child(3)  { --x: 23%; --c: var(--langit);  --d: 3.8s; --delay: -1.1s; }
.tanz67-confetti i:nth-child(4)  { --x: 31%; --c: var(--langit-soft);  --d: 4.6s; --delay: -3.0s; }
.tanz67-confetti i:nth-child(5)  { --x: 40%; --c: var(--biru);   --d: 3.2s; --delay: -0.7s; }
.tanz67-confetti i:nth-child(6)  { --x: 49%; --c: var(--langit);  --d: 4.4s; --delay: -2.9s; }
.tanz67-confetti i:nth-child(7)  { --x: 57%; --c: var(--biru);   --d: 3.6s; --delay: -1.6s; }
.tanz67-confetti i:nth-child(8)  { --x: 65%; --c: var(--langit);  --d: 4.9s; --delay: -0.4s; }
.tanz67-confetti i:nth-child(9)  { --x: 73%; --c: var(--langit-soft);  --d: 3.9s; --delay: -2.1s; }
.tanz67-confetti i:nth-child(10) { --x: 81%; --c: var(--langit);  --d: 4.3s; --delay: -3.4s; }
.tanz67-confetti i:nth-child(11) { --x: 88%; --c: var(--biru);   --d: 3.5s; --delay: -1.3s; }
.tanz67-confetti i:nth-child(12) { --x: 95%; --c: var(--langit);  --d: 4.7s; --delay: -2.6s; }

/* ---- Short landscape screens (phones on their side): side by side ---- */
@media (max-height: 520px) and (orientation: landscape) {
    .tanz67[open] { flex-direction: row; gap: 1.5rem; }
    .tanz67-dancer { height: min(80vh, 420px); height: min(80dvh, 420px); }
    .tanz67-title  { font-size: var(--display-lg); }
}

/* ================================================================
   Motion — all of it, and only here
   ================================================================
   One cycle is two beats: beat one the left palm (6) is up, beat two
   the right (7). Every keyframe set starts and ends on the same frame
   and runs on the shared beat, so the loop has no seam. */
@media (prefers-reduced-motion: no-preference) {
    .tanz67.is-playing::before {
        animation: tanz67-turn 48s linear infinite;
    }
    .tanz67.is-playing .tanz67-arm {
        animation: tanz67-seesaw calc(var(--tanz67-beat) * 2) ease-in-out infinite;
    }
    .tanz67.is-playing .tanz67-num--6 {
        animation: tanz67-pop calc(var(--tanz67-beat) * 2) ease-in-out infinite;
    }
    .tanz67.is-playing .tanz67-num--7 {
        animation: tanz67-pop calc(var(--tanz67-beat) * 2) ease-in-out infinite;
        animation-delay: calc(var(--tanz67-beat) * -1);
    }
    .tanz67.is-playing .tanz67-upper {
        animation: tanz67-sway calc(var(--tanz67-beat) * 2) ease-in-out infinite;
    }
    .tanz67.is-playing .tanz67-head {
        animation: tanz67-nod calc(var(--tanz67-beat) * 2) ease-in-out infinite;
    }
    .tanz67.is-playing .tanz67-bob {
        animation: tanz67-bob var(--tanz67-beat) ease-in-out infinite;
    }
    .tanz67.is-playing .tanz67-shadow {
        animation: tanz67-shadow var(--tanz67-beat) ease-in-out infinite;
    }
    .tanz67.is-playing .tanz67-leg--left {
        animation: tanz67-step calc(var(--tanz67-beat) * 2) ease-in-out infinite;
    }
    .tanz67.is-playing .tanz67-leg--right {
        animation: tanz67-step-mirror calc(var(--tanz67-beat) * 2) ease-in-out infinite;
        animation-delay: calc(var(--tanz67-beat) * -1);
    }

    .tanz67-confetti { display: block; }
    .tanz67.is-playing .tanz67-confetti i {
        animation: tanz67-fall var(--d) linear infinite;
        animation-delay: var(--delay);
    }

    .tanz67-progress { display: block; }
    .tanz67.is-playing .tanz67-progress {
        animation: tanz67-countdown var(--tanz67-duration) linear forwards;
    }
}

@keyframes tanz67-seesaw {
    0%, 100% { transform: rotate(14deg); }    /* left palm up: 6 */
    50%      { transform: rotate(-14deg); }   /* right palm up: 7 */
}
@keyframes tanz67-pop {
    0%, 100% { transform: scale(1.2); opacity: 1; }
    50%      { transform: scale(0.75); opacity: 0.45; }
}
@keyframes tanz67-sway {
    0%, 100% { transform: rotate(4deg); }
    50%      { transform: rotate(-4deg); }
}
@keyframes tanz67-nod {                       /* counter to the sway */
    0%, 100% { transform: rotate(-7deg); }
    50%      { transform: rotate(7deg); }
}
@keyframes tanz67-bob {
    0%, 100% { transform: translateY(0); }
    50%      { transform: translateY(-6px); }
}
@keyframes tanz67-shadow {
    0%, 100% { transform: scaleX(1); }
    50%      { transform: scaleX(0.9); }
}
@keyframes tanz67-step {
    0%, 50%, 100% { transform: rotate(0deg) translateY(0); }
    25%           { transform: rotate(5deg) translateY(-7px); }
}
@keyframes tanz67-step-mirror {
    0%, 50%, 100% { transform: rotate(0deg) translateY(0); }
    25%           { transform: rotate(-5deg) translateY(-7px); }
}
@keyframes tanz67-turn {
    to { transform: rotate(360deg); }
}
@keyframes tanz67-fall {
    to { transform: translateY(110vh) rotate(540deg); }
}
@keyframes tanz67-countdown {
    from { transform: scaleX(1); }
    to   { transform: scaleX(0); }
}
