/* =============================================================================
 * Parking scene — styles and choreography for templates/home/_parking_scene.html.twig
 *
 * Two rules govern everything below.
 *
 * 1. Only `transform` and `opacity` are animated. Both are handled off the
 *    layout path, so the loop stays smooth on a mid-range phone. Animating
 *    x/y/width on the SVG instead would re-lay-out the drawing on every frame.
 *
 * 2. The 100% keyframe of every animation is the resting frame: cars parked,
 *    booms down, lamps lit. app.css crushes animation-duration to 0.01ms under
 *    `prefers-reduced-motion: reduce`, and because each animation here declares
 *    `animation-fill-mode: both`, the browser then holds that 100% frame
 *    forever. A visitor who asked for less motion gets a still parking lot that
 *    looks drawn on purpose, not a slow-motion version of the ride.
 *
 * Colour comes from the theme tokens in app.css. The few shades that have no
 * token — asphalt, bay paint, kerb — are declared here for both schemes.
 * ========================================================================== */

.ps-scene {
    /* ---- Light scheme ---------------------------------------------------- */
    --ps-slab: #d6dde0;             /* concrete the bays are painted on        */
    --ps-aisle: #c0cace;            /* the drive aisle, a shade darker         */
    --ps-kerb: #e4e8e6;             /* paved plazas either side of the gates   */
    --ps-line: rgba(255, 255, 255, 0.92);
    --ps-ink: var(--asphalt-900);   /* boom stripes and sign letter, on amber  */
    --ps-post: var(--asphalt-900);  /* sign and gate posts, on pavement        */
    /* Bright amber reads on dark asphalt and disappears on light concrete
     * (1.16:1), so the reserved-bay outline takes the deep variant in light. */
    --ps-reserved: var(--accent-fg);
    --ps-booth: #f2efe7;
    --ps-glass: rgba(255, 255, 255, 0.6);
    --ps-shade: rgba(15, 23, 27, 0.2);

    --ps-car-slate: var(--asphalt-500);
    --ps-car-dusk: var(--asphalt-700);
    --ps-car-pale: #eceff1;
    --ps-car-guest: var(--asphalt-300);

    --ps-tail: #d84315;

    width: 100%;
}

@media (prefers-color-scheme: dark) {
    .ps-scene {
        --ps-slab: #242a2e;
        --ps-aisle: #1a2024;
        --ps-kerb: #2c3338;
        --ps-line: rgba(233, 229, 236, 0.34);
        /* --ps-ink stays near-black because it only ever paints on the amber
         * plate and boom arm, which do not change between schemes. --ps-post
         * paints on the pavement, so it has to move the other way like every
         * other ground colour here — near-black on near-black was a 1.28:1
         * silhouette of nothing. */
        --ps-ink: #0f1417;
        --ps-post: var(--asphalt-300);
        --ps-reserved: var(--primary-500);
        --ps-booth: #333b41;
        --ps-glass: rgba(233, 229, 236, 0.24);
        --ps-shade: rgba(0, 0, 0, 0.28);

        --ps-car-slate: #78909c;
        --ps-car-dusk: #546e7a;
        --ps-car-pale: #b0bec5;
        --ps-car-guest: #8d9aa3;

        --ps-tail: #ff7043;
    }
}

/* viewBox + width:100%, never a pixel height: the drawing scales with its
 * column instead of overflowing it. */
.ps-scene__svg {
    display: block;
    width: 100%;
    height: auto;
    overflow: hidden;               /* keeps a car that has driven off-canvas out */
}

/* ---- Ground ------------------------------------------------------------- */
.ps-slab { fill: var(--ps-slab); }
.ps-aisle { fill: var(--ps-aisle); }
.ps-kerb { fill: var(--ps-kerb); }

.ps-booth__body { fill: var(--ps-booth); }
.ps-booth__window { fill: var(--ps-glass); }
.ps-booth__roof { fill: var(--primary-700); }

.ps-lines path {
    fill: none;
    stroke: var(--ps-line);
    stroke-width: 4;
    stroke-linecap: round;
}

.ps-chevrons path {
    fill: none;
    stroke: var(--ps-line);
    stroke-width: 4;
    stroke-linecap: round;
    stroke-linejoin: round;
    opacity: 0.55;
}

/* The spot the amber car comes back to, so the empty bay reads as reserved
 * rather than as a hole in the drawing. */
.ps-bay-reserved {
    fill: none;
    stroke: var(--ps-reserved);
    stroke-width: 3;
    stroke-dasharray: 10 9;
    opacity: 0.75;
}

/* ---- Sign --------------------------------------------------------------- */
.ps-sign__plate { fill: var(--primary-500); }
.ps-sign__post { fill: var(--ps-post); opacity: 0.55; }

.ps-sign__letter {
    fill: var(--ps-ink);
    font-family: var(--font-sans);
    font-size: 46px;
    font-weight: 800;
}

/* ---- Cars --------------------------------------------------------------- */
/* Each variant sets one custom property; cabin and glass are alpha overlays,
 * so they read correctly on an amber car and on a near-white one alike. */
.ps-car--slate { --ps-body: var(--ps-car-slate); }
.ps-car--dusk { --ps-body: var(--ps-car-dusk); }
.ps-car--pale { --ps-body: var(--ps-car-pale); }
.ps-car--guest { --ps-body: var(--ps-car-guest); }
.ps-car--hero { --ps-body: var(--primary-500); }

.ps-car__body {
    fill: var(--ps-body);
    stroke: var(--ps-shade);
    stroke-width: 1.5;
}

.ps-car__mirror { fill: var(--ps-body); }
.ps-car__cabin { fill: var(--ps-shade); }
.ps-car__glass { fill: var(--ps-glass); }
.ps-car__lamp { fill: var(--primary-100); }
.ps-car__tail { fill: var(--ps-tail); }

/* ---- Gates -------------------------------------------------------------- */
.ps-gate__post { fill: var(--ps-post); }
.ps-gate__arm { fill: var(--primary-500); }
.ps-gate__stripe { fill: var(--ps-ink); }
.ps-gate__lamp { fill: var(--primary-300); }

/* =============================================================================
 * Choreography
 *
 * One 20s loop, four animations, all the same duration so the booms and the
 * cars stay in step. Deliberately no `animation-delay`: the reduced-motion
 * rule in app.css shortens the duration but leaves the delay alone, which
 * would strand an element on its 0% frame for seconds. Every offset is baked
 * into the keyframe percentages instead.
 *
 * The story, per loop:
 *    0%   amber car parked, grey car still off-site
 *    4%   grey car reaches the entry gate, boom lifts, it parks bottom-left
 *   13%   amber car backs out, turns, drives to the exit gate
 *   31%   exit boom lifts, amber car leaves
 *   57%   amber car comes back in, entry boom lifts, it re-parks by 86%
 *   89%   grey car leaves through the exit gate and is off-canvas by 100%
 *
 * The loop closes on itself: 100% is pose-for-pose identical to 0%, so there
 * is no jump on repeat, and it doubles as the still frame.
 * ========================================================================== */

.ps-car--hero,
.ps-car--guest,
.ps-gate__boom {
    /* Explicit and paired on purpose. transform-box: view-box makes
     * transform-origin resolve in viewBox user units, and every animated
     * element sits directly in the root coordinate system — so `0 0` is a
     * car's own centre, and `100px 286px` is exactly the boom's hinge. */
    transform-box: view-box;
    animation-duration: 20s;
    animation-iteration-count: infinite;
    animation-fill-mode: both;
}

.ps-car--hero,
.ps-car--guest {
    transform-origin: 0 0;
    animation-timing-function: ease-in-out;  /* per segment: pull away, cruise, brake */
    will-change: transform;
}

.ps-car--hero { animation-name: ps-drive-hero; }
.ps-car--guest { animation-name: ps-drive-guest; }

/* A boom that pivots in plan view swings aside instead of rising: in a
 * top-down drawing a lifting arm would only foreshorten, and nobody would
 * read it as "open". Same event, legible from this angle. */
.ps-gate__boom {
    animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
}

.ps-gate__boom--in {
    transform-origin: 100px 286px;
    animation-name: ps-gate-in;
}

.ps-gate__boom--out {
    transform-origin: 660px 194px;
    animation-name: ps-gate-out;
}

.ps-gate__lamp {
    animation: ps-lamp 2.4s ease-in-out infinite both;
}

/* The amber car: parked centre-top, out through the exit, back in, re-parked. */
@keyframes ps-drive-hero {
    0%   { transform: translate(400px, 132px) rotate(-90deg); opacity: 1; }
    8%   { transform: translate(400px, 132px) rotate(-90deg); }
    13%  { transform: translate(400px, 240px) rotate(-90deg); }   /* backs into the aisle */
    18%  { transform: translate(400px, 240px) rotate(0deg); }     /* turns to face the exit */
    27%  { transform: translate(600px, 240px) rotate(0deg); }     /* pulls up to the boom */
    31%  { transform: translate(600px, 240px) rotate(0deg); }     /* waits for it to open */
    38%  { transform: translate(900px, 240px) rotate(0deg); opacity: 1; }
    39%  { transform: translate(920px, 240px) rotate(0deg); opacity: 0; }
    41%  { transform: translate(-190px, 240px) rotate(0deg); opacity: 0; }  /* the jump back is hidden */
    43%  { transform: translate(-190px, 240px) rotate(0deg); opacity: 1; }
    52%  { transform: translate(-190px, 240px) rotate(0deg); }
    57%  { transform: translate(36px, 240px) rotate(0deg); }      /* arrives at the entry gate */
    61%  { transform: translate(36px, 240px) rotate(0deg); }
    72%  { transform: translate(400px, 240px) rotate(0deg); }     /* drives to its bay */
    78%  { transform: translate(400px, 240px) rotate(-90deg); }   /* turns into it */
    86%  { transform: translate(400px, 132px) rotate(-90deg); }
    100% { transform: translate(400px, 132px) rotate(-90deg); opacity: 1; }
}

/* The grey car: arrives, parks bottom-left, leaves again near the end of the
 * loop. It only ever uses the aisle while the amber car is elsewhere. */
@keyframes ps-drive-guest {
    0%   { transform: translate(-190px, 240px) rotate(0deg); opacity: 1; }
    4%   { transform: translate(36px, 240px) rotate(0deg); }
    9%   { transform: translate(36px, 240px) rotate(0deg); }
    16%  { transform: translate(208px, 240px) rotate(0deg); }
    21%  { transform: translate(208px, 240px) rotate(90deg); }
    28%  { transform: translate(208px, 348px) rotate(90deg); }
    76%  { transform: translate(208px, 348px) rotate(90deg); }
    80%  { transform: translate(208px, 240px) rotate(90deg); }
    84%  { transform: translate(208px, 240px) rotate(0deg); }
    89%  { transform: translate(600px, 240px) rotate(0deg); }
    91%  { transform: translate(600px, 240px) rotate(0deg); }
    95%  { transform: translate(900px, 240px) rotate(0deg); opacity: 1; }
    96%  { transform: translate(920px, 240px) rotate(0deg); opacity: 0; }
    98%  { transform: translate(-190px, 240px) rotate(0deg); opacity: 0; }
    100% { transform: translate(-190px, 240px) rotate(0deg); opacity: 1; }
}

/* Entry boom: opens for the grey car at 6%, for the amber one at 59%. Both
 * cars sit still while it moves — that beat is what makes the gate look like
 * it is reacting to the car rather than running on a timer of its own. */
@keyframes ps-gate-in {
    0%   { transform: rotate(0deg); }
    2%   { transform: rotate(0deg); }
    6%   { transform: rotate(80deg); }
    17%  { transform: rotate(80deg); }
    20%  { transform: rotate(0deg); }
    56%  { transform: rotate(0deg); }
    59%  { transform: rotate(80deg); }
    70%  { transform: rotate(80deg); }
    73%  { transform: rotate(0deg); }
    100% { transform: rotate(0deg); }
}

/* Exit boom: opens at 31% for the amber car, at 91% for the grey one, and is
 * back down by 99% so the still frame shows a closed gate. */
@keyframes ps-gate-out {
    0%   { transform: rotate(0deg); }
    27%  { transform: rotate(0deg); }
    31%  { transform: rotate(-80deg); }
    40%  { transform: rotate(-80deg); }
    43%  { transform: rotate(0deg); }
    88%  { transform: rotate(0deg); }
    91%  { transform: rotate(-80deg); }
    96%  { transform: rotate(-80deg); }
    99%  { transform: rotate(0deg); }
    100% { transform: rotate(0deg); }
}

@keyframes ps-lamp {
    0%   { opacity: 1; }
    50%  { opacity: 0.4; }
    100% { opacity: 1; }
}

/* =============================================================================
 * Reduced motion
 *
 * app.css already collapses every animation on the site to 0.01ms, which — with
 * `fill-mode: both` above — would leave this drawing on its 100% frame. That is
 * the right frame, but it depends on two files agreeing, so the resting pose is
 * also stated outright here.
 *
 * Note what this rule does NOT do: `animation: none` on its own would drop each
 * car back to its authored position, and the two moving cars are authored at the
 * origin (0,0) with no transform attribute — they would pile up in the top-left
 * corner. Cancelling the animation and setting the pose have to happen together.
 * ========================================================================== */
@media (prefers-reduced-motion: reduce) {
    .ps-car--hero {
        animation: none;
        transform: translate(400px, 132px) rotate(-90deg);
    }

    .ps-car--guest {
        animation: none;
        transform: translate(208px, 348px) rotate(90deg);
    }

    .ps-gate__boom {
        animation: none;
        transform: rotate(0deg);        /* both booms down */
    }

    .ps-gate__lamp {
        animation: none;
        opacity: 1;
    }
}
