/* ═══════════════════════════════════════════
   years-in-order — beat 4: the recipient lays the fallen years into a road
   of light. Every class and keyframe is prefixed `years-in-order-`.
   Play-state classes (--landed, --drawn, --live, --traced, …) sit on the
   persistent elements the HTML ships; per-item classes (slot --lit, photo
   --gone) are re-applied by boot from the module's state.
   ═══════════════════════════════════════════ */

.years-in-order-container {
    position: absolute;
    inset: 0;
    display: grid;
    grid-template-rows: minmax(0, 1fr) auto;
    row-gap: 10px;
    /* Top: below the masthead name, measured at entry (--years-in-order-top).
       Bottom: the screen-space band (copy / hint + button), plus the lane the
       badge guard lifts the badge into above that band, so the lifted badge
       never lands on the tray. */
    padding:
        var(--years-in-order-top, calc(env(safe-area-inset-top, 0px) + 58px))
        16px
        calc(env(safe-area-inset-bottom, 0px) + var(--years-in-order-ui-bottom) + var(--years-in-order-band) + var(--years-in-order-lane));
    font-family: var(--font-body);
    color: var(--text-primary);
    --years-in-order-thumb: min(34vw, 19vh, 210px);
    --years-in-order-node: 56px;               /* set in px by the road layout */
    --years-in-order-ui-bottom: 18px;
    --years-in-order-band: 68px;               /* hint line + 44 px button; the copy lines fit inside it */
    --years-in-order-lane: 44px;               /* the badge (~29 px) + the guard's 8 px gap, with room to spare */
}

/* Entry states are applied instantly (prepare), never animated in. */
.years-in-order-instant,
.years-in-order-instant * {
    transition: none !important;
    animation: none !important;
}

/* ───────── Screen space: the copy band and the hint (moved into #stage) ─────────
   Opacity only once visible: nothing here travels, so the badge guard can
   settle on it. Shown only while this beat is the active screen. */
.years-in-order-ui {
    position: absolute;
    left: 0;
    right: 0;
    bottom: calc(env(safe-area-inset-bottom, 0px) + 18px);
    z-index: 5;
    display: grid;
    align-items: end;
    justify-items: center;
    min-height: 68px;
    padding: 0 16px;
    font-family: var(--font-body);
    color: var(--text-primary);
    pointer-events: none;
}

.reveel-stage:not(:has(#screen-years-in-order.active)) > .years-in-order-ui { display: none; }

.years-in-order-lines,
.years-in-order-hint { grid-area: 1 / 1; }

.years-in-order-lines {
    display: grid;
    grid-template-areas: 'a' 'b';
    justify-items: center;
    row-gap: 0.3rem;
    text-align: center;
    padding-bottom: 6px;
}

.years-in-order-line {
    margin: 0;
    font: 600 clamp(1.1rem, 5vw, 1.6rem)/1.2 var(--font-display);
    color: var(--text-primary);
    text-wrap: balance;
    text-shadow: 0 0 22px rgba(232, 168, 124, 0.3);
    /* Not 0: the badge guard skips opacity-0 text, and it only re-measures on
       the class flip, so a line fading in from 0 sat under the badge for its
       whole fade. At 0.01 it is invisible and already an obstacle. */
    opacity: 0.01;
    transition: opacity 1s var(--ease-silk);
}

.years-in-order-line-a { grid-area: a; }

.years-in-order-line-b {
    grid-area: b;
    color: var(--accent-warm-bright);
    font-size: clamp(1rem, 4.4vw, 1.35rem);
}

.years-in-order-line.years-in-order-line--on { opacity: 1; }
.years-in-order-line.years-in-order-line--off { opacity: 0.01; }

/* ───────── The road ───────── */
.years-in-order-road {
    position: relative;
    z-index: 1;
    min-height: 0;
    transform-origin: 50% 40%;
    transition: transform 6s var(--ease-drift), opacity 6s var(--ease-drift);
}


.years-in-order-svg {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    overflow: visible;
    pointer-events: none;
}

.years-in-order-base,
.years-in-order-thread,
.years-in-order-trace,
.years-in-order-trace-halo,
.years-in-order-comet {
    fill: none;
    stroke-linecap: round;
    stroke-linejoin: round;
}

/* The unlit road: a faint line that draws itself in at 1.2 s. */
.years-in-order-base {
    stroke: var(--slot-empty);
    stroke-width: 1.2;
    stroke-dasharray: 100 100;
    stroke-dashoffset: 100;
    transition: stroke-dashoffset 1.8s var(--ease-expo-out);
}

.years-in-order-road--drawn .years-in-order-base { stroke-dashoffset: 0; }

/* A gold thread between two lit neighbours (700 ms, after the snap). */
.years-in-order-thread {
    stroke: var(--thread);
    stroke-width: 2;
    stroke-dasharray: 100 100;
    stroke-dashoffset: 100;
}

.years-in-order-thread.years-in-order-thread--on { stroke-dashoffset: 0; }

/* The exit: the whole road traced end to end in one run of light. */
.years-in-order-trace,
.years-in-order-trace-halo {
    stroke-dasharray: 100 100;
    stroke-dashoffset: 100;
    transition: stroke-dashoffset 3s var(--ease-silk);
}

.years-in-order-trace { stroke: var(--light-core); stroke-width: 1.6; }
.years-in-order-trace-halo { stroke: var(--accent-warm-glow); stroke-width: 7; opacity: 0.55; }

.years-in-order-road--traced .years-in-order-trace,
.years-in-order-road--traced .years-in-order-trace-halo { stroke-dashoffset: 0; }

/* The light sweep along the ribbon: a bright head riding the trace. */
.years-in-order-comet {
    stroke: var(--text-primary);
    stroke-width: 4;
    stroke-dasharray: 5 200;
    stroke-dashoffset: 5;
    opacity: 0;
}

.years-in-order-road--comet .years-in-order-comet {
    animation: years-in-order-comet 3s var(--ease-silk) forwards;
}

@keyframes years-in-order-comet {
    0% { stroke-dashoffset: 5; opacity: 0; }
    8% { opacity: 1; }
    88% { opacity: 1; }
    100% { stroke-dashoffset: -100; opacity: 0; }
}

/* ───────── Slots: a star, its medallion, its chime ring, its label ───────── */
.years-in-order-slots { position: absolute; inset: 0; }

.years-in-order-slot {
    position: absolute;
    width: calc(var(--years-in-order-col, 80px) - 4px);
    min-width: 44px;
    min-height: 44px;
    margin: 0;
    padding: 0 0 4px;
    border: 0;
    background: none;
    color: inherit;
    font: inherit;
    cursor: pointer;
    display: grid;
    justify-items: center;
    align-content: start;
    row-gap: 4px;
    transform: translate(-50%, calc(var(--years-in-order-node) * -0.5));
    -webkit-tap-highlight-color: transparent;
    touch-action: manipulation;
}

.years-in-order-slot:focus-visible {
    outline: 2px solid var(--focus-ring);
    outline-offset: 2px;
    border-radius: 12px;
}

.years-in-order-medal {
    position: relative;
    display: block;
    width: var(--years-in-order-node);
    height: var(--years-in-order-node);
    opacity: 0;
}

/* Rest states only. Every per-item move in this beat (the stagger-ins, the
   snap, the chime, the threads, the brightening) is a Web Animation started
   from JS on the same class flip: those fire no transitionend/animation
   events and write no attributes, so ten photos never wake the page-wide
   badge guard frame after frame. CSS transitions stay on the few one-off,
   whole-layer moves. */
.years-in-order-road--drawn .years-in-order-medal { opacity: 1; }

.years-in-order-aura,
.years-in-order-star,
.years-in-order-node,
.years-in-order-ring {
    position: absolute;
    border-radius: 50%;
    pointer-events: none;
}

.years-in-order-aura {
    inset: -35%;
    background: radial-gradient(circle, var(--halo) 0%, var(--halo-far) 45%, transparent 70%);
    opacity: 0;
}

/* An unlit star: a hairline ring with a point of light. */
.years-in-order-star {
    inset: 22%;
    border: 1px solid var(--slot-empty);
    background: radial-gradient(circle, var(--slot-empty) 0 16%, transparent 22%);
}

.years-in-order-road--choosing .years-in-order-slot:not(.years-in-order-slot--lit) .years-in-order-star,
.years-in-order-slot.years-in-order-slot--magnet .years-in-order-star {
    border-color: var(--gilt-line-strong);
}

.years-in-order-slot.years-in-order-slot--magnet .years-in-order-star { transform: scale(1.35); }
.years-in-order-slot.years-in-order-slot--magnet .years-in-order-aura { opacity: 0.8; }

/* The placed year: a centred cover-cropped medallion with a gilt ring. */
.years-in-order-node {
    inset: 0;
    overflow: hidden;
    background: var(--bg-elevated);
    box-shadow: 0 0 0 1.5px var(--gilt-line-strong), var(--photo-star-glow);
    opacity: 0;
}

.years-in-order-node img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center;
}

.years-in-order-slot--lit .years-in-order-node { opacity: 1; }
.years-in-order-slot--lit .years-in-order-star { opacity: 0; }
.years-in-order-slot--lit { cursor: default; }

/* The visual chime: a ring of light expanding from the node (900 ms). */
.years-in-order-ring {
    inset: 0;
    border: 1.5px solid var(--chime-ring);
    opacity: 0;
}


.years-in-order-label {
    /* Shown whole, never clipped or ellipsised: up to 3 lines across the
       slot's column; the road layout reserves those 3 lines under every star. */
    display: block;
    width: 100%;
    overflow: visible;
    overflow-wrap: anywhere;
    font: 500 0.64rem/1.15 var(--font-body);
    letter-spacing: 0.06em;
    text-transform: uppercase;
    text-align: center;
    color: var(--text-secondary);
    opacity: 0;
}

.years-in-order-road[data-rows="3"] .years-in-order-label { font-size: 0.58rem; letter-spacing: 0.04em; }

.years-in-order-road--drawn .years-in-order-label { opacity: 0.62; }
.years-in-order-road--drawn .years-in-order-slot--lit .years-in-order-label {
    opacity: 1;
    color: var(--accent-warm-bright);
}

/* Never failable: a wrong drop makes the right slot breathe once… */
.years-in-order-slot--breathe .years-in-order-star {
    animation: years-in-order-breathe 1.2s var(--ease-breath) 1;
}

@keyframes years-in-order-breathe {
    0%, 100% { transform: scale(1); border-color: var(--slot-empty); }
    50% { transform: scale(1.4); border-color: var(--gilt-line-strong); }
}

/* …after 12 s idle, the next correct slot glows (the delay is the idle
   timer; flipping --flip swaps to an identical keyframe, which restarts it
   on every interaction, with no JS timer)… */
.years-in-order-road--live .years-in-order-slot--next .years-in-order-aura {
    animation: years-in-order-idle-a 2.4s var(--ease-breath) 12s infinite;
}

.years-in-order-road--live.years-in-order-road--flip .years-in-order-slot--next .years-in-order-aura {
    animation-name: years-in-order-idle-b;
}

/* …and after two misses on the same photo, its slot pulses steadily. */
.years-in-order-road--live .years-in-order-slot.years-in-order-slot--pulse .years-in-order-aura {
    animation: years-in-order-pulse 1.8s var(--ease-breath) infinite;
}

@keyframes years-in-order-idle-a { 0%, 100% { opacity: 0.15; } 50% { opacity: 0.95; } }
@keyframes years-in-order-idle-b { 0%, 100% { opacity: 0.15; } 50% { opacity: 0.95; } }
@keyframes years-in-order-pulse { 0%, 100% { opacity: 0.25; } 50% { opacity: 1; } }

/* Exit: each placed year brightens in order, 0.3 s apart. */
.years-in-order-road--bright .years-in-order-slot--lit .years-in-order-node {
    box-shadow: 0 0 0 1.5px var(--accent-warm-bright), 0 0 22px 6px rgba(242, 196, 160, 0.6);
    filter: brightness(1.18);
}

/* Exit: the path lifts and dims to a faint constellation. */
.years-in-order-road.years-in-order-road--lift {
    transform: translateY(-3vh) scale(0.94);
    opacity: 0.36;
}

.years-in-order-road--lift .years-in-order-slots { opacity: 0.4; transition: opacity 2s var(--ease-silk); }

/* ───────── The tray: the fallen years, stacked and shuffled ───────── */
.years-in-order-tray {
    position: relative;
    z-index: 3;
    display: grid;
    place-items: center;
    height: calc(var(--years-in-order-thumb) + 20px);
    touch-action: none;
    visibility: hidden;
}

.years-in-order-tray.years-in-order-tray--landed { visibility: visible; }

/* At rest: in the pile. The fall from the sky is a Web Animation. */
.years-in-order-photo {
    grid-area: 1 / 1;
    position: relative;
    display: block;
    cursor: grab;
    touch-action: none;
    -webkit-tap-highlight-color: transparent;
    -webkit-user-select: none;
    user-select: none;
    transform: translate(var(--years-in-order-fx, 0px), var(--years-in-order-fy, 0px)) rotate(var(--years-in-order-rot, 0deg));
    pointer-events: none;
}

.years-in-order-photo img {
    display: block;
    width: auto;
    height: auto;
    max-width: var(--years-in-order-thumb);
    max-height: var(--years-in-order-thumb);
    border: 1px solid var(--frame);
    box-shadow: var(--frame-shadow);
    -webkit-user-drag: none;
    pointer-events: none;
}

/* The star's light, fading as it lands and becomes a photo (animated in JS). */
.years-in-order-photo-glow {
    position: absolute;
    inset: -12%;
    background: radial-gradient(circle, var(--light-core) 0%, var(--accent-warm-glow) 30%, transparent 66%);
    opacity: 0;
    pointer-events: none;
}

/* The top of the stack lifts slightly: the one in play. */
.years-in-order-tray--ready .years-in-order-photo.years-in-order-photo--top {
    transform: translateY(-12px) rotate(0deg) scale(1.04);
    pointer-events: auto;
}

.years-in-order-tray--ready .years-in-order-photo--top img {
    box-shadow: var(--frame-shadow), 0 0 26px rgba(242, 196, 160, 0.3);
}

.years-in-order-photo--top:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 4px; }

.years-in-order-photo.years-in-order-photo--selected img {
    border-color: var(--accent-warm-bright);
    box-shadow: 0 0 0 2px var(--focus-ring), var(--frame-shadow), 0 0 34px rgba(242, 196, 160, 0.45);
}

.years-in-order-photo.years-in-order-photo--drag {
    cursor: grabbing;
    z-index: 60 !important;
}

/* Placed: gone from the tray (the snap into the slot is a Web Animation). */
.years-in-order-tray .years-in-order-photo.years-in-order-photo--gone {
    opacity: 0;
    pointer-events: none;
    z-index: 60 !important;
}

/* ───────── Hint and the non-drag button ───────── */
.years-in-order-hint {
    display: grid;
    justify-items: center;
    align-content: end;
    row-gap: 8px;
    text-align: center;
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.5s var(--ease-silk), visibility 0s linear 0.5s;
}

.years-in-order-hint.years-in-order-hint--on {
    opacity: 1;
    visibility: visible;
    transition: opacity 0.6s var(--ease-silk);
}

.years-in-order-hint-text {
    margin: 0;
    font: 500 0.78rem/1.3 var(--font-body);
    letter-spacing: 0.22em;
    text-transform: uppercase;
    color: var(--accent-warm);
}

.years-in-order-place {
    min-height: 44px;
    padding: 0.7rem 1.35rem;
    font: 500 0.9rem/1 var(--font-body);
    color: var(--text-primary);
    cursor: pointer;
    background: var(--glass);
    border: 1px solid var(--glass-border-hover);
    border-radius: 999px;
    touch-action: manipulation;
    pointer-events: auto;
}

.years-in-order-place:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 3px; }

/* ───────── The glint that descends: the envelope-to-be ───────── */
.years-in-order-glint {
    position: absolute;
    left: 50%;
    top: 50%;
    width: 12px;
    height: 12px;
    margin: -6px 0 0 -6px;
    border-radius: 50%;
    background: radial-gradient(circle, var(--light-core) 0%, var(--accent-warm-bright) 45%, var(--accent-warm-deep) 100%);
    box-shadow: 0 0 16px 5px var(--accent-warm-glow), 0 0 54px 18px rgba(196, 138, 96, 0.25);
    opacity: 0;
    transform: translateY(-54vh) scale(0.6);
    transition: transform 4s var(--ease-stage), opacity 1.2s var(--ease-silk);
    pointer-events: none;
}

.years-in-order-glint.years-in-order-glint--on { opacity: 1; transform: none; }

/* Looping ornaments are parked while the hold is off (see --live above). */


/* ───────── Reduced motion: every step still plays, calmly ───────── */
@media (prefers-reduced-motion: reduce) {
    .years-in-order-tray--ready .years-in-order-photo.years-in-order-photo--top { transform: rotate(0deg); }
    .years-in-order-slot--breathe .years-in-order-star { animation: years-in-order-breathe-calm 1.2s var(--ease-breath) 1; }
    .years-in-order-slot.years-in-order-slot--magnet .years-in-order-star { transform: none; }

    .years-in-order-trace,
    .years-in-order-trace-halo { transition-duration: 6s; }
    .years-in-order-comet { display: none; }

    .years-in-order-road.years-in-order-road--lift { transform: none; }
    .years-in-order-glint { transform: none; transition: opacity 2s var(--ease-silk); }
}

@keyframes years-in-order-breathe-calm {
    0%, 100% { border-color: var(--slot-empty); }
    50% { border-color: var(--gilt-line-strong); }
}
