/*
 * Act I — the Attunement, and the panel its answer lands in.
 *
 * Positions come from `board-geometry.css`; nothing here is a measured number.
 */

/* --- The DESTINY panel ---------------------------------------------------- */

/*
 * The board's painted display case, on the left.
 *
 * Sized and placed entirely from the measured well. The card inside is square-on while
 * the well leans very slightly — the same decision the ten recesses take, and for the
 * same reason: real perspective on a card would fight the frames, which are final (D10).
 *
 * No border, no ground, no ring. The board draws the case; a rounded rectangle a few
 * pixels inside a painted one reads as a rendering fault.
 */
.destiny {
    position: absolute;
    inset-block-start: var(--board-destiny-y);
    inset-inline-start: var(--board-destiny-x);
    transform: translate(-50%, -50%);
    aspect-ratio: var(--card-aspect);
    z-index: 2;

    /*
     * The card is laid out at reading size and scaled down into the well, exactly as a
     * seat does — see "Rendered large, shown small" in card.css. Sized to the well and
     * magnified it would be a blow-up of a raster made at panel size.
     */
    --seat-cqh: var(--board-destiny-cqh);
    --seat-scale: calc(var(--seat-cqh) / var(--render-cqh));
    width: calc(var(--seat-cqh) * 1cqh);
}

/*
 * The mount carries the down-scale; the card never knows it is shown small.
 *
 * Identical in job and in shape to `.slot__mount`, and it has to be. `.card--inspecting`
 * replaces the card's own `transform`, so a card that carried its own `scale()` would
 * lose it the instant it was held — and gain `--present-scale`, which is the *reciprocal*
 * of the scale it just lost. The Destiny duly left the screen. Put the scale one element
 * out and the two cancel exactly, which is the whole design of "held up to be read".
 */
.destiny__mount {
    position: absolute;
    inset-block-start: 50%;
    inset-inline-start: 50%;
    width: calc(var(--render-cqh) * 1cqh);
    aspect-ratio: var(--card-aspect);
    transform: translate(-50%, -50%) scale(var(--seat-scale));
}

.destiny__card {
    position: absolute;
    inset: 0;
    width: 100%;
    /*
     * Leaning with its case. The painted well's sides lean about two degrees and a
     * square-on card in it reads as crooked from across the room — the same call the deck
     * makes in its own well. A SKEW rather than a rotation, for the deck's reason: a
     * rotated card tilts its top edge against a level painted one.
     *
     * `.card--inspecting` replaces this, so a Destiny held up to be read is square-on.
     * That is right — it is in your hand at that point, not in the case.
     */
    transform: skewX(var(--board-destiny-skew));
}

/*
 * Arriving is no longer an animation of its own.
 *
 * There used to be a `destiny-arrive` drop-and-settle on the mount, because the card
 * appeared in the case and turned over there. It is now drawn centre-stage, turned in
 * the reader's hand, and *travels* into the case on `.card--inspecting`'s own transition
 * — the same one that puts a dealt card back in its slot. A keyframe drop on top of that
 * travel would be two arrivals for one card, so the state exists only to say the reveal
 * is still running: no glow yet, and no `settled` shadow.
 */
.destiny[data-state='revealing'] {
    cursor: pointer;
}

/*
 * Settled, and glowing very slightly. Enough to say *this is yours and it is still here*
 * two minutes later, not enough to compete with the ten cards that are the actual reading.
 */
.destiny[data-state='settled'] .destiny__card {
    filter: drop-shadow(0 0 1.2cqh color-mix(in srgb, var(--colour-gold) 30%, transparent));
}

/*
 * The mount is transformed, so it is a stacking context of its own and traps the held
 * card inside it — the same trap as `.slot__mount`, met at the same place in the tree.
 */
.destiny[data-held='true'] .destiny__mount {
    z-index: 40;
}

/*
 * Readable. In the panel this card is 176px wide, which puts its body copy at about six
 * pixels — there to be recognised, not to be read. Clicking it holds it up exactly as a
 * dealt card is held up.
 */
.destiny[data-state] {
    cursor: pointer;
}

/*
 * **This element has a `transform`, so it is a stacking context**, and the card's own
 * `z-index` cannot lift it past the scrim from inside. Whatever raises a card has to
 * raise every transformed ancestor between it and the scrim — the same trap already
 * documented on `.slot__mount` and again on `.table__row`, met here a third time by a
 * third element that centres itself with a translate.
 */
.destiny[data-held='true'] {
    z-index: 40;
}

/* --- The ceremony --------------------------------------------------------- */

/*
 * The one thing in this client that legitimately floats, so it is the one thing allowed
 * a ground of its own. Everything else sits on painted furniture (see CLAUDE.md §4).
 *
 * `[hidden]` is enforced with `!important` in reset.css precisely so nothing can leave a
 * hidden element on screen by accident, and `display: grid` here would fight it — so the
 * grid goes on a selector that only matches when it is *not* hidden.
 */
.attunement {
    position: absolute;
    inset: 0;
    z-index: 60;

    background:
        radial-gradient(ellipse at 50% 45%,
            color-mix(in srgb, var(--colour-table-deep) 82%, transparent) 0%,
            color-mix(in srgb, black 92%, transparent) 70%);
    backdrop-filter: blur(2px);
}

/*
 * A tight stack, centred — NOT a page with a header and a footer.
 *
 * The pair row used to be `1fr`, which made it eat every spare pixel and pushed the
 * scene to the top of the screen and the prompt to the bottom. Both then read as page
 * furniture rather than as part of the question: the eye lands on two large cards in the
 * middle and never travels 30cqh to find out what it is being asked. Every row is `auto`
 * and the whole stack centres as one object, so the words sit against the cards they
 * belong to.
 *
 * The gap is a shade wider than the hover lift, so pointing at a card raises it toward
 * the scene without ever touching it.
 */
.attunement:not([hidden]) {
    display: grid;
    grid-template-rows: auto auto auto auto;
    justify-items: center;
    align-content: center;
    gap: 2.2cqh;
    padding: 2cqh 4cqw;
}

.attunement__progress {
    font-family: var(--font-display);
    font-size: 1.5cqh;
    letter-spacing: 0.34em;
    text-transform: uppercase;
    color: color-mix(in srgb, var(--colour-gold) 62%, transparent);
}

/*
 * The scene, and the reason this is a story question rather than a preference one. Set
 * large and in the body face, because it is prose and the two cards under it are not.
 */
.attunement__scene {
    max-width: 62cqw;
    text-align: center;
    font-family: var(--font-body);
    font-style: italic;
    font-size: 3.1cqh;
    line-height: 1.3;
    color: var(--colour-text);
    text-shadow: 0 0.2cqh 1cqh rgb(0 0 0 / 80%);
}

.attunement__pair {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 5cqw;

    /*
     * Read at the size a held card is read at, then scaled to fit two side by side. The
     * pair is the whole screen at this moment, so anything smaller would be asking
     * someone to squint at the most important decision in the act.
     */
    --seat-cqh: 38;
    --seat-scale: calc(var(--seat-cqh) / var(--render-cqh));
}

/*
 * A seat, not a button — visually. It carries no chrome of its own because the card *is*
 * the affordance; a bordered rectangle around a painted card frame is two frames.
 */
.attunement__seat {
    position: relative;
    width: calc(var(--seat-cqh) * 1cqh);
    aspect-ratio: var(--card-aspect);
    padding: 0;
    border: none;
    background: none;
    cursor: pointer;
    transition: translate 220ms var(--ease-lift), filter 220ms ease, opacity 320ms ease;
}

.attunement__seat .card {
    position: absolute;
    inset-block-start: 50%;
    inset-inline-start: 50%;
    width: calc(var(--render-cqh) * 1cqh);
    aspect-ratio: var(--card-aspect);
    transform: translate(-50%, -50%) scale(var(--seat-scale));
}

/* Nothing is choosable until both have turned. */
.attunement[data-phase='dealing'] .attunement__seat {
    cursor: default;
}

.attunement[data-phase='open'] .attunement__seat:hover,
.attunement[data-phase='open'] .attunement__seat:focus-visible {
    translate: 0 -1.6cqh;
    filter: drop-shadow(0 1.4cqh 2cqh rgb(0 0 0 / 60%))
            drop-shadow(0 0 1.6cqh color-mix(in srgb, var(--colour-gold) 45%, transparent));
    outline: none;
}

/*
 * The choice, made visible. The taken card lifts and holds; the other falls away.
 *
 * Both are needed. Fading only the loser reads as a bug — the card you clicked does
 * nothing and its neighbour vanishes — and lifting only the winner leaves the rejected
 * option sitting there as though it were still available.
 */
.attunement[data-phase='taken'] .attunement__seat[data-taken='true'] {
    translate: 0 -2.4cqh;
    filter: drop-shadow(0 0 2.4cqh color-mix(in srgb, var(--colour-gold) 60%, transparent));
}

.attunement[data-phase='taken'] .attunement__seat[data-taken='false'] {
    translate: 0 2.2cqh;
    opacity: 0;
    pointer-events: none;
}

.attunement__prompt {
    font-family: var(--font-display);
    font-size: 1.7cqh;
    letter-spacing: 0.24em;
    text-transform: uppercase;
    color: color-mix(in srgb, var(--colour-gold) 70%, transparent);
    transition: opacity 200ms ease;
}

/* Nothing to take yet, and nothing left to take. */
.attunement[data-phase='dealing'] .attunement__prompt,
.attunement[data-phase='taken'] .attunement__prompt,
.attunement[data-phase='closing'] .attunement__prompt {
    opacity: 0;
}

/*
 * The act ending: the five scenes dim away before the Destiny is drawn.
 *
 * Hiding the overlay outright cut from the last pair of cards to the board in a single
 * frame, and the Destiny arriving afterwards read as a fourth thing happening rather
 * than as the answer to the five that came before. Fading gives the reveal something to
 * arrive into.
 *
 * `pointer-events: none` because the cards are still on screen while they fade and a
 * sixth answer clicked into a finished act would resolve nothing — the ceremony has
 * already let go of its resolver.
 */
.attunement[data-phase='closing'] {
    opacity: 0;
    pointer-events: none;
    transition: opacity var(--duration-turn) ease-out;
}
