/* ===========================================================================
   Illustration kit — shared chrome for every use-case animation.

   Coordinate system
   -----------------
   The phone interior is authored at a FIXED design size of 300 x 650 units and
   scaled to fit, so typography and proportions are identical at every
   breakpoint. `--u` is one design unit; write every length as calc(N * var(--u)).

   Visible band
   ------------
   The card clips the phone: the top ~35u and the bottom ~160u are always hidden.
   Both screens therefore open with a 92u header whose top is cut by the card
   edge, which reads as the header running off the top of the frame. Content
   lives between y=40 and y=480.

   Reserved zone
   -------------
   The playback pill floats at the bottom of the card, covering roughly y>445.
   Keep anything meaningful above **y = 450**; below that belongs decorative
   chrome only (a fake input bar, wallpaper).

   Theming
   -------
   Per use case, set `--uc-accent` on the card (emerald for messages, amber for
   food, ...). It drives the app header, the send button and the tap highlight.

   Direction
   ---------
   RTL is handled with logical properties. NOTE: never put a `-webkit-` and a
   `-moz-` pseudo-element in the same selector list — one unrecognised selector
   invalidates the whole rule and the override is silently dropped.
   =========================================================================== */

.uc-illo {
    position: absolute;
    inset: 0;
    container-type: inline-size;
}



/* `--u` is declared on the stage, not on .uc-illo: cq units resolve against the
   nearest ancestor container, and .uc-illo IS that container — an element cannot
   query itself. Declaring it one level down keeps the resolution unambiguous.
   Descendants inherit the same value, since .uc-illo is their container too. */
.uc-stage {
    /* Fallback for browsers without container query units (~280px phone at the
       common desktop breakpoint). */
    --u: 0.93px;
}



@supports (container-type: inline-size) {
    .uc-stage { --u: calc(100cqw / 300); }
}



.uc-stage {
    position: absolute;
    inset-block-start: 0;
    inset-inline-start: 0;
    width: calc(300 * var(--u));
    height: calc(650 * var(--u));
    overflow: hidden;
    font-family: Inter, sans-serif;
    line-height: 1.35;
    -webkit-font-smoothing: antialiased;
}



/* --- the two stacked screens ------------------------------------------- */

.uc-screen {
    position: absolute;
    inset: 0;
    background: #fff;
}



/* Default (no-JS / reduced-motion) poster state: show the finished result.
   The animator overrides all of this in resetAll(). */
.uc-screen--sova { opacity: 0; visibility: hidden; }



/* A use case that walks through more than one app marks every screen after the
   first --alt. They are mid-run states, never the finished result, so they stay
   out of the poster exactly like the Sova screen does. .uc-screen--app remains
   the one screen the poster shows: author THAT as the end of the story. */
.uc-screen--alt { opacity: 0; visibility: hidden; }



/* ============================ Sova chat screen ========================== */

.uc-sova-header {
    display: flex;
    /* Centred, NOT bottom-aligned. The top 38u of this header is clipped by the
       card, so content is centred over the visible 38..92 band via the top
       padding. Bottom-aligning lined up the *bottoms* of items with different
       heights (chevron, title, avatar), which read as misaligned. */
    align-items: center;
    gap: calc(9 * var(--u));
    height: calc(92 * var(--u));
    padding-inline: calc(16 * var(--u));
    padding-block-start: calc(38 * var(--u));
    border-block-end: 1px solid #eef0f4;
    background: #fff;
}



/* Sova brand lockup: the real owl mark (#FCD141) on the brand navy (#001F3F).
   Yellow appears ONLY inside this small disc — at that size it reads as a logo
   accent and never competes with the emerald/amber/blue/purple card tints that
   the five use-case illustrations sit on. Navy carries the brand everywhere
   else (bubbles, send buttons), because it stays legible on all of them. */
.uc-sova-mark {
    width: calc(34 * var(--u));
    height: calc(34 * var(--u));
    border-radius: 50%;
    background: #001F3F;
    display: flex;
    align-items: center;
    justify-content: center;
    flex: none;
    overflow: hidden;
}



.uc-sova-mark img {
    width: calc(27 * var(--u));
    height: calc(27 * var(--u));
    display: block;
}



.uc-sova-name {
    font-size: calc(16 * var(--u));
    font-weight: 600;
    color: #0f172a;
    letter-spacing: -0.01em;
}



.uc-sova-body {
    padding: calc(18 * var(--u)) calc(16 * var(--u));
    display: flex;
    flex-direction: column;
    gap: calc(10 * var(--u));
}



/* user prompt bubble — Sova navy, aligned to the inline end */
.uc-bubble-user {
    align-self: flex-end;
    max-width: calc(232 * var(--u));
    background: #001F3F;
    color: #fff;
    font-size: calc(13 * var(--u));
    font-weight: 500;
    padding: calc(11 * var(--u)) calc(13 * var(--u));
    border-radius: calc(18 * var(--u));
    border-end-end-radius: calc(5 * var(--u));
    text-align: start;
}



/* Sova's reply */
.uc-bubble-sova {
    align-self: flex-start;
    max-width: calc(232 * var(--u));
    background: #f1f3f9;
    color: #334155;
    font-size: calc(13 * var(--u));
    font-weight: 500;
    padding: calc(11 * var(--u)) calc(13 * var(--u));
    border-radius: calc(18 * var(--u));
    border-end-start-radius: calc(5 * var(--u));
    text-align: start;
}



.uc-bubble-sova.is-done {
    display: flex;
    align-items: center;
    gap: calc(7 * var(--u));
    background: #ecfdf5;
    color: #047857;
}



.uc-done-check {
    width: calc(16 * var(--u));
    height: calc(16 * var(--u));
    border-radius: 50%;
    background: #10b981;
    color: #fff;
    display: flex;
    align-items: center;
    justify-content: center;
    flex: none;
}



.uc-done-check svg { width: calc(9 * var(--u)); height: calc(9 * var(--u)); }



/* typing indicator */
.uc-typing {
    align-self: flex-start;
    display: flex;
    align-items: center;
    gap: calc(4 * var(--u));
    background: #f1f3f9;
    padding: calc(13 * var(--u)) calc(14 * var(--u));
    border-radius: calc(18 * var(--u));
    border-end-start-radius: calc(5 * var(--u));
}



.uc-typing i {
    width: calc(6 * var(--u));
    height: calc(6 * var(--u));
    border-radius: 50%;
    background: #94a3b8;
    display: block;
}



/* bottom input bar, shared shape between screens */
.uc-inputbar {
    position: absolute;
    inset-inline: calc(14 * var(--u));
    inset-block-start: calc(432 * var(--u));
    height: calc(38 * var(--u));
    display: flex;
    align-items: center;
    gap: calc(8 * var(--u));
}



.uc-inputbar-field {
    flex: 1;
    height: 100%;
    background: #f1f3f9;
    border-radius: calc(19 * var(--u));
    display: flex;
    align-items: center;
    padding-inline: calc(14 * var(--u));
    font-size: calc(11.5 * var(--u));
    color: #94a3b8;
}



.uc-inputbar-send {
    width: calc(38 * var(--u));
    height: calc(38 * var(--u));
    border-radius: 50%;
    background: #001F3F;
    color: #fff;
    display: flex;
    align-items: center;
    justify-content: center;
    flex: none;
}



.uc-inputbar-send svg { width: calc(15 * var(--u)); height: calc(15 * var(--u)); }


.uc-screen--app .uc-inputbar-send { background: var(--uc-accent, #059669); }



/* ========================== messaging app screen ======================== */

.uc-app-header {
    display: flex;
    align-items: center;              /* see .uc-sova-header for why */
    gap: calc(12 * var(--u));
    height: calc(92 * var(--u));
    padding-inline: calc(15 * var(--u));
    padding-block-start: calc(38 * var(--u));
    background: var(--uc-accent, #059669);
    color: #fff;
}



.uc-app-title {
    font-size: calc(16 * var(--u));
    font-weight: 700;
    letter-spacing: -0.01em;
}



.uc-icon-back {
    width: calc(17 * var(--u));
    height: calc(17 * var(--u));
    flex: none;
}


/* mirror the chevron in RTL */
[dir="rtl"] .uc-icon-back { transform: scaleX(-1); }



.uc-avatar {
    width: calc(44 * var(--u));
    height: calc(44 * var(--u));
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: calc(16 * var(--u));
    font-weight: 600;
    color: #fff;
    flex: none;
}



/* placeholder bars stand in for pre-existing chat history — deliberately
   text-free so they need no translation */
.uc-bar {
    display: block;
    height: calc(6 * var(--u));
    border-radius: calc(3 * var(--u));
    background: #e5e7eb;
}



/* --- header cart badge --------------------------------------------------- */
/* Sits at the inline end of .uc-app-header in any shopping-shaped use case. */

.uc-cart {
    margin-inline-start: auto;
    position: relative;
    display: flex;
    align-items: center;
    flex: none;
}



.uc-cart svg {
    width: calc(20 * var(--u));
    height: calc(20 * var(--u));
    color: #fff;
}



.uc-cart-count {
    position: absolute;
    inset-block-start: calc(-5 * var(--u));
    inset-inline-end: calc(-6 * var(--u));
    min-width: calc(16 * var(--u));
    height: calc(16 * var(--u));
    padding-inline: calc(4 * var(--u));
    border-radius: 999px;
    background: #fff;
    color: var(--uc-accent, #059669);
    font-size: calc(10.5 * var(--u));
    font-weight: 700;
    display: flex;
    align-items: center;
    justify-content: center;
    font-variant-numeric: tabular-nums;
}



/* --- agent pill --------------------------------------------------------- */

.uc-agent-pill {
    position: absolute;
    /* Sits in the gap between the last contact row (ends at y=388) and the input
       bar (starts at y=432). The pill floats above the thread too, so anything
       lower collides with the thread's input bar. */
    inset-block-start: calc(392 * var(--u));
    /* Centred with auto margins, NOT translateX(-50%): GSAP animates this
       element's y, and it writes an inline transform that would capture (and
       then freeze) whichever translateX applied at build time — leaving the pill
       mis-centred when i18n flips `dir` to rtl afterwards. */
    inset-inline: 0;
    margin-inline: auto;
    width: fit-content;
    display: flex;
    align-items: center;
    gap: calc(7 * var(--u));
    background: #fff;
    border: 1px solid #e5e7eb;
    border-radius: calc(22 * var(--u));
    padding: calc(7 * var(--u)) calc(16 * var(--u)) calc(7 * var(--u)) calc(8 * var(--u));
    box-shadow: 0 calc(4 * var(--u)) calc(14 * var(--u)) rgba(15, 23, 42, 0.1);
    white-space: nowrap;
    z-index: 3;
}



.uc-agent-pill .uc-sova-mark {
    width: calc(22 * var(--u));
    height: calc(22 * var(--u));
}



.uc-agent-pill .uc-sova-mark img {
    width: calc(18 * var(--u));
    height: calc(18 * var(--u));
}



.uc-agent-label {
    font-size: calc(12.5 * var(--u));
    font-weight: 600;
    color: #334155;
}



/* --- tap cursor --------------------------------------------------------- */

.uc-cursor {
    position: absolute;
    inset-block-start: 0;
    inset-inline-start: 0;
    width: calc(26 * var(--u));
    height: calc(26 * var(--u));
    margin-block-start: calc(-13 * var(--u));
    margin-inline-start: calc(-13 * var(--u));
    border-radius: 50%;
    background: rgba(15, 23, 42, 0.16);
    border: calc(1.5 * var(--u)) solid rgba(15, 23, 42, 0.3);
    opacity: 0;
    pointer-events: none;
    z-index: 5;
}



/* The ripple is a tap highlight, so it takes the card's accent like the header
   and the send button do. It is drawn at full opacity; the animation fades it
   from 0.85 to 0, which is where the translucency comes from. */
.uc-ripple {
    position: absolute;
    inset: calc(-6 * var(--u));
    border-radius: 50%;
    border: calc(2 * var(--u)) solid var(--uc-accent, #059669);
    opacity: 0;
}



/* --- primary action bar --------------------------------------------------
   The one full-width button an app screen commits with (Checkout, Confirm
   ride, ...). Add .is-done to swap in the tick once the action lands. */

.uc-actionbar {
    position: absolute;
    inset-inline: calc(15 * var(--u));
    inset-block-start: calc(392 * var(--u));
    height: calc(40 * var(--u));
    border-radius: calc(13 * var(--u));
    background: var(--uc-accent, #059669);
    color: #fff;
    font-size: calc(13.5 * var(--u));
    font-weight: 700;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: calc(7 * var(--u));
}



.uc-actionbar-check {
    width: calc(17 * var(--u));
    height: calc(17 * var(--u));
    border-radius: 50%;
    background: #fff;
    color: var(--uc-accent, #059669);
    display: none;
    align-items: center;
    justify-content: center;
}



.uc-actionbar-check svg { width: calc(10 * var(--u)); height: calc(10 * var(--u)); }


.uc-actionbar.is-done .uc-actionbar-check { display: flex; }



/* --- bottom sheet --------------------------------------------------------
   Shell only: geometry, radius, shadow, grip, title and the sticky CTA. What
   goes between the title and the CTA is the use case's own business. Hidden in
   the poster state; the animator drives it with autoAlpha + yPercent.
   Override --uc-sheet-top / --uc-sheet-bottom (design units) per use case. */

.uc-sheet {
    position: absolute;
    inset-inline: 0;
    inset-block-start: calc(var(--uc-sheet-top, 170) * var(--u));
    inset-block-end: calc(var(--uc-sheet-bottom, 210) * var(--u));
    z-index: 3;
    background: #fff;
    border-start-start-radius: calc(22 * var(--u));
    border-start-end-radius: calc(22 * var(--u));
    box-shadow: 0 calc(-6 * var(--u)) calc(24 * var(--u)) rgba(15, 23, 42, .14);
    padding: calc(10 * var(--u)) calc(16 * var(--u));
    display: flex;
    flex-direction: column;
    opacity: 0;
    visibility: hidden;
}



.uc-sheet-grip {
    width: calc(38 * var(--u));
    height: calc(4 * var(--u));
    border-radius: 999px;
    background: #e2e8f0;
    align-self: center;
    flex: none;
}



.uc-sheet-title {
    font-size: calc(15 * var(--u));
    font-weight: 700;
    color: #111827;
    margin-block: calc(12 * var(--u)) calc(10 * var(--u));
}



.uc-sheet-add {
    margin-block-start: auto;
    height: calc(40 * var(--u));
    border-radius: calc(13 * var(--u));
    background: var(--uc-accent, #059669);
    color: #fff;
    font-size: calc(13.5 * var(--u));
    font-weight: 700;
    display: flex;
    align-items: center;
    justify-content: center;
}



/* --- playback controls ---------------------------------------------------
   One row, inset from the card edges: a stroked play/pause glyph on the same
   baseline as the seek line. Everything is drawn at the SAME 2px stroke weight
   so the glyph and the track read as one control rather than a button parked on
   top of a line. Nothing is shown at rest — it appears on hover, on keyboard
   focus, while paused, and always on touch (which has no hover).
   Sized in px, not `--u`: these live outside the phone, at page scale. */

.uc-controls {
    position: absolute;
    /* Centred with auto margins, never a transform: the animator writes inline
       transforms elsewhere and a translate-based centre would be clobbered.
       Width is capped BELOW the phone's width at every breakpoint, so the pill
       always floats within the screen and never sits on the phone's bezel —
       which is what a left-anchored button did once the phone got wider. */
    inset-inline: 0;
    margin-inline: auto;
    width: min(72%, 258px);
    bottom: 11px;
    z-index: 20;
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 6px 13px;
    border-radius: 999px;
    background: rgba(255, 255, 255, .76);
    -webkit-backdrop-filter: blur(14px) saturate(155%);
    backdrop-filter: blur(14px) saturate(155%);
    border: 1px solid rgba(15, 23, 42, .08);
    box-shadow: 0 4px 16px rgba(15, 23, 42, .12);
    opacity: 0;
    pointer-events: none;
    transition: opacity .18s ease;
}



@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
    .uc-controls { background: rgba(255, 255, 255, .95); }
}



.uc-controls[hidden] { display: none; }



.uc-illo-card:hover .uc-controls,
.uc-controls:has(:focus-visible),
.uc-controls.is-paused {
    opacity: 1;
    pointer-events: auto;
}



/* Older engines without :has() fall back to :focus-within. Slightly sticky after
   a mouse click, but never leaves keyboard users without a control. */
@supports not (selector(:has(*))) {
    .uc-controls:focus-within { opacity: 1; pointer-events: auto; }
}



/* No hover on touch: keep the controls permanently available. */
@media (hover: none) {
    .uc-controls { opacity: 1; pointer-events: auto; }
}



/* --- play / pause glyph -------------------------------------------------- */
/* No disc, no fill — just a stroked glyph, so it sits at the same visual weight
   as the 2px seek track. */

.uc-ctrl-btn {
    flex: none;
    width: 20px;
    height: 20px;
    padding: 0;
    border: 0;
    background: none;
    color: #1b3450;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    opacity: .85;
    transition: opacity .15s ease;
}



.uc-ctrl-btn:hover { opacity: 1; }


.uc-ctrl-btn svg { width: 16px; height: 16px; display: block; }



/* one icon at a time, driven by .is-paused on the control root */
.uc-ctrl-play { display: none; }


.uc-controls.is-paused .uc-ctrl-play { display: block; }


.uc-controls.is-paused .uc-ctrl-pause { display: none; }



/* --- seek line ----------------------------------------------------------- */

.uc-ctrl-seek {
    -webkit-appearance: none;
    appearance: none;
    flex: 1;
    min-width: 0;
    /* transparent hit area around a 2px visual line — a 2px drag target would be
       unusable; the visible track is drawn by the pseudo-elements below */
    height: 16px;
    margin: 0;
    padding: 0;
    background: transparent;
    cursor: pointer;
}



.uc-ctrl-seek::-webkit-slider-runnable-track {
    height: 2px;
    border-radius: 999px;
    background: linear-gradient(to right,
        #1b3450 0 calc(var(--p, 0) * 100%),
        rgba(15, 23, 42, .25) calc(var(--p, 0) * 100%) 100%);
}



.uc-ctrl-seek::-moz-range-track {
    height: 2px;
    border-radius: 999px;
    background: linear-gradient(to right,
        #1b3450 0 calc(var(--p, 0) * 100%),
        rgba(15, 23, 42, .25) calc(var(--p, 0) * 100%) 100%);
}



/* RTL: browsers mirror the range control itself, so the thumb travels
   right-to-left and the fill has to start from the right edge.
   These MUST stay as two separate rules — a selector list containing a pseudo
   element the engine doesn't recognise invalidates the WHOLE rule, so pairing
   the -webkit- and -moz- selectors made Chrome drop the override entirely and
   silently fall back to the LTR fill. */
[dir="rtl"] .uc-ctrl-seek::-webkit-slider-runnable-track {
    background: linear-gradient(to left,
        #1b3450 0 calc(var(--p, 0) * 100%),
        rgba(15, 23, 42, .25) calc(var(--p, 0) * 100%) 100%);
}



[dir="rtl"] .uc-ctrl-seek::-moz-range-track {
    background: linear-gradient(to left,
        #1b3450 0 calc(var(--p, 0) * 100%),
        rgba(15, 23, 42, .25) calc(var(--p, 0) * 100%) 100%);
}



/* The seek line mirrors, so the play glyph has to point the way playback
   travels. The pause glyph is symmetric and needs no mirroring. */
[dir="rtl"] .uc-ctrl-play { transform: scaleX(-1); }



.uc-ctrl-seek::-webkit-slider-thumb {
    -webkit-appearance: none;
    width: 9px;
    height: 9px;
    margin-top: -3.5px;            /* centre on the 2px track */
    border-radius: 50%;
    background: #1b3450;
    border: 0;
}



.uc-ctrl-seek::-moz-range-thumb {
    width: 9px;
    height: 9px;
    border: 0;
    border-radius: 50%;
    background: #1b3450;
}



.uc-ctrl-btn:focus-visible,
.uc-ctrl-seek:focus-visible {
    outline: 2px solid #1b3450;
    outline-offset: 3px;
    border-radius: 4px;
}



@media (prefers-reduced-motion: reduce) {
    .uc-controls, .uc-ctrl-btn { transition: none; }
}



/* --- hidden i18n source block ------------------------------------------- */
/* i18n.js fills these; the animator reads textContent out of them. Kept out of
   the animated nodes so a language switch can never clobber a bubble mid-type. */
.uc-strings { display: none; }



/* --- reduced motion ------------------------------------------------------ */
/* The un-animated DOM is already the finished-result poster, so there is
   nothing to do but make sure the Sova screen stays hidden. The animator
   never even fetches GSAP in this mode. */
@media (prefers-reduced-motion: reduce) {
    .uc-screen--sova,
    .uc-screen--alt { opacity: 0 !important; visibility: hidden !important; }
    .uc-cursor { opacity: 0 !important; }
}
