/* /praxis/whatsapp-assistent/: a compact hero, one chat per feature (played once when
   it scrolls into view), leaves and bunches sliding in at the section edges,
   and the palm-oil comic fixed at the bottom of the screen, moved by
   js/whatsapp.js. Drawing palette and classes come from scenes.css. */

/* The illustrations (inc/wa-art/) carry their own colours; the line-drawing
   scene contract does not apply to this page (Benedikt, 2026-09-27). */

.wa-main {
    --wa-band-h: 170px;
    padding-bottom: var(--wa-band-h);
    overflow-x: clip;
}

/* ------------------------------------------------------------ layout */

.wa-hero {
    padding: calc(var(--header-h) + clamp(2rem, 5vw, 4rem)) 0 clamp(2.5rem, 5vw, 4rem);
    background: var(--blush);
}

.wa-row {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 22rem);
    align-items: center;
    gap: clamp(2rem, 6vw, 5rem);
}

.wa-feature {
    position: relative;
    padding-block: clamp(3.5rem, 8vw, 6rem);
}

/* Text and phone above the edge decorations. */
.wa-feature .content {
    position: relative;
    z-index: 1;
}

.wa-feature:nth-of-type(odd) {
    background: var(--blush);
}

.wa-feature--flip .wa-row {
    grid-template-columns: minmax(0, 22rem) minmax(0, 1fr);
}

.wa-feature--flip .wa-phone {
    order: -1;
}

.wa-hero h1 {
    margin: 0 0 1rem;
    text-wrap: balance;
}

.wa-feature h2 {
    margin: 0 0 1rem;
    font-size: clamp(1.9rem, 3.2vw, 2.6rem);
    line-height: 1.1;
    letter-spacing: -.02em;
    text-wrap: balance;
}

.wa-lead {
    max-width: 46ch;
    margin: 0 0 1.25rem;
    font-size: clamp(1.1rem, 1.5vw, 1.25rem);
    font-weight: 500;
    line-height: 1.5;
    color: var(--ink-2);
    text-wrap: pretty;
}

.wa-points {
    display: grid;
    gap: 1rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

.wa-points li {
    padding-left: .9rem;
    border-left: 3px solid var(--peach);
}

.wa-points h3 {
    margin: 0 0 .2rem;
    font-size: 1.0625rem;
    line-height: 1.3;
}

.wa-points p {
    max-width: 60ch;
    margin: 0;
    font-size: 1rem;
    line-height: 1.55;
    color: var(--ink-2);
}

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

.wa-phone {
    position: relative;
    width: 100%;
    max-width: 22rem;
    margin: 0 auto;
    overflow: hidden;
    border: 10px solid var(--navy);
    border-radius: 34px;
    background: var(--white);
    box-shadow: var(--shadow-2);
    font-size: .95rem;
    line-height: 1.4;
}

.wa-phone::before {
    content: "";
    position: absolute;
    top: 6px;
    left: 50%;
    width: 64px;
    height: 12px;
    margin-left: -32px;
    border-radius: 6px;
    background: var(--navy);
}

.wa-phone-head {
    display: flex;
    align-items: center;
    gap: .6rem;
    padding: 1.6rem 1rem .7rem;
    border-bottom: 1px solid var(--line);
}

.wa-avatar {
    flex: none;
    width: 2.2rem;
    height: 2.2rem;
    border-radius: 50%;
    background: var(--ok) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='2' stroke-linecap='round'%3E%3Cpath d='M12 21V11M12 11C9 7 5 7 3 9M12 11c3-4 7-4 9-2M12 11C11 7 8 4 5 4M12 11c1-4 4-7 7-7'/%3E%3C/svg%3E") center / 62% no-repeat;
}

.wa-chat-name {
    display: flex;
    flex-direction: column;
    font-weight: 700;
    line-height: 1.2;
}

.wa-chat-status {
    font-size: .8rem;
    font-weight: 500;
    color: var(--ink-3);
}

.wa-chat {
    position: relative;
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    gap: .55rem;
    margin: 0;
    padding: .9rem .8rem 1.1rem;
    list-style: none;
    background: var(--blush);
}

.wa-msg {
    max-width: 86%;
    padding: .55rem .75rem;
    border-radius: 1rem;
    font-size: .92rem;
    box-shadow: 0 1px 0 rgba(25, 22, 51, .08);
}

/* The farmer's own messages on the right, the assistant's on the left. */
.wa-msg--in {
    align-self: flex-end;
    border-bottom-right-radius: .3rem;
    background: var(--peach-100);
}

.wa-msg--out {
    align-self: flex-start;
    border-bottom-left-radius: .3rem;
    background: var(--white);
}

/* An earlier line of the same conversation, for context. Dimmed by colour,
   not opacity: the bubble keeps its 55 % tint, the text is --ink-3, 4.7:1
   (the faded navy it had was 3.7:1). */
.wa-msg--earlier {
    background: rgba(253, 233, 220, .55); /* --peach-100 at 55 % */
    box-shadow: 0 1px 0 rgba(25, 22, 51, .044);
    color: var(--ink-3);
}

.wa-msg-text,
.wa-msg-source,
.wa-msg-from,
.wa-msg-rewrite,
.wa-msg-photo {
    display: block;
}

.wa-msg-from {
    margin-bottom: .15rem;
    font-size: .8rem;
    font-weight: 700;
    color: var(--blue);
}

.wa-msg-source {
    margin-top: .35rem;
    font-size: .8rem;
    color: var(--ink-3);
}

.wa-msg-photo {
    margin: -.2rem -.3rem .45rem;
    overflow: hidden;
    border-radius: .6rem;
}

.wa-msg-photo svg {
    display: block;
    width: 100%;
    height: auto;
}

/* What the rewrite model makes of a follow-up. The farmer never sees it, so
   it hangs under the bubble as an annotation. */
.wa-msg-rewrite {
    margin: .5rem -.2rem -.1rem;
    padding: .35rem .55rem;
    border-radius: .6rem;
    background: var(--navy);
    font-size: .8rem;
    font-weight: 600;
    color: var(--white);
}

.wa-msg-rewrite-label {
    font-weight: 500;
    color: var(--peach);
}

.wa-typing {
    position: absolute;
    top: 0;
    left: .8rem;
    display: flex;
    visibility: hidden;
    gap: .3rem;
    padding: .7rem .85rem;
    border-radius: 1rem 1rem 1rem .3rem;
    background: var(--white);
}

.wa-typing span {
    width: .5rem;
    height: .5rem;
    border-radius: 50%;
    background: var(--ink-3);
}

/* Played by js/whatsapp.js whenever the phone scrolls into view: lines
   wait, the farmer's pops in, the assistant "types", its answer pops in.
   Waiting lines keep their space, so the phone has its full size from the
   start and never grows; the typing dots float where the answer will be. */
html.js .wa-phone:not(.is-done) .wa-msg:not(.is-shown) {
    visibility: hidden;
}

.wa-phone.is-typing .wa-typing {
    visibility: visible;
}

.wa-phone.is-typing .wa-typing span {
    animation: wa-dot .6s ease-in-out infinite;
}

.wa-typing span:nth-child(2) { animation-delay: .1s; }
.wa-typing span:nth-child(3) { animation-delay: .2s; }

.wa-msg.is-new {
    animation: wa-pop .34s cubic-bezier(.3, 1.3, .5, 1) both;
}

.wa-msg--in.is-new { transform-origin: 100% 100%; }
.wa-msg--out.is-new { transform-origin: 0 100%; }

@keyframes wa-pop {
    from { opacity: 0; transform: scale(.7) translateY(.6rem); }
}

@keyframes wa-dot {
    50% { transform: translateY(-.25rem); opacity: .5; }
}

/* ------------------------------------------------------------ section edges */

.wa-deco {
    --wa-deco-w: clamp(110px, 10vw, 150px);
    position: absolute;
    top: 18%;
    width: var(--wa-deco-w);
    pointer-events: none;
    opacity: 0;
    transition: transform .9s cubic-bezier(.2, .8, .2, 1), opacity .5s ease;
}

.wa-deco svg {
    display: block;
    width: 100%;
    height: auto;
}

/* Each leaf stays in the side gutter (screen edge to text column), clear of
   the heading, the text and the chat. Below about 1440 px the gutter is
   narrower than a leaf, so the leaf slides further out of the screen. */
.wa-deco--left {
    left: min(-1.75rem, max(var(--gutter), (100vw - var(--content)) / 2) - var(--wa-deco-w) - .5rem);
    transform: translateX(-120%) rotate(-40deg);
}

.wa-deco--right {
    top: auto;
    bottom: 14%;
    right: min(-1rem, max(var(--gutter), (100vw - var(--content)) / 2) - var(--wa-deco-w) - .5rem);
    transform: translateX(120%) rotate(40deg) scaleX(-1);
}

.wa-deco.is-in {
    opacity: 1;
}

.wa-deco--left.is-in { transform: translateX(0) rotate(-12deg); }
.wa-deco--right.is-in { transform: translateX(0) rotate(14deg) scaleX(-1); }

/* Once in, they sway a little, pivoting at their stem end. */
.wa-deco.is-in svg {
    transform-origin: 8% 90%;
    animation: wa-sway 4.8s ease-in-out .9s infinite alternate;
}

.wa-deco--right.is-in svg {
    animation-duration: 5.6s;
}

.wa-main.is-paused .wa-deco svg,
.wa-feature.is-far .wa-deco svg {
    animation-play-state: paused;
}

@keyframes wa-sway {
    from { transform: rotate(-4deg) translateY(0); }
    to { transform: rotate(5deg) translateY(-4px); }
}

/* ------------------------------------------------------------ the comic band */

.wa-band {
    position: fixed;
    right: 0;
    bottom: 0;
    left: 0;
    z-index: 40;
    height: var(--wa-band-h);
    overflow: hidden;
    pointer-events: none;
    /* The band's work stays inside it: nothing in it can re-layout the page. */
    contain: strict;
    transform: translateY(105%);
    transition: transform .45s cubic-bezier(.2, .8, .2, 1);
}

html:not(.js) .wa-band {
    display: none;
}

html:not(.js) .wa-main {
    padding-bottom: 0;
}

.wa-band.is-on {
    transform: none;
}

.wa-layer {
    position: absolute;
    top: 0;
    left: 0;
    width: calc(var(--wa-band-h) * 6400 / 170); /* viewBox -1200..5200 */
    height: 100%;
    will-change: transform;
}

/* Distance reads as haze, and it keeps the page text behind legible. */
.wa-layer[data-f="0.35"] { opacity: .5; }
.wa-layer[data-f="0.6"] { opacity: .7; }

/* The strips are far wider than the screen: opt out of the global svg cap. */
.wa-layer-svg {
    display: block;
    width: 100%;
    max-width: none;
    height: 100%;
}

/* Stage 2: js/whatsapp.js scales each .wa-grow palm as the band passes. */
.wa-grow {
    transform: scale(.22);
}

/* The figure in the middle, flipped to face the way the band moves. */
.wa-actor {
    --dir: 1;
    position: absolute;
    bottom: 0;
    left: 50%;
    width: calc(var(--wa-band-h) * 200 / 170);
    height: 100%;
    margin-left: calc(var(--wa-band-h) * -100 / 170);
    transform: scaleX(var(--dir));
    transition: transform .3s cubic-bezier(.3, 1.4, .5, 1);
}

.wa-actor-item {
    position: absolute;
    inset: 0;
    opacity: 0;
    transition: opacity .3s ease;
}

.wa-actor-item.is-active {
    opacity: 1;
}

.wa-actor-svg {
    display: block;
    width: 100%;
    height: 100%;
}

.wa-actor.is-moving .wa-leg--a { animation: wa-step var(--step, .4s) ease-in-out infinite alternate; }
.wa-actor.is-moving .wa-leg--b { animation: wa-step var(--step, .4s) ease-in-out infinite alternate-reverse; }
.wa-actor.is-moving .wa-wheel { animation: wa-roll calc(var(--step, .4s) * 2) linear infinite; }
.wa-actor.is-moving .wa-body { animation: wa-bob calc(var(--step, .4s) * 1.2) ease-in-out infinite alternate; }
.wa-actor.is-moving .wa-arm--a { animation: wa-swing var(--step, .4s) ease-in-out infinite alternate-reverse; }
.wa-actor.is-moving .wa-arm--b { animation: wa-swing var(--step, .4s) ease-in-out infinite alternate; }

/* Standing still: the figure breathes, the engine idles. */
.wa-actor:not(.is-moving) .wa-actor-svg { animation: wa-breathe 2.4s ease-in-out infinite; }

@keyframes wa-step { from { transform: rotate(-22deg); } to { transform: rotate(22deg); } }
@keyframes wa-swing { from { transform: rotate(-14deg); } to { transform: rotate(14deg); } }
@keyframes wa-roll { to { transform: rotate(360deg); } }
@keyframes wa-bob { to { transform: translateY(-1.5px); } }
@keyframes wa-breathe { 50% { transform: translateY(-1px); } }

/* Ambient life in the panorama: rain on the young palms, bunches riding the
   conveyor, the mill's gear, oil in the pipe. */
.wa-rain { animation: wa-rain .9s linear infinite; }
.wa-belt { animation: wa-belt 2.4s linear infinite; }
.wa-gear { animation: wa-roll 6s linear infinite; }
.wa-flow { animation: wa-flow 1.8s linear infinite; }
.wa-puff--3 { animation-delay: .8s; }

@keyframes wa-rain {
    from { transform: translateY(-4px); opacity: 0; }
    30% { opacity: 1; }
    to { transform: translateY(8px); opacity: 0; }
}

/* Up the conveyor, along its 60:52 slope, into the mill. */
@keyframes wa-belt {
    from { transform: translate(0, 0); opacity: 0; }
    12% { opacity: 1; }
    85% { opacity: 1; }
    to { transform: translate(60px, -52px); opacity: 0; }
}

@keyframes wa-flow {
    to { transform: translateX(40px); }
}

/* Paused by the visitor, or asleep while off screen or in a hidden tab
   (js/whatsapp.js): its loops would otherwise repaint it on every frame. */
.wa-band.is-paused *,
.wa-band.is-paused *::before,
.wa-band.is-asleep *,
.wa-band.is-asleep *::before {
    animation-play-state: paused !important;
}

/* The pause/play control, bottom right above the band's ground. Always in
   the tab order: it shows with the band, and whenever it has keyboard focus. */
.wa-band-pause {
    position: fixed;
    right: .75rem;
    bottom: calc(var(--wa-band-h) - 2.75rem - .75rem);
    z-index: 41;
    display: grid;
    place-items: center;
    width: 2.75rem;
    height: 2.75rem;
    border: 1px solid var(--line);
    border-radius: 50%;
    background: rgba(255, 255, 255, .9);
    color: var(--navy);
    cursor: pointer;
    opacity: 0;
    transition: opacity .3s ease;
}

.wa-band-pause[hidden] {
    display: none;
}

.wa-band-pause:not(.is-on) {
    pointer-events: none;
}

/* :focus-visible, not :focus: after a click it would stay up over the footer. */
.wa-band-pause.is-on,
.wa-band-pause:focus-visible {
    opacity: 1;
}

.wa-band-pause:focus-visible {
    outline: 3px solid var(--navy);
    outline-offset: 2px;
}

.wa-band-pause svg {
    width: 1.1rem;
    height: 1.1rem;
    fill: none;
    stroke: currentColor;
    stroke-width: 3;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.wa-band-pause .wa-icon-play,
.wa-band-pause[aria-pressed="true"] .wa-icon-pause {
    display: none;
}

.wa-band-pause[aria-pressed="true"] .wa-icon-play {
    display: inline;
}

/* Ambient life in the panorama. */
.wa-puff {
    fill: rgba(25, 22, 51, .12);
    animation: wa-puff 3.2s ease-out infinite;
    transform-box: fill-box;
    transform-origin: center;
}

.wa-puff--2 { animation-delay: 1.6s; }

.wa-fall {
    animation: wa-fall 5s ease-in infinite;
}

.wa-drop {
    animation: wa-drip 2.6s ease-in infinite;
}

@keyframes wa-puff {
    from { transform: translate(0, 6px) scale(.5); opacity: 0; }
    30% { opacity: 1; }
    to { transform: translate(8px, -14px) scale(1.4); opacity: 0; }
}

@keyframes wa-fall {
    0%, 55% { transform: none; opacity: 1; }
    80% { transform: translateY(76px); opacity: 1; }
    100% { transform: translateY(76px); opacity: 0; }
}

@keyframes wa-drip {
    0% { transform: translateY(-6px); opacity: 0; }
    20% { opacity: 1; }
    80% { transform: translateY(20px); opacity: 1; }
    100% { transform: translateY(24px); opacity: 0; }
}

/* Leaves drifting through the band. */
.wa-band-leaf {
    position: absolute;
    top: 18%;
    right: -60px;
    width: calc(var(--wa-band-h) * .26);
    animation: wa-leaf 16s linear infinite;
}

.wa-band-leaf--2 {
    top: 42%;
    animation-duration: 22s;
    animation-delay: -9s;
}

.wa-band-leaf svg {
    display: block;
    width: 100%;
    height: auto;
}

@keyframes wa-leaf {
    from { transform: translateX(0) rotate(0); }
    25% { transform: translateX(-25vw) translateY(14px) rotate(40deg); }
    50% { transform: translateX(-50vw) translateY(-6px) rotate(-10deg); }
    75% { transform: translateX(-75vw) translateY(12px) rotate(30deg); }
    to { transform: translateX(calc(-100vw - 120px)) rotate(0); }
}

/* ------------------------------------------------------------ how it works */

.wa-how {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: 1.25rem;
    margin: 0;
    padding: 0;
    list-style: none;
    counter-reset: wa-how;
}

.wa-how li {
    counter-increment: wa-how;
}

/* Four steps: 2 × 2 from 640 px, as the site grid wants for four items
   (WEBSITE_DESIGN.md §5). auto-fit made it 3+1 at 1024 px. */
@media (min-width: 640px) {
    .wa-how {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

.wa-how h3::before {
    content: counter(wa-how);
    display: inline-grid;
    place-items: center;
    width: 2rem;
    height: 2rem;
    margin-right: .6rem;
    border-radius: 50%;
    background: var(--peach-100);
    font-size: 1rem;
    color: var(--navy);
    vertical-align: .1em;
}

/* ------------------------------------------------------------ small screens */

@media (max-width: 899px) {
    .wa-main {
        --wa-band-h: 110px;
    }

    .wa-row,
    .wa-feature--flip .wa-row {
        grid-template-columns: minmax(0, 1fr);
    }

    .wa-feature--flip .wa-phone {
        order: 0;
    }

    .wa-phone {
        max-width: 20rem;
    }

    /* On phones: clear of the running text, above the heading on the left
       and below the phone on the right, and well into the screen. */
    .wa-deco {
        width: 104px;
    }

    .wa-deco--left {
        top: .25rem;
        left: -1.25rem;
    }

    .wa-deco--right {
        bottom: .75rem;
        right: -1rem;
    }

    .wa-feature {
        padding-top: 7.5rem;
        padding-bottom: 6rem;
    }
}

/* Phones, upright or on their side: a lower band (Benedikt, 2026-09-28),
   10 % of a 390 x 800 screen instead of 14 %. Everything in it, the pause
   button's place and the page's bottom padding scale with --wa-band-h;
   below about 80 px the pause button would outweigh the drawing. */
@media (max-width: 639px), (max-height: 500px) {
    .wa-main {
        --wa-band-h: 80px;
    }
}

@media (prefers-reduced-motion: reduce) {
    .wa-band,
    .wa-actor,
    .wa-actor-item,
    .wa-deco {
        transition: none;
    }

    .wa-msg.is-new,
    .wa-deco svg,
    .wa-phone.is-typing .wa-typing span,
    .wa-band .wa-leg,
    .wa-band .wa-arm,
    .wa-band .wa-wheel,
    .wa-band .wa-body,
    .wa-band .wa-actor-svg,
    .wa-puff,
    .wa-fall,
    .wa-drop,
    .wa-rain,
    .wa-belt,
    .wa-gear,
    .wa-flow,
    .wa-band-leaf {
        animation: none !important;
    }

    .wa-band-leaf {
        display: none;
    }
}
