/* ============================================================
   UNIQorn — draw.css
   /tarot-akashic/draw/ — 线上免费抽牌.

   Base is exactly var(--white) (checklist A2). Soft paper surfaces distinguish
   the counterpart drawer and reflection from the main reading.

   One question, one card, one press. The page has no photograph and no door
   list, so nothing here inherits the space landing's composition — what it
   has instead is a question and an answer, and a single indigo stroke that
   leaves the first and comes to rest on the second.

   The whole interaction is one number
   -----------------------------------
   --draw-p runs 0 -> 1. It is the drawn length of the ink, the arrival of the
   card and its reading, and the appearance of the red point, and it is the
   only thing JavaScript writes. It defaults to 1, so with no script — or with
   reduced motion asked for, or in print — the entire answer is present and
   nothing is hidden. JS writes it *inline*, and inline beats this stylesheet,
   so "JS is driving" and "nothing is hidden" are the same declaration and
   cannot drift apart.

   The reveal windows below are the drawer's rule applied again: the card is
   solid before the ink reaches it. There the generator put the anchor at 0.406
   of the path; here the anchor is where the path *ends*, so the card and the
   reading settle over 0.62-0.90 and the point appears over 0.84-1.00, i.e. as
   the line lands on it.

   Colour: two hues and the anchor. No fourth, no new tokens — everything here
   resolves against foundation.css's :root.
   ============================================================ */

.draw-stage {
    --draw-p: 1;

    /*
     * The ink's dash length, in *screen* pixels — assets/draw.js overwrites it
     * with the path's own measured length before anything is drawn.
     *
     * The default is deliberately absurd rather than the generator's figure.
     * A literal here would be a second source for a generated number, and the
     * only two states the default has to serve are the extremes: at --draw-p 1
     * the offset is zero, so any dash longer than the path draws it whole (the
     * no-JS render), and at --draw-p 0 the offset is the whole dash, so nothing
     * is drawn. Both are true for any value larger than the path.
     */
    --line-len: 9999px;

    /* The red point floats above the card, centred on it. One number, used by
       the anchor and by the line's seating in assets/draw.js — the generator's
       reference frame describes this same arrangement rather than keeping a
       second copy of it. */
    --draw-anchor-gap: 30px;

    position: relative;
    width: 100%;
    max-width: 44rem;
    margin-inline: auto;
    padding-block: var(--space-6) var(--space-18);
}

/* The ask page has nothing below the press, so it does not need the stage's
   bottom air — the note is the last thing on it. */
.draw-stage--ask { padding-block: var(--space-6) var(--space-12); }

/* ---------- the way back ---------- */

/*
 * The one row on this page that points backwards.
 *
 * Wallance, 2026-09-24: 「免费抽牌在解读的部分可不可以加一个 back 回到主页的按键
 * （左上角部分）」.
 *
 * Why it has to exist: the header carries the way home, but it is not sticky
 * and the answer is a long document. By the time anyone is reading the card
 * the header has scrolled away, and every link left on screen — the exits at
 * the foot of the page — points forwards. So the reveal opens with one quiet
 * row pointing back, at its top left.
 *
 * And it has to *stay*. The reading is one line and a card, but the
 * reflection prompt and the exits below it add another full screen, and a
 * row that scrolls away the moment you start reading the card is no better
 * than the header it replaces. So the row is also a small floating chip in
 * the top-left corner of the page — same link, same words, same hand —
 * that hands itself off to the inline row when it is on screen and steps
 * back in when it is not.
 *
 * The two are governed by one viewport test, so they cannot be in two states
 * at once, and a row that only exists once a script has run cannot be the
 * way out of a page for anyone without the script. With no script the page
 * is also at the top of the document, so the inline row is the only one
 * needed, and it stays where it always was. The chip is purely the script's
 * gift, and is removed the moment the inline row re-enters.
 *
 * The arrow is at the left and travels left on hover — the exits' gesture read
 * the other way round. There is no Latin counterpart: the label is a place,
 * not a name from the VOLUME list, and inventing a new one is exactly what
 * §6.1.2 forbids.
 */
.draw-back {
    display: inline-flex;
    align-items: center;
    gap: var(--space-3);
    margin-bottom: var(--space-8);
    color: var(--meta);
    text-decoration: none;
    font-family: var(--font-body);
    font-size: var(--text-sm);
    letter-spacing: var(--tracking-label);
    opacity: clamp(0, calc((var(--draw-p) - .5) * 4), 1);
    transition: color var(--motion-base) var(--ease-standard);
}
.draw-back:hover { color: var(--indigo); }
.draw-back-go { transition: transform var(--motion-base) var(--ease-standard); }
.draw-back:hover .draw-back-go { transform: translateX(-6px); }

.draw-redraw-icon {
    display: inline-block;
    transition: transform .3s ease;
}
.draw-redraw-btn:hover .draw-redraw-icon,
.draw-redraw-btn:focus-visible .draw-redraw-icon { transform: rotate(90deg); }

/*
 * The floating chip — only when the inline row is not visible.
 *
 * Same DOM element, two positions, one viewport test. The chip is the same
 * pixel as the inline row's first line (16px font, 1.2 line-height, 21px
 * button), measured from the same top-left, so when it appears the layout
 * does not shift and the inline row's bottom margin is not orphaned.
 *
 * The chip is on the *article*, not the stage, so it sits above the header
 * the moment the reading begins and never appears on the ask page (the
 * hero's lede is the page's orientation there, and the chip would be a
 * third thing competing with it).
 *
 * --draw-back-floating is the single fact the script writes: 1 when the
 * chip is on screen, 0 when it is not. The chip's own opacity is gated on
 * both this and --draw-p so it cannot show up before there is a reading,
 * and a state that has neither (no script, no reading) gets nothing.
 */
.draw-page--revealed .draw-back {
    margin-bottom: var(--space-8);
}

/*
 * On a desktop the row is taken out of the flow and pinned to the top left of
 * the reveal, so it does not push the sentence down.
 *
 * It used to sit in normal flow, above 「你心中的问题，宇宙给你的回应」, and that
 * one row of 21px plus its 40px bottom margin was 56px of empty paper between
 * the top of the answer and the sentence the page is built around. The way back
 * is a convenience in the corner; the sentence is the answer. So the row is
 * absolute, the sentence starts at the top centre, and both are where they
 * should be.
 *
 * Phones keep it in flow: at 360px the corner is where the sentence begins, and
 * an absolutely positioned link would sit on top of it.
 */
.draw-reveal { position: relative; }

@media (min-width: 641px) {
    .draw-reveal > .draw-back,
    .draw-stage > .draw-back {
        position: absolute;
        top: 0;
        left: 0;
        margin-bottom: 0;
        z-index: 3;
    }
}
.draw-page--revealed .draw-back.is-floating {
    position: fixed;
    top: 24px;
    left: 24px;
    z-index: 10;
    margin: 0;
    padding: 6px var(--space-3);
    border: 1px solid var(--line);
    border-radius: var(--radius-pill);
    background: rgba(255, 255, 255, 0.92);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    opacity: clamp(0, calc((var(--draw-p) - .5) * 4) * var(--draw-back-floating, 0), 1);
}
@media (max-width: 640px) {
    .draw-page--revealed .draw-back.is-floating {
        top: 16px;
        left: 16px;
    }
}

/* ---------- the question, which is where the line starts ---------- */

/*
 * The line's entry is the end of this sentence, and assets/draw.js measures it
 * with a Range rather than with the element's box — a block-level <p> reports
 * the full column width, and the line has to leave the *question*, not the
 * column. That also makes the entry correct on phones, where the sentence
 * wraps and the end of it is the end of the last line.
 */
/*
 * The passage between the question and the card — the air the line crosses.
 *
 * It used to be --space-22, 88px, which is the space between two paragraphs.
 * That made the line 98px long, and a 1px hairline with a 4px bow over 98px
 * reads as a hook, not as a line. The other two lines on this site are about
 * distance — the cover crosses a room, a landing crosses a page — and this one
 * had none, so the page's one gesture was a connector between two things that
 * were already adjacent.
 *
 * It scales with the window height rather than being a fixed number, because
 * what it has to be is a proportion of what the visitor can see: too little and
 * the line is a hook again, too much and the question and the answer stop
 * belonging to each other. At 900 tall this is 252px, which puts the chord at
 * about 300px — near enough to the 308px the generator was designed around that
 * the curve it validated is the curve that gets drawn.
 *
 * Wallance, 2026-09-19: 给他距离.
 *
 * The ask page does not take it. There the press *is* the response to the
 * sentence, and putting 250px between them makes the visitor travel to act on
 * something they have just read — which is the opposite of what that page is
 * for. The passage belongs to the answer, where the line has to cross it.
 */
.draw-stage {
    --draw-passage: clamp(190px, 28vh, 330px);
}

.draw-ask {
    max-width: 30rem;
    margin: 0 0 var(--space-22);
    font-family: var(--font-display);
    font-size: clamp(17px, 1.7vw, 21px);
    line-height: 1.7;
    color: var(--fg-2);
}

/*
 * The reading's own sentence, and the top of the page.
 *
 * Centred on the page's axis, tight to the top of the reveal: the line now
 * leaves its *bottom centre* rather than the end of its last character, so the
 * sentence has to be symmetrical about the axis for the ink to fall from it
 * straight.
 *
 * The measure is 18em, not a ch count. `ch` is the width of a zero, and in a
 * CJK sentence that is half a character — 28ch clipped 「你心中的问题，宇宙给你的
 * 回应」 by one glyph and left 应 alone on a second line, which is the worst
 * possible wrap for a centred sentence. 18em holds all fifteen characters on
 * one line at every size this text takes; `balance` keeps a phone's two-line
 * wrap even rather than 14/1.
 */
.draw-reveal .draw-ask {
    max-width: min(100%, 18em);
    margin: 0 auto;
    padding-top: 2px;
    text-align: center;
    text-wrap: balance;
}

.draw-reveal .draw-ask,
.draw-prompt-line {
    font-family: var(--font-display);
    font-size: clamp(20px, 2.1vw, 26px);
    line-height: 1.6;
    letter-spacing: 0.04em;
    color: var(--fg-2);
    text-align: center;
}

/* ---------- the press ---------- */

/* The wrapper exists so the shuffle has something to hang above. The button's
   bottom air moves here: on an inline-flex child it would sit outside the
   wrapper's height and the deck would have nothing to clear. */
.draw-press {
    position: relative;
    display: inline-block;
    margin-bottom: var(--space-12);
}

.draw-go {
    display: inline-flex;
    flex-direction: column;
    align-items: center;
    gap: var(--space-2);
    min-height: 48px;
    padding: 0.85rem 2.2rem;
    border: 1px solid var(--indigo);
    border-radius: var(--radius-pill);
    background: var(--white);
    color: var(--indigo);
    text-decoration: none;
    text-align: center;
    transition: background var(--motion-base) var(--ease-standard),
                color var(--motion-base) var(--ease-standard);
}

.draw-redraw-btn {
    display: inline-flex;
    flex-direction: row;
    align-items: center;
    justify-content: center;
    gap: 0.55rem;
    min-height: 44px;
    padding: 0.65rem 1.6rem;
    border: 1px solid var(--indigo);
    border-radius: var(--radius-pill);
    background: var(--white);
    color: var(--indigo);
    text-decoration: none;
    text-align: center;
    white-space: nowrap;
    transition: background var(--motion-base) var(--ease-standard),
                color var(--motion-base) var(--ease-standard);
}

.draw-redraw-label {
    font: 500 14px/1 var(--font-body);
    letter-spacing: 0.12em;
}

.draw-redraw-sep { opacity: 0.5; }

.draw-redraw-en {
    font: 500 11px/1 var(--font-mono);
    letter-spacing: 0.18em;
    text-transform: uppercase;
    opacity: 0.78;
}
.draw-go:hover,
.draw-go:focus-visible,
.draw-redraw-btn:hover,
.draw-redraw-btn:focus-visible { background: var(--indigo); color: var(--white); }
.draw-go:focus-visible,
.draw-redraw-btn:focus-visible {
    outline: 2px solid var(--indigo);
    outline-offset: 4px;
}
.draw-go-label {
    font: 500 var(--text-sm)/1.2 var(--font-body);
    letter-spacing: var(--tracking-label);
}
.draw-go-en {
    font: 500 11px/1 var(--font-mono);
    letter-spacing: .28em;
    text-transform: uppercase;
    color: var(--meta);
    transition: color var(--motion-base) var(--ease-standard);
}
.draw-go:hover .draw-go-en,
.draw-go:focus-visible .draw-go-en { color: var(--white); }

/* ---------- the deck ----------

   The six-card shuffle that used to live here is gone. It was the press's own
   little gesture, and the experience replaced it with the real thing: 78 backs,
   a fan, a pick and a melt, in assets/draw-deck.css.

   Keeping both was the original plan — the six as a degenerate case of the 78 —
   and it was the wrong call twice over. The names collide, so every rule of the
   78 had to be scoped to [data-draw-deck] to leave the six alone, and worse: the
   six's `.draw-deck` box (position: absolute, 32 x 55, parked above the button)
   then applied to the 78 as well and parked the whole fan off-screen. A deck
   component with a second, invisible deck underneath it is not a component.

   What survives is the back itself. The 78-card deck paints one shared image,
   img/tarot/tarot-card-back.webp, onto every button in the fan (assets/draw-deck.css).

*/

/* ---------- the drawn line ---------- */

.draw-drawn {
    position: absolute;
    inset: 0;
    pointer-events: none;
}

.draw-line {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    overflow: visible;
}

/*
 * The line is only ever what has been drawn. At --draw-p 0 there is nothing on
 * screen at all — no track under it showing where it intends to go. That is
 * the drawer's rule (skill §64: Wallance asked for ink, not a plan of the ink)
 * and it holds here too.
 *
 * --line-len is written by assets/draw.js from the path's own measured screen
 * length. vector-effect keeps the hairline a hairline: without it the
 * non-uniform stretch of preserveAspectRatio="none" would thicken the line on
 * one axis and thin it on the other, differently at every window size.
 */
.draw-ink {
    fill: none;
    stroke: var(--indigo);
    stroke-width: 1;
    stroke-linecap: round;
    stroke-linejoin: round;
    vector-effect: non-scaling-stroke;
    stroke-dasharray: var(--line-len);
    stroke-dashoffset: calc(var(--line-len) * (1 - var(--draw-p)));
}

/* ---------- the seat: the card, and the point above it ---------- */

/*
 * The card and its words are centered in a single vertical narrative flow.
 * The card takes center stage, and the reading unfolds directly below it.
 */
.draw-answer {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--space-12);
}

.draw-seat {
    position: relative;
    width: clamp(180px, 25vw, 272px);
    margin-inline: auto;
}

/*
 * The passage between the sentence and the card.
 *
 * It used to be --draw-passage, 190-330px, tuned for a line that crossed the
 * page sideways. With the ink leaving the sentence's bottom centre and landing
 * on the point above the card, that distance stopped being a journey and became
 * a gap: the thread was a long, thin nothing. A compact drop is the proportion
 * the gesture now wants — and the number is the *thread*, not the gap: 14px of
 * entry air below the sentence and 30px of anchor clearance above the card come
 * out of it, so ~108px of margin draws a ~64px thread.
 *
 * The margin is on the seat rather than on the card because the anchor is
 * positioned against the seat's top edge: a margin on the card would open a
 * space between the point and the card it is supposed to be marking.
 */
.draw-reveal .draw-seat {
    margin-top: clamp(6.75rem, 11vh, 8.25rem);
}

.draw-anchor {
    position: absolute;
    left: 50%;
    top: calc(-1 * var(--draw-anchor-gap));
    width: 9px;
    height: 9px;
    margin: -4.5px 0 0 -4.5px;
    border-radius: 50%;
      background: var(--anchor-red);
      /* Rose Anchor with its own halo, nothing else. One per screen, graphic
         only, never a text colour — see skill §66. */
      box-shadow: 0 0 0 5px rgba(197, 139, 142, .10);
    opacity: clamp(0, calc((var(--draw-p) - .84) * 6.25), 1);
}

/*
 * The card, and the turn.
 *
 * The figure is only a perspective; everything that paints is on the two
 * faces. That split is forced: `overflow: hidden` flattens a 3D context, and
 * the card used to clip its own corners, so the inner could not have
 * preserved depth and the "turn" would have been a slide.
 *
 * --flip is the whole turn. 1 is face-up, which is the default, so a visitor
 * with no script — or with reduced motion asked for — simply gets the card
 * already turned. The script writes 0 before the reveal and lets it move to 1,
 * which means the animation is the *return* to the default rather than a
 * special state that has to be cleaned up.
 */
.draw-card {
    --flip: 1;
    margin: 0;
    aspect-ratio: var(--card-ratio);
    perspective: 1100px;
    opacity: clamp(0, calc((var(--draw-p) - .62) * 3.6), 1);
}

/* In the experience, the visitor just drew this card: it is already present and
   turns over from its back to its face right before them. Both the reveal container
   and the card are immediately visible so the full 180° turn is clearly seen. */
.draw-stage--experience[data-draw-state="revealed"] .draw-reveal {
    opacity: 1;
    visibility: visible;
    transition: none;
}

.draw-stage--experience[data-draw-state="revealed"] .draw-card {
    opacity: 1;
    visibility: visible;
    transform-origin: center center;
}

@keyframes draw-card-grow {
    from {
        transform: scale(0.36) translateY(-14px);
        box-shadow: var(--shadow-lg);
    }
    to {
        transform: scale(1) translateY(0);
        box-shadow: var(--shadow-lg);
    }
}

.draw-card.is-growing {
    transform-origin: center center;
    animation: draw-card-grow 1800ms var(--ease-flow) both;
}

.draw-card-inner {
    position: relative;
    display: block;
    width: 100%;
    height: 100%;
    transform-style: preserve-3d;
    transform: rotateY(calc((1 - var(--flip)) * 180deg));
}

/*
 * The turn is a keyframe animation, not a transition.
 *
 * It was a transition first, driven by writing --flip to 0 and then taking the
 * value away so it would travel back to its default of 1. That never worked,
 * and the reason is worth keeping: with `transition: transform 900ms`, the
 * computed transform at the instant the value changes is still the *start* of
 * the transition. Writing 0 therefore rendered nothing visible, and taking it
 * away two frames later set the same target it already had — identity — so the
 * card went from face-up to face-up with 900ms of nothing in between. A
 * transition needs to be *seen* leaving from where it was; an entrance has no
 * "from" until something puts it there.
 *
 * A keyframe animation states both ends, so neither end depends on timing.
 */
.draw-card-inner.is-turning {
    animation: draw-card-turn 1800ms var(--ease-flow) both;
}

@keyframes draw-card-turn {
    from { transform: rotateY(180deg); }
    to   { transform: rotateY(0deg); }
}

.draw-card-face {
    position: absolute;
    inset: 0;
    overflow: hidden;
    border-radius: var(--radius-md);
    border: 1px solid var(--line);
    background: var(--paper);
    box-shadow: var(--shadow-lg);
    backface-visibility: hidden;
}

.draw-card-face--back {
    transform: rotateY(180deg);
    background: url('img/tarot/tarot-card-back.webp') center / cover no-repeat;
}

/*
 * The back is the confirmed original water-ripples card back.
 */
.draw-card-face--back::after {
    display: none;
}

.draw-card img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

/* Reversed is the same card turned over — geometry, not a second asset. */
.draw-card.is-reversed img { transform: rotate(180deg); }

/* Reduced motion: the card is simply already face-up — --flip's default — and
   the script never asks for a turn, so there is nothing to suppress here
   beyond the animation itself. The guard is on the script side, where the
   decision to animate actually lives. */
@media (prefers-reduced-motion: reduce) {
    .draw-card-inner.is-turning,
    .draw-card.is-growing { animation: none; }
}

/* ---------- the reading ---------- */

.draw-reading {
    width: 100%;
    max-width: 34rem;
    margin-inline: auto;
    text-align: center;
    opacity: clamp(0, calc((var(--draw-p) - .68) * 4.5), 1);
}

.draw-orientation {
    display: inline-flex;
    align-items: center;
    margin: 0 0 var(--space-3);
    padding: 5px 14px;
    border: 1px solid rgba(30, 58, 95, 0.22);
    border-radius: var(--radius-pill);
    background: rgba(30, 58, 95, 0.04);
    font: 500 12px/1.2 var(--font-body);
    letter-spacing: 0.14em;
    color: var(--indigo);
    text-align: center;
}

/*
 * Where the card stands in the deck.
 *
 * The orientation line says which face is showing; this one says what the card
 * *is* — its number, its arcana, its element. It sits directly under the
 * orientation badge in a quiet mono face, so taxonomy stays distinct from
 * status. A reading that only says 「逆位」 hands the
 * visitor a verdict; a reading that also says 「07 · 大阿卡纳 · 巨蟹座」 hands
 * them a place to stand.
 */
.draw-meta {
    margin: 0 0 var(--space-5);
    font: 400 12px/1.6 var(--font-mono);
    letter-spacing: 0.16em;
    color: var(--meta);
    text-align: center;
}
.draw-meta:empty { display: none; }

.draw-name {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    margin: 0 0 var(--space-4);
    font-family: var(--font-display);
    font-size: clamp(30px, 3.4vw, 40px);
    font-weight: 400;
    line-height: 1.2;
    letter-spacing: 0.04em;
    color: var(--fg);
    text-align: center;
}
.draw-name-en {
    font: 500 11px/1.2 var(--font-mono);
    letter-spacing: .28em;
    text-transform: uppercase;
    color: var(--meta);
}

.draw-archetype {
    max-width: 100%;
    margin: 0 auto var(--space-7);
    padding-bottom: var(--space-7);
    border-bottom: 1px solid var(--line);
    font-family: var(--font-body);
    font-size: var(--text-base);
    line-height: 1.7;
    letter-spacing: 0.03em;
    color: var(--muted);
    text-align: center;
}

/* The four keywords, under the archetype's rule. Quiet on purpose: they are the
   reading's vocabulary, not a second headline. Hidden when there are none. */
.draw-keywords {
    margin: 0 auto var(--space-5);
    font: 500 12px/1.6 var(--font-body);
    letter-spacing: 0.14em;
    color: var(--indigo);
    opacity: 0.82;
    text-align: center;
}
.draw-keywords:empty { display: none; }

.draw-title {
    margin: 0 auto var(--space-5);
    font-family: var(--font-display);
    font-size: clamp(21px, 2.1vw, 25px);
    font-weight: 500;
    line-height: 1.5;
    letter-spacing: 0.02em;
    color: var(--fg);
    text-align: center;
    text-wrap: balance;
}

.draw-desc {
    margin: 0 auto;
    max-width: 100%;
    font-size: 16.5px;
    line-height: 1.95;
    letter-spacing: 0.02em;
    color: var(--fg-2);
    text-align: left;
    text-wrap: pretty;
}

/* ---------- the other face of the card ---------- */

/*
 * 「全息视角」 — the counterpart, one press away.
 *
 * A reversed draw used to end on its warning. That is half a card: the upright
 * face is the same card's other half, and a reading that withholds it reads as
 * a bad omen and as a page keeping something back. So the counterpart is always
 * the *other* orientation, it is native <details> (works with no script), and
 * it is closed until asked for — the answer above it is what the visitor came
 * for, and this is what they can open when they want to go one layer deeper.
 *
 * A contained paper surface and a circular plus make this an unmistakable
 * interactive drawer, separate from the main reading and reflection.
 */
.draw-counterpart {
    max-width: 34rem;
    margin: var(--space-8) auto 0;
    padding: var(--space-4) var(--space-6);
    border: 1px solid var(--line);
    border-radius: var(--radius-md);
    background: rgba(251, 248, 243, 0.65);
    text-align: left;
}

.draw-counterpart-summary {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-4);
    min-height: 44px;
    cursor: pointer;
    list-style: none;
    color: var(--indigo);
    transition: color var(--motion-base) var(--ease-standard);
}
.draw-counterpart-summary::-webkit-details-marker { display: none; }
.draw-counterpart-summary::marker { content: ''; }
.draw-counterpart-summary:hover { color: var(--indigo); }
.draw-counterpart-summary:focus-visible {
    outline: 1px solid var(--indigo);
    outline-offset: 4px;
}

.draw-counterpart-label {
    font: 500 var(--text-sm)/1.6 var(--font-body);
    letter-spacing: var(--tracking-label);
}

/* The plus rotates into a close mark when the drawer is open. */
.draw-counterpart-go {
    flex: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 26px;
    border: 1px solid rgba(30, 58, 95, 0.16);
    border-radius: 50%;
    background: rgba(30, 58, 95, 0.04);
    font-size: 13px;
    line-height: 1;
    transition: transform var(--motion-base) var(--ease-standard);
}
.draw-counterpart[open] .draw-counterpart-go { transform: rotate(45deg); }

.draw-counterpart[open] .draw-counterpart-body {
    margin-top: var(--space-4);
    padding-top: var(--space-5);
    border-top: 1px solid var(--line-soft);
}

.draw-counterpart-note {
    margin: 0 0 var(--space-5);
    font-size: var(--text-sm);
    line-height: 1.9;
    color: var(--meta);
}

.draw-counterpart-title {
    margin: 0 0 var(--space-3);
    font-family: var(--font-display);
    font-size: clamp(18px, 1.8vw, 21px);
    line-height: 1.5;
    color: var(--fg);
}

.draw-counterpart-desc {
    margin: 0;
    font-size: var(--text-md);
    line-height: 1.95;
    letter-spacing: 0.02em;
    color: var(--muted);
}

/* ---------- the reflection prompt ---------- */

.draw-prompt {
    max-width: 34rem;
    margin: var(--space-10, 40px) auto 0;
    padding: var(--space-10, 40px) var(--space-8);
    border-top: 1px solid var(--line);
    border-bottom: 1px solid var(--line);
    border-radius: var(--radius-sm);
    background: linear-gradient(180deg, rgba(30, 58, 95, 0.02) 0%, rgba(120, 154, 203, 0.03) 100%);
    text-align: center;
    opacity: clamp(0, calc((var(--draw-p) - .68) * 4.5), 1);
}

.draw-redraw-bar {
    display: flex;
    justify-content: center;
    margin-top: var(--space-8);
    opacity: clamp(0, calc((var(--draw-p) - .68) * 4.5), 1);
}
@media (prefers-reduced-motion: reduce) {
    .draw-go,
    .draw-go-en,
    .draw-redraw-btn,
    .draw-redraw-icon { transition: none; }
    .draw-redraw-btn:hover .draw-redraw-icon,
    .draw-redraw-btn:focus-visible .draw-redraw-icon,
    .draw-redraw-btn:hover,
    .draw-redraw-btn:focus-visible { transform: none; }
}

.draw-prompt-label {
    display: inline-block;
    margin: 0 auto var(--space-5);
    padding-bottom: var(--space-3);
    border-bottom: 1px solid rgba(120, 154, 203, 0.35);
    font: 500 12px/1.4 var(--font-body);
    letter-spacing: 0.22em;
    color: var(--indigo);
    text-align: center;
}

.draw-prompt-text {
    margin: 0 auto;
    max-width: 30rem;
    font-family: var(--font-display);
    font-size: clamp(18px, 1.8vw, 22px);
    line-height: 1.65;
    letter-spacing: 0.02em;
    color: var(--fg);
    text-align: center;
    text-wrap: balance;
}

/*
 * The private note.
 *
 * The prompt asks a question and the page then left the visitor holding the
 * answer. The rounded note card gives that answer a place: no name, no action,
 * no storage — it exists in the textarea and nowhere else, and 「再抽一张」
 * clears it. Focus outlines the whole card in indigo.
 */
.draw-journal {
    max-width: 34rem;
    margin: var(--space-7) auto 0;
}

.draw-journal-input {
    display: block;
    width: 100%;
    min-height: 7.5em;
    padding: var(--space-4);
    border: 1px solid var(--line);
    border-radius: var(--radius-md);
    background: rgba(255, 255, 255, 0.9);
    color: var(--fg);
    font-family: var(--font-body);
    font-size: var(--text-sm);
    line-height: 1.85;
    text-align: center;
    resize: none;
    transition: border-color var(--motion-base) var(--ease-standard);
}
.draw-journal-input::placeholder {
    color: var(--meta);
    opacity: 1;
}
.draw-journal-input:focus {
    outline: 2px solid var(--indigo);
    outline-offset: 3px;
    border-color: var(--indigo);
}

/* ---------- where the draw can go next ---------- */

/*
 * Three ways on, as an editorial index.
 *
 * The head is the difference between a menu and a funnel: it says these are
 * places to continue, not steps to take. It carries the section's top air and
 * the exits lose theirs, so the hairline above the rows belongs to the head
 * rather than floating between two blocks.
 */
.draw-exits-head {
    max-width: 34rem;
    margin: var(--space-12) auto var(--space-5);
    font: 500 var(--text-xs)/1.6 var(--font-mono);
    letter-spacing: var(--tracking-label);
    color: var(--meta);
    text-align: center;
    opacity: clamp(0, calc((var(--draw-p) - .68) * 4.5), 1);
}

.draw-exits {
    display: flex;
    flex-direction: column;
    max-width: 34rem;
    margin: 0 auto;
    border-top: 1px solid var(--line);
    opacity: clamp(0, calc((var(--draw-p) - .68) * 4.5), 1);
}

/*
 * Same shape as the space landing's door rows — a Chinese label, its Latin
 * counterpart stacked under it, one arrow — but quieter and smaller. These are
 * not the page's navigation; they are what the answer opens onto, so they sit
 * below the reading rather than beside it.
 *
 * The label and its Latin counterpart stay *together*, which is the one thing
 * the first version got wrong: it put the Chinese label at the left of the row
 * and the Latin one at the far right, and at this stage's width that is seven
 * hundred pixels apart, so the pair stopped reading as a pair. The arrow is what
 * belongs at the far right — it is the row's own gesture, not a second label.
 *
 * All three rows are the same weight now. The last one used to be indigo and
 * said 「预约一次解读」, which made the page's final sentence a request; it is a
 * row that explains what a longer conversation is, and it is offered, not
 * pushed.
 */
.draw-exit {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: start;
    gap: var(--space-3) var(--space-8);
    min-height: 56px;
    padding: var(--space-5) 0;
    border-bottom: 1px solid var(--line);
    color: var(--fg-2);
    text-decoration: none;
    transition: color var(--motion-base) var(--ease-standard);
}
.draw-exit:hover { color: var(--indigo); }
.draw-exit-body { display: block; }
.draw-exit-zh {
    display: block;
    font-family: var(--font-display);
    font-size: clamp(17px, 1.6vw, 20px);
    line-height: 1.5;
    letter-spacing: 0.02em;
    color: var(--fg);
    transition: color var(--motion-base) var(--ease-standard);
}
.draw-exit-sub {
    display: block;
    margin-top: var(--space-2);
    font-family: var(--font-body);
    font-size: var(--text-sm);
    line-height: 1.8;
    color: var(--muted);
    text-wrap: pretty;
}
.draw-exit-en {
    display: block;
    margin-top: var(--space-3);
    font: 500 11px/1 var(--font-mono);
    letter-spacing: .28em;
    text-transform: uppercase;
    color: var(--meta);
}
.draw-exit-go {
    padding-top: .35em;
    font-size: 13px;
    color: var(--mist);
    transition: transform var(--motion-base) var(--ease-standard),
                color var(--motion-base) var(--ease-standard);
}
.draw-exit:hover .draw-exit-go { transform: translateX(6px); color: var(--indigo); }
.draw-exit:hover .draw-exit-zh { color: var(--indigo); }

/* ---------- 星芒转场印记: the star, as a transition ----------

   The page used to close on uniqorn_page_ink(0) — a raster star, blurry at any
   density, static by nature. The same drawing is now inline SVG, and because it
   is inline it can be the transition rather than a decoration: the stage portal
   blooms between the pick and the reading, and the scroll divider draws itself
   open on the way from the journal to the exits.

   Three parts, animated separately, all on the same 220-unit viewBox:
   the wash (halos), the axis (two half-lines that draw outward from the
   centre), and the star (rays, orbit, core). Everything is additive: nothing
   here is a container, so nothing can shift the layout it passes through.
   ------------------------------------------------------------------ */

.draw-star-mark {
    display: block;
    width: 100%;
    height: auto;
    overflow: visible;
}

/* transform-box makes transform-origin resolve in the SVG's own coordinates
   rather than in the element's bounding box — without it a group centred on
   110,110 scales from its own corner and swings off the axis. */
.draw-star-halo,
.draw-star-rays,
.draw-star-orbit {
    transform-box: view-box;
    transform-origin: 50% 50%;
}

.draw-star-axis-top,
.draw-star-axis-bottom {
    stroke-dasharray: 106;
    stroke-dashoffset: 0;
}

/* --- A. the stage portal --- */

/*
 * Fixed rather than absolute, and centred on the window rather than on the
 * stage. At `revealed` the stage is a whole reading tall, so a stage-centred
 * mark would bloom somewhere around the journal — below the fold, unseen. The
 * portal belongs where the visitor is looking, which is the middle of the
 * screen, at both handoffs.
 *
 * It is a sibling of the deck and the reveal rather than a child of either, so
 * it can sit above both while the chosen card settles and the other
 * seventy-seven melt away. `pointer-events: none` keeps it from eating the
 * press that follows.
 */
.draw-portal-star {
    position: fixed;
    inset: 0;
    display: grid;
    place-items: center;
    pointer-events: none;
    z-index: 30;
    opacity: 0;
    visibility: hidden;
}

.draw-portal-star .draw-star-mark {
    width: clamp(200px, 32vw, 300px);
}

.draw-portal-star.is-active {
    visibility: visible;
    animation: drawStarPortal 760ms var(--ease-flow) both;
}

.draw-portal-star.is-active .draw-star-halo {
    animation: drawStarHalo 760ms var(--ease-standard) both;
}

.draw-portal-star.is-active .draw-star-rays {
    animation: drawStarRays 760ms var(--ease-flow) both;
}

.draw-portal-star.is-active .draw-star-axis-top,
.draw-portal-star.is-active .draw-star-axis-bottom {
    animation: drawStarAxis 760ms var(--ease-standard) both;
}

@keyframes drawStarPortal {
    0%   { opacity: 0; }
    35%  { opacity: 1; }
    70%  { opacity: 1; }
    100% { opacity: 0; }
}

@keyframes drawStarHalo {
    from { opacity: 0; transform: scale(.72); }
    to   { opacity: 1; transform: scale(1); }
}

/* 45deg to 0: the star arrives as an eight-pointed mark rotated onto its
   diagonals and settles onto the cardinal axes. */
@keyframes drawStarRays {
    from { opacity: 0; transform: rotate(45deg) scale(.4); }
    to   { opacity: 1; transform: rotate(0deg) scale(1); }
}

@keyframes drawStarAxis {
    from { stroke-dashoffset: 106; }
    to   { stroke-dashoffset: 0; }
}

/* --- B. the scroll divider --- */

/*
 * Where a hairline would otherwise sit between the journal and the exits. It is
 * invisible until assets/draw.js adds `is-awakened` on entry, then draws itself
 * open from the centre outward: top axis down out of the reading, wash open,
 * rays unfurl, bottom axis down into 「延伸探索」.
 */
.draw-star-transition {
    width: 100%;
    margin: var(--space-12) auto 0;
    opacity: 0;
    transition: opacity 900ms var(--ease-standard);
}

.draw-star-transition .draw-star-mark {
    width: clamp(180px, 26vw, 230px);
    margin-inline: auto;
}

.draw-star-transition.is-awakened { opacity: 1; }

.draw-star-transition .draw-star-halo {
    transform: scale(.75);
    opacity: 0;
    transition: transform 1100ms var(--ease-flow), opacity 900ms var(--ease-standard);
}

.draw-star-transition.is-awakened .draw-star-halo {
    transform: scale(1);
    opacity: 1;
}

.draw-star-transition .draw-star-rays {
    transform: rotate(-45deg) scale(.5);
    opacity: 0;
    transition: transform 1100ms var(--ease-flow) 160ms, opacity 800ms var(--ease-standard) 160ms;
}

.draw-star-transition.is-awakened .draw-star-rays {
    transform: rotate(0deg) scale(1);
    opacity: 1;
}

.draw-star-transition .draw-star-axis-top,
.draw-star-transition .draw-star-axis-bottom {
    stroke-dashoffset: 106;
    transition: stroke-dashoffset 1000ms var(--ease-standard) 120ms;
}

.draw-star-transition.is-awakened .draw-star-axis-top { stroke-dashoffset: 0; }

/* The lower half arrives last, so the mark opens downward into the section it
   is pointing at rather than in both directions at once. */
.draw-star-transition.is-awakened .draw-star-axis-bottom {
    stroke-dashoffset: 0;
    transition-delay: 560ms;
}

/* The orbit breathes once it is lit — a still mark at the foot of a long reading
   reads as a logo, and this is meant to read as a thing that is on. */
.draw-star-transition.is-awakened .draw-star-ring {
    animation: drawStarBreathe 7s ease-in-out infinite;
}

@keyframes drawStarBreathe {
    0%, 100% { opacity: .45; transform: scale(1); }
    50%      { opacity: .9;  transform: scale(1.07); }
}

@media (prefers-reduced-motion: reduce) {
    .draw-portal-star.is-active { animation: none; }
    .draw-portal-star.is-active .draw-star-halo,
    .draw-portal-star.is-active .draw-star-rays,
    .draw-portal-star.is-active .draw-star-axis-top,
    .draw-portal-star.is-active .draw-star-axis-bottom { animation: none; }

    .draw-star-transition,
    .draw-star-transition .draw-star-halo,
    .draw-star-transition .draw-star-rays,
    .draw-star-transition .draw-star-axis-top,
    .draw-star-transition .draw-star-axis-bottom {
        transition: none;
    }

    .draw-star-transition .draw-star-halo { transform: none; opacity: 1; }
    .draw-star-transition .draw-star-rays { transform: none; opacity: 1; }
    .draw-star-transition .draw-star-axis-top,
    .draw-star-transition .draw-star-axis-bottom { stroke-dashoffset: 0; }
    .draw-star-transition.is-awakened .draw-star-ring { animation: none; }
}

/* ============================================================
   Armed: the page is about to draw.

   This is the no-JS contract read the other way round. The stylesheet's
   default is the finished answer, because a visitor without a script must
   receive a whole reading rather than a half-drawn one. `is-armed` is put on
   <html> by assets/draw.js from the document head, before the first paint —
   so the finished answer never flashes on screen and then resets.

   Everything under it is geometry and opacity that the script then writes
   --draw-p to drive. Nothing is hidden that the script does not immediately
   bring back.
   ============================================================ */

.is-armed .draw-stage { --draw-p: 0; }

/* ---------- phones ---------- */

@media (max-width: 640px) {
    .draw-stage {
        /* The point needs less clearance when the card is small, or it floats
           free of the thing it is supposed to be marking. */
        --draw-anchor-gap: 22px;
    }
    .draw-prompt {
        margin-top: var(--space-8);
        padding: var(--space-8) var(--space-5);
    }
    .draw-counterpart { padding-inline: var(--space-5); }
    .draw-redraw-btn {
        gap: 0.4rem;
        padding-inline: 1.1rem;
    }
    .draw-exits-head { margin-top: var(--space-12); }
    .draw-journal { max-width: 100%; }
}

/* ============================================================
   The experience: five states on one document.

   ask → shuffle → spread → picked → revealed, carried on data-draw-state.

   Every layer is in the DOM in every state and the attribute decides what is
   shown. Nothing is added or removed — an element that only exists once a
   script has run cannot be laid out, cannot be seated against, and cannot be
   read by anyone without the script.

   Hiding is opacity *and* visibility. Opacity alone leaves a hidden layer
   focusable and readable, which is how a visitor ends up tabbing into a card
   they have not drawn yet.
   ============================================================ */

.draw-prompt-line,
.draw-ask-block,
.draw-deck,
.draw-reveal {
    transition: opacity var(--motion-slow) var(--ease-standard),
                visibility 0s linear var(--motion-slow);
}

/*
 * The prompt, above the deck. Centred, in the display face — the mono face is
 * reserved for state and metadata, and this is neither: it is the instruction
 * the visitor reads before they act.
 */
.draw-prompt-line {
    margin: 0 0 var(--space-12);
}

/* The experience centres; the reveal does not. The reveal is the editorial
   answer and keeps the page's left edge, which is what the line is seated
   against. Only the states before it are a composition of their own. */
.draw-stage--experience .draw-ask-block,
.draw-stage--experience .draw-prompt-line {
    text-align: center;
    margin-inline: auto;
}

.draw-stage--experience[data-draw-state="shuffle"] .draw-deck,
.draw-stage--experience[data-draw-state="spread"] .draw-deck,
.draw-stage--experience[data-draw-state="picked"] .draw-deck {
    margin-inline: auto;
}

/* Button Dissolve Animation */
.draw-press.is-dissolving {
    opacity: 0;
    transform: scale(0.92);
    pointer-events: none;
    transition: opacity 320ms var(--ease-standard), transform 320ms var(--ease-standard);
}

/* Which layers are on, per state. */
.draw-stage[data-draw-state="ask"] .draw-reveal,
.draw-stage[data-draw-state="shuffle"] .draw-ask-block,
.draw-stage[data-draw-state="shuffle"] .draw-reveal,
.draw-stage[data-draw-state="spread"] .draw-ask-block,
.draw-stage[data-draw-state="spread"] .draw-reveal,
.draw-stage[data-draw-state="picked"] .draw-ask-block,
.draw-stage[data-draw-state="picked"] .draw-reveal {
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
}

.draw-stage[data-draw-state="revealed"] .draw-deck {
    pointer-events: none;
}

.draw-stage[data-draw-state="revealed"] .draw-deck-card.is-picked {
    opacity: 0 !important;
    visibility: hidden;
    transition: none !important;
}

.draw-stage[data-draw-state="revealed"] .draw-prompt-line,
.draw-stage[data-draw-state="revealed"] .draw-ask-block {
    display: none;
}

/* ============================================================
   The experience's flow: one column, the deck at its centre.

   ask → shuffle → spread → picked all share one arrangement, so the press
   never swaps a composition for a different one: the prompt at the top, the
   deck holding the centre at a reserved height, the whisper and the press
   under it.

   Why the deck is `position: relative` here. draw-deck.css parks the 78-card
   box absolutely (`top: auto`, no height) so the fan cannot push the sentence
   above it or the answer below it — right for the revealed document, wrong for
   the ask. An absolute box contributes no height, so before a card was picked
   the stage had a sentence, a button and a large emptiness where the deck
   should have been, and `.draw-note` hung in it. The box now holds the fan's
   own height in the four states before the answer, and the fan opens into
   space that was already reserved: zero jump, zero overlap.

   Why the height is fixed rather than intrinsic. The gathered deck is about
   9px of edge; the fan is 260px tall. An intrinsic box would collapse in ask
   and then grow under the visitor as the cards opened, moving the button and
   the note down mid-gesture.
   ============================================================ */

.draw-stage--experience {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
}

.draw-stage--experience .draw-prompt-line,
.draw-stage--experience .draw-ask-block,
.draw-stage--experience .draw-deck-whisper {
    width: 100%;
    flex: 0 0 auto;
}

/*
 * The reveal is a layer, not a column item, until it is the answer. In the four
 * states before `revealed` it is invisible but still laid out — a whole
 * reading's worth of height inside a centred column would push the deck off
 * centre. Taking it out of flow costs nothing: nothing measures it until the
 * line is seated, and the line is only seated at `revealed`.
 */
.draw-stage--experience:not([data-draw-state="revealed"]) .draw-reveal {
    position: absolute;
    inset: 0;
    pointer-events: none;
}

/*
 * The deck box in the ritual states (ask, shuffle, spread, picked).
 *
 * Scoped to all four states so the gathered stack in ask/shuffle and the apex
 * of the fan in spread share the exact same top anchor — zero jump when
 * pressing Begin.
 */
.draw-stage--experience:not([data-draw-state="revealed"]) .draw-deck[data-draw-deck] {
    position: relative;
    left: auto;
    right: auto;
    top: auto;
    bottom: auto;
    width: 100%;
    height: clamp(190px, 26vw, 250px);
    aspect-ratio: auto;
    flex: 0 0 auto;
}

.draw-stage--experience:not([data-draw-state="revealed"]) .draw-deck[data-draw-deck] .draw-deck-card {
    top: 12%;
}

/*
 * The resting deck, in ask.
 *
 * Seventy-eight backs gathered at --deck-p 0, with the thickness the stack
 * already draws — and one soft shadow breathing behind it, so the visitor is
 * looking at a deck on a table rather than at a button in whitespace. It is not
 * a control in this state: pointer-events is none, and draw-deck.js only treats
 * the fan as the pick surface once the state is `spread`.
 */
.draw-stage--experience[data-draw-state="ask"] .draw-deck[data-draw-deck] {
    --deck-p: 0;
    opacity: 1;
    visibility: visible;
    pointer-events: none;
}

.draw-stage--experience[data-draw-state="ask"] .draw-deck[data-draw-deck]::before {
    content: "";
    position: absolute;
    left: 50%;
    top: 12%;
    width: var(--deck-card-w);
    aspect-ratio: var(--card-ratio);
    transform: translateX(-50%);
    border-radius: var(--radius-sm);
    box-shadow: var(--shadow-lg);
    animation: draw-deck-rest 7s ease-in-out infinite;
    pointer-events: none;
}

@keyframes draw-deck-rest {
    0%, 100% { opacity: .5; }
    50%      { opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
    .draw-stage--experience[data-draw-state="ask"] .draw-deck[data-draw-deck]::before {
        animation: none;
        opacity: .75;
    }
}

/*
 * The whisper under the fan.
 *
 * Present in every state so its line is part of the reserved height and the
 * press does not move when it appears; visible only in `spread`, the one state
 * in which the fan is the control. It is text, not a tooltip — a tooltip needs
 * a pointer and the fan is used with a finger as often as a mouse.
 */
.draw-deck-whisper {
    margin: var(--space-4) 0 0;
    min-height: 1.6em;
    font: 500 var(--text-xs)/1.6 var(--font-mono);
    letter-spacing: var(--tracking-label);
    color: var(--meta);
    text-align: center;
    opacity: 0;
    transition: opacity var(--motion-base) var(--ease-standard);
    pointer-events: none;
}

.draw-stage[data-draw-state="spread"] .draw-deck-whisper { opacity: 1; }

/* Out of the document once the answer arrives — the whisper belongs to the fan,
   and at `revealed` the fan is gone. `display: none` rather than opacity 0 so it
   does not leave a line of empty space above the reading. */
.draw-stage[data-draw-state="revealed"] .draw-deck-whisper { display: none; }

/* The answer is a document again: the column is only for the ritual. */
.draw-stage--experience[data-draw-state="revealed"] {
    display: block;
}


/*

/*
 * The experience takes the viewport. The hero shrinks to one quiet row above the
 * place where the deck will stand, and the stage itself is exactly as tall as
 * the visitor's visible window (less a small top margin, so the wordmark sits
 * somewhere to look up at). That is what the rest of the layout was waiting
 * for: with everything in its place the deck lands at viewport centre on load,
 * and the prompt above it, and no scroll is required before any state.
 *
 * Reversed at the moment the answer arrives, when the document takes over and
 * the reading scrolls.
 */

.draw-page .page-hero {
    /* One short row: eyebrow + lede. The title is hidden in the experience
       — it would be the third time the visitor reads the same word, and the
       page is about the gesture now, not about the page. */
    margin-bottom: var(--space-10);
    /*
     * Centred on the same axis as the stage.
     *
     * The editorial default is a left edge at 72ch, which is right for a page
     * of prose. This page is not prose: the deck, the press and the answer are
     * all on the centre line, so a hero pinned to the far left read as a
     * layout that had slipped rather than as an editorial margin.
     */
    max-width: 44rem;
    margin-inline: auto;
    text-align: center;
}

.draw-page .page-hero .page-lede { margin-inline: auto; }

.draw-page .page-hero-title { display: none; }

/* During the experience the hero's lede ("一个问题，一张牌。") sits above
   the press; it is the page's own orientation. In the revealed state the
   reading has its own lede (the .draw-ask sentence), and the hero's lede
   becomes a second, contradicting orientation line. Hide the whole hero
   then — the visitor came here to read the card, not to be told what
   page they are on.

   Two writers put this class on the article and they agree: assets/draw.js
   toggles it when the experience reaches `revealed`, and page-draw.php writes
   it server-side when the answer arrives as a link. The second one was
   missing until 2026-09-24, so a shared link showed the hero *and* the
   reading — the same duplication, on the one path where the reading is the
   whole page. Wallance: 「返回主页上面的字我都不要」.

   What it removes is the eyebrow (01 塔罗 & 阿卡西记录 · TAROT & AKASHIC, which
   the header already says one line above) and the lede. The page then opens on
   the way back and the sentence the line leaves from, and nothing else. */
.draw-page.draw-page--revealed .page-hero { display: none; }

.draw-stage--experience {
    position: relative;
    width: 100%;
    max-width: min(92vw, 960px);
    margin-inline: auto;
    min-height: min(72dvh, 620px);
    padding-block: var(--space-8) var(--space-16);
}

.draw-stage--experience[data-draw-state="revealed"] {
    min-height: 0;
}


/* The reveal is a document again, and it scrolls. It returns to the flow the
   moment the state is revealed, so the stage can grow to fit the reading.
   `relative`, not `static`: the way back is positioned against it. */
.draw-stage--experience[data-draw-state="revealed"] .draw-reveal {
    position: relative;
}
