/*
 * UniMap Cards -- signup/login/verify/about-you/welcome shell CSS.
 *
 * Extracted in v0.263.0 from Unimap_Signup::print_css(), which used to
 * inline this whole file as a <style> block on every one of the 11
 * routes this class renders (~35KB, unminified, re-sent uncached on
 * every request). Linked externally now so browsers actually cache it
 * across pageviews/routes. Content is unchanged from the inline
 * version -- see Unimap_Signup::render_shell_start() for the <link>
 * tag and its cache-busting query string.
 */
*, *::before, *::after { box-sizing: border-box; }
        html, body { margin: 0; padding: 0; }
        body {
            font-family: 'Poppins', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
            background: #1C1C1C;
            color: #FFFFFF;
            -webkit-font-smoothing: antialiased;
            min-height: 100vh;
        }
        a { color: #5A8F8D; text-decoration: none; }
        a:hover { color: #7AACAA; }

        .us-bg {
            min-height: 100vh;
            display: flex;
            flex-direction: column;
            /* Flat solid background across the whole auth flow. The former
               teal radial glows read as "AI landing page" and fought the
               clean, Apple-like flat look we want here. Re-add the two
               radial-gradient() layers above #1C1C1C to restore the glow. */
            background: #1C1C1C;
        }

        .us-topbar {
            display: flex; align-items: center; justify-content: space-between;
            padding: 18px 24px;
            padding-top: calc(18px + env(safe-area-inset-top));
        }
        .us-topbar__brand img { height: 28px; width: auto; display: block; }
        /* Right-side cluster: language switcher + (optional) logout button.
           Single flex container keeps the gap consistent regardless of
           whether the user is logged in. */
        .us-topbar__right {
            display: flex;
            align-items: center;
            gap: 10px;
        }
        .us-topbar__logout {
            display: inline-flex; align-items: center; gap: 8px;
            color: rgba(255,255,255,0.7);
            font-size: 13px; font-weight: 500;
            padding: 8px 14px;
            border-radius: 100px;
            transition: all 0.15s ease;
        }
        .us-topbar__logout:hover { color: #FFFFFF; background: rgba(255,255,255,0.06); }

        .us-main {
            flex: 1;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            padding: 24px 16px 32px;
        }
        .us-card {
            background: #252525;
            border: 1px solid rgba(255,255,255,0.06);
            border-radius: 24px;
            width: 100%;
            max-width: 460px;
            padding: 36px 32px 32px;
            box-shadow: 0 4px 30px rgba(0,0,0,0.35);
        }
        @media (max-width: 480px) {
            .us-card { padding: 28px 22px 24px; border-radius: 20px; }
        }

        .us-steps {
            display: flex; align-items: center; justify-content: center;
            gap: 8px;
            margin-bottom: 32px;
        }
        .us-step { display: flex; flex-direction: column; align-items: center; gap: 6px; min-width: 64px; }
        .us-step__dot {
            width: 28px; height: 28px; border-radius: 50%;
            display: flex; align-items: center; justify-content: center;
            font-size: 12px; font-weight: 700;
            transition: all 0.2s ease;
        }
        .us-step--todo   .us-step__dot { background: rgba(255,255,255,0.08); color: rgba(255,255,255,0.4); }
        .us-step--active .us-step__dot { background: #5A8F8D; color: #FFFFFF; box-shadow: 0 0 0 4px rgba(90,143,141,0.18); }
        .us-step--done   .us-step__dot { background: #5A8F8D; color: #FFFFFF; }
        .us-step__label {
            font-size: 11px; font-weight: 600;
            color: rgba(255,255,255,0.5);
            text-transform: uppercase; letter-spacing: 0.5px;
        }
        .us-step--active .us-step__label,
        .us-step--done   .us-step__label { color: #FFFFFF; }
        .us-step-line {
            width: 48px; height: 2px;
            margin-bottom: 22px;
            background: rgba(255,255,255,0.08);
            border-radius: 2px;
        }
        .us-step-line--done { background: #5A8F8D; }

        .us-h1 {
            font-family: 'Poppins', sans-serif;
            font-size: 26px; font-weight: 700;
            color: #FFFFFF;
            margin: 0 0 8px;
            text-align: center;
            line-height: 1.2;
        }
        .us-sub {
            text-align: center;
            font-size: 14px;
            color: rgba(255,255,255,0.65);
            line-height: 1.55;
            margin: 0 0 28px;
        }
        .us-sub strong { color: #FFFFFF; font-weight: 600; }

        .us-form { display: flex; flex-direction: column; gap: 16px; }
        .us-form--centered { align-items: center; }

        .us-row { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
        @media (max-width: 380px) { .us-row { grid-template-columns: 1fr; } }

        .us-field { display: flex; flex-direction: column; gap: 6px; }
        .us-label { font-size: 13px; font-weight: 500; color: rgba(255,255,255,0.85); }
        .us-optional { font-weight: 400; color: rgba(255,255,255,0.4); font-size: 12px; }
        .us-hint { font-size: 12px; color: rgba(255,255,255,0.5); margin-top: -2px; }

        .us-field input[type="text"],
        .us-field input[type="email"],
        .us-field input[type="password"],
        .us-field input[type="date"],
        .us-field select {
            font-family: inherit;
            font-size: 16px;
            /* Fixed line-height so the input's box height is identical for
               password dots and revealed text. Without it, line-height:normal
               resolves from the rendered glyphs, and on Android/WebView the
               disc font is taller than the text font -- so toggling reveal
               changed the input height, which re-centred the absolutely
               positioned .us-password__toggle and made the eye icon jump. */
            line-height: 1.25;
            color: #FFFFFF;
            background: #1C1C1C;
            border: 1.5px solid rgba(255,255,255,0.10);
            border-radius: 12px;
            padding: 14px 16px;
            width: 100%;
            transition: border 0.15s ease, background 0.15s ease;
            -webkit-appearance: none;
            appearance: none;
        }
        .us-field input::placeholder { color: rgba(255,255,255,0.35); }
        .us-field input:focus, .us-field select:focus {
            outline: none;
            border-color: #5A8F8D;
            background: #1C1C1C;
            box-shadow: 0 0 0 3px rgba(90,143,141,0.18);
        }
        .us-field input[type="date"] { color-scheme: dark; }
        .us-field select {
            background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%23ffffff80' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'><polyline points='6 9 12 15 18 9'/></svg>");
            background-repeat: no-repeat;
            background-position: right 16px center;
            padding-right: 44px;
        }
        .us-field select option { background: #1C1C1C; color: #FFFFFF; }

        .us-field.is-error input, .us-field.is-error select { border-color: #C0392B; }

        .us-fielderror { font-size: 12px; color: #FFB7B0; margin-top: 2px; }

        /* v0.252.0 — locked "University: X ✓ (not right? change)" display
           shown instead of the open dropdown when the account email's
           domain resolves to a known school. Same box shape as a real
           input so it reads as a filled-in field, not a plain paragraph. */
        .us-university-derived {
            display: flex;
            align-items: center;
            justify-content: space-between;
            gap: 12px;
            font-size: 15px;
            color: #FFFFFF;
            background: #1C1C1C;
            border: 1.5px solid rgba(90,143,141,0.35);
            border-radius: 12px;
            padding: 12px 12px 12px 16px;
        }
        .us-university-derived__value {
            display: flex;
            align-items: center;
            gap: 8px;
            color: #5EE5A3;
        }
        .us-university-derived .us-link-btn { margin-top: 0; white-space: nowrap; }

        .us-password { position: relative; }
        .us-password input { padding-right: 48px; }
        .us-password__toggle {
            position: absolute; top: 50%; right: 8px;
            transform: translateY(-50%);
            background: transparent; border: 0; color: rgba(255,255,255,0.6);
            padding: 8px; cursor: pointer;
            border-radius: 8px;
            display: flex; align-items: center; justify-content: center;
        }
        .us-password__toggle:hover { color: #FFFFFF; background: rgba(255,255,255,0.06); }
        /* Both icon spans must use the SAME display so swapping states
           doesn't shift the glyph vertically. .us-eye had no rule, so it
           fell back to a span's default `inline` -- its SVG sat on the
           text baseline (dropped low), while the revealed .us-eye-off is
           inline-flex (glyph centered). Matching them keeps the eye
           centered in both the hidden and shown states. */
        .us-password__toggle .us-eye     { display: inline-flex; }
        .us-password__toggle .us-eye-off { display: none; }
        .us-password__toggle.is-shown .us-eye    { display: none; }
        .us-password__toggle.is-shown .us-eye-off { display: inline-flex; }

        .us-code {
            display: flex; gap: 10px; justify-content: center;
            margin: 4px 0 8px;
        }
        .us-code input {
            font-family: inherit;
            font-size: 32px; font-weight: 700;
            text-align: center;
            color: #FFFFFF;
            background: #1C1C1C;
            border: 2px solid rgba(255,255,255,0.10);
            border-radius: 14px;
            width: 52px;
            height: 64px;
            padding: 0;
            transition: all 0.15s ease;
            -webkit-appearance: none;
            appearance: none;
        }
        @media (max-width: 420px) {
            .us-code { gap: 6px; }
            .us-code input { width: 44px; height: 56px; font-size: 26px; border-radius: 12px; }
        }
        @media (max-width: 360px) {
            .us-code input { width: 40px; height: 52px; font-size: 22px; }
        }
        .us-code input:focus {
            outline: none;
            border-color: #5A8F8D;
            box-shadow: 0 0 0 4px rgba(90,143,141,0.18);
            transform: translateY(-1px);
        }
        .us-code.is-error input { border-color: #C0392B; }
        .us-code.is-error input:focus { box-shadow: 0 0 0 4px rgba(192,57,43,0.25); }

        /*
         * v0.96.0 — Segmented email/doc chooser on /verify-student.
         * A two-tab pill track that makes the "verify with your uni email
         * OR upload a document" choice explicit; each tab reveals one pane
         * (the two existing forms, untouched). Toggled by the inline
         * script at the bottom of render_verify_student().
         */
        .us-seg {
            display: flex;
            gap: 4px;
            background: rgba(255,255,255,0.05);
            border: 1px solid rgba(255,255,255,0.08);
            border-radius: 14px;
            padding: 4px;
            margin-bottom: 22px;
        }
        .us-seg button {
            flex: 1 1 0;
            appearance: none;
            border: 0;
            background: transparent;
            color: rgba(255,255,255,0.6);
            font-family: 'Poppins', sans-serif;
            font-size: 13.5px;
            font-weight: 600;
            padding: 11px 8px;
            border-radius: 10px;
            cursor: pointer;
            white-space: nowrap;
            transition: background 0.15s ease, color 0.15s ease;
        }
        .us-seg button:hover { color: #FFFFFF; }
        .us-seg button.is-active { background: #5A8F8D; color: #FFFFFF; }
        .us-seg button:focus-visible {
            outline: none;
            box-shadow: 0 0 0 3px rgba(90,143,141,0.35);
        }
        /* Progressive enhancement: without JS the segment stays hidden and
           BOTH panes remain visible — the pre-v0.96 always-visible layout —
           so a document can always be uploaded even if the toggle script
           never runs. The toggle JS adds .js-seg to the card to switch on
           the tabbed behaviour. */
        .us-seg { display: none; }
        .js-seg .us-seg { display: flex; }
        .js-seg .us-pane { display: none; }
        .js-seg .us-pane.is-active { display: block; }

        .us-field--upload .us-drop {
            display: block;
            margin-top: 8px;
            border: 2px dashed rgba(255,255,255,0.18);
            border-radius: 16px;
            padding: 28px 20px;
            cursor: pointer;
            text-align: center;
            transition: all 0.15s ease;
            background: rgba(255,255,255,0.02);
        }
        .us-field--upload .us-drop:hover {
            border-color: #5A8F8D;
            background: rgba(90,143,141,0.06);
        }
        .us-field--upload.is-error .us-drop { border-color: #C0392B; }

        /*
         * v0.38.0 — Two-sided ID checkbox.
         *
         * Custom-styled checkbox that matches the dark theme and pill
         * button family. Native input stays present (opacity:0) so the
         * form still submits the value and screen readers still see a
         * checkbox role.
         */
        .us-check--two-sided {
            display: flex;
            gap: 12px;
            align-items: flex-start;
            padding: 12px 4px;
            cursor: pointer;
            user-select: none;
            margin-top: -4px;   /* tighten under the drop zone */
        }
        .us-check--two-sided input[type="checkbox"] {
            position: absolute;
            opacity: 0;
            width: 1px;
            height: 1px;
            pointer-events: none;
        }
        .us-check__box {
            flex: 0 0 auto;
            width: 22px;
            height: 22px;
            border-radius: 6px;
            border: 2px solid rgba(255,255,255,0.28);
            background: rgba(255,255,255,0.02);
            display: inline-flex;
            align-items: center;
            justify-content: center;
            transition: all 0.15s ease;
            margin-top: 1px;
        }
        .us-check__box svg {
            width: 14px;
            height: 14px;
            color: #fff;
            opacity: 0;
            transform: scale(0.6);
            transition: all 0.15s ease;
        }
        .us-check--two-sided input[type="checkbox"]:checked + .us-check__box {
            background: #5A8F8D;
            border-color: #5A8F8D;
        }
        .us-check--two-sided input[type="checkbox"]:checked + .us-check__box svg {
            opacity: 1;
            transform: scale(1);
        }
        .us-check--two-sided input[type="checkbox"]:focus-visible + .us-check__box {
            box-shadow: 0 0 0 4px rgba(90,143,141,0.28);
        }
        .us-check--two-sided:hover .us-check__box {
            border-color: rgba(255,255,255,0.5);
        }
        .us-check__text {
            display: flex;
            flex-direction: column;
            gap: 2px;
            font-size: 14px;
            line-height: 1.4;
            color: rgba(255,255,255,0.9);
        }
        .us-check__hint {
            font-size: 12px;
            color: rgba(255,255,255,0.55);
        }

        /*
         * Back-side upload slot animation. Toggling this on/off with just
         * grid-template-rows: 0fr won't hide the parent's flex gap (the
         * .us-form uses gap: 16px, which applies between visible children
         * regardless of their measured size). So we split visibility into
         * two states: `.is-collapsing` animates the height + opacity down
         * to zero, and once the transition completes the JS toggle adds
         * the `hidden` attribute which drops the element from the flow
         * entirely via display:none. Reverse on open.
         */
        .us-field--back {
            overflow: hidden;
            display: grid;
            grid-template-rows: 1fr;
            opacity: 1;
            transition:
                grid-template-rows 0.28s ease,
                opacity 0.2s ease 0.05s;
        }
        .us-field--back.is-collapsing {
            grid-template-rows: 0fr;
            opacity: 0;
            pointer-events: none;
        }
        .us-field--back[hidden] {
            display: none;   /* eliminated from the flex flow, gap collapses */
        }
        .us-field--back > * {
            min-height: 0;    /* let grid row collapse cleanly */
        }

        /*
         * Visually-hidden file input. opacity:0 + position absolute keeps
         * the input in the layout flow (preserving file uploads on
         * Android Samsung Internet + older Chrome) while still hiding it.
         * The label.us-drop is the visible click target.
         */
        .us-file-input {
            position: absolute;
            left: -9999px;
            width: 1px;
            height: 1px;
            opacity: 0;
            pointer-events: none;
        }

        /* Diagnostic panel for admins when validation fails. */
        .us-diag {
            margin-top: 12px;
            background: rgba(255,255,255,0.04);
            border: 1px solid rgba(255,255,255,0.10);
            border-radius: 12px;
            padding: 12px 16px;
            font-family: 'SF Mono', Menlo, Consolas, monospace;
            font-size: 11px;
            line-height: 1.6;
            color: rgba(255,255,255,0.75);
            white-space: pre-wrap;
            word-break: break-all;
        }
        .us-diag strong { color: #5A8F8D; font-weight: 600; }
        .us-drop__icon { color: #5A8F8D; margin-bottom: 12px; display: flex; justify-content: center; }
        .us-drop__title { font-size: 15px; font-weight: 600; color: #FFFFFF; margin-bottom: 4px; }
        .us-drop__hint  { font-size: 12px; color: rgba(255,255,255,0.5); }
        .us-drop__filename {
            font-size: 14px; color: #FFFFFF; font-weight: 500;
            margin: 8px 0;
            word-break: break-all;
        }
        .us-drop__replace {
            background: transparent; border: 0; color: #5A8F8D;
            font-family: inherit; font-size: 13px; font-weight: 500;
            cursor: pointer;
            padding: 4px 10px;
        }
        .us-drop__replace:hover { color: #7AACAA; text-decoration: underline; }

        .us-checkbox {
            display: flex; align-items: flex-start; gap: 10px;
            font-size: 13px; color: rgba(255,255,255,0.75);
            line-height: 1.5;
            cursor: pointer;
        }
        .us-checkbox input[type="checkbox"] {
            -webkit-appearance: none; appearance: none;
            width: 20px; height: 20px; flex-shrink: 0;
            background: #1C1C1C;
            border: 1.5px solid rgba(255,255,255,0.20);
            border-radius: 6px;
            cursor: pointer;
            margin: 0; padding: 0;
            position: relative;
            transition: all 0.15s ease;
        }
        .us-checkbox input[type="checkbox"]:checked {
            background: #5A8F8D;
            border-color: #5A8F8D;
        }
        .us-checkbox input[type="checkbox"]:checked::after {
            content: "";
            position: absolute;
            left: 5px; top: 1px;
            width: 6px; height: 11px;
            border-right: 2px solid #FFF; border-bottom: 2px solid #FFF;
            transform: rotate(45deg);
        }
        .us-checkbox.is-error input[type="checkbox"] { border-color: #C0392B; }

        /* Compact inline variant — used on login for "remember me" */
        .us-checkbox--inline { align-items: center; }
        .us-checkbox--inline span { font-size: 13px; }

        /* Login alt-links cluster (forgot password, signup link) */
        .us-altlinks {
            display: flex; flex-direction: column; align-items: center; gap: 10px;
            margin-top: 8px;
            padding-top: 18px;
            border-top: 1px solid rgba(255,255,255,0.08);
        }
        .us-altlinks__row { display: flex; align-items: center; gap: 6px; font-size: 13px; color: rgba(255,255,255,0.55); }
        .us-altlink {
            font-size: 13px; color: rgba(255,255,255,0.75);
            text-decoration: none;
            padding: 4px 8px;
            border-radius: 8px;
            transition: all 0.15s ease;
        }
        .us-altlink:hover { color: #FFFFFF; background: rgba(255,255,255,0.04); }
        .us-altlink--primary { color: #7AACAA; font-weight: 500; }
        .us-altlink--primary:hover { color: #FFFFFF; background: rgba(90,143,141,0.18); }

        .us-submit {
            margin-top: 8px;
            display: inline-flex; align-items: center; justify-content: center; gap: 8px;
            font-family: 'Poppins', sans-serif;
            font-size: 15px; font-weight: 600;
            color: #FFFFFF !important;
            background: #5A8F8D;
            border: 0;
            border-radius: 100px;
            padding: 16px 24px;
            cursor: pointer;
            width: 100%;
            transition: all 0.15s ease;
            text-decoration: none !important;
        }
        .us-submit:hover  { background: #6BA09E; color: #FFFFFF !important; transform: translateY(-1px); box-shadow: 0 8px 20px rgba(90,143,141,0.25); text-decoration: none !important; }
        .us-submit:active { transform: translateY(0); }
        .us-submit--ghost {
            background: transparent;
            border: 1.5px solid rgba(255,255,255,0.15);
            color: #FFFFFF;
        }
        .us-submit--ghost:hover { background: rgba(255,255,255,0.06); border-color: rgba(255,255,255,0.30); box-shadow: none; }

        .us-submit--danger {
            background: #C0392B;
            color: #FFFFFF;
        }
        .us-submit--danger:hover { background: #A02C20; box-shadow: 0 8px 20px rgba(192,57,43,0.28); }

        .us-divider {
            display: flex; align-items: center; gap: 12px;
            margin: 4px 0;
            color: rgba(255,255,255,0.35);
            font-size: 12px;
        }
        .us-divider::before, .us-divider::after {
            content: '';
            flex: 1;
            height: 1px;
            background: rgba(255,255,255,0.10);
        }

        .us-google-btn {
            display: flex; align-items: center; justify-content: center; gap: 10px;
            width: 100%;
            background: #FFFFFF;
            color: #1C1C1C;
            border: 1.5px solid rgba(255,255,255,0.10);
            border-radius: 100px;
            padding: 14px 24px;
            font-family: 'Poppins', sans-serif;
            font-size: 14px; font-weight: 600;
            text-decoration: none;
            transition: all 0.15s ease;
        }
        .us-google-btn:hover { background: #F0F0F0; color: #1C1C1C; transform: translateY(-1px); box-shadow: 0 6px 16px rgba(0,0,0,0.18); }
        .us-google-btn svg { flex-shrink: 0; }

        /* Modal — shared dark card style, matches the signup surface
           so users don't get a jarring context switch. Backdrop uses a
           slightly deeper black than the base bg + a blur so the card
           behind reads as inactive. */
        .us-modal {
            position: fixed;
            inset: 0;
            display: none;
            align-items: center;
            justify-content: center;
            padding: 24px 16px;
            z-index: 10000;
        }
        .us-modal.is-open { display: flex; }
        .us-modal__backdrop {
            position: absolute; inset: 0;
            background: rgba(0,0,0,0.65);
            backdrop-filter: blur(4px);
            -webkit-backdrop-filter: blur(4px);
            cursor: pointer;
        }
        .us-modal__panel {
            position: relative;
            width: 100%;
            max-width: 420px;
            background: #252525;
            border: 1px solid rgba(255,255,255,0.08);
            border-radius: 20px;
            padding: 28px 26px 22px;
            box-shadow: 0 20px 60px rgba(0,0,0,0.5);
            animation: us-modal-in 0.15s ease-out;
        }
        @keyframes us-modal-in {
            from { opacity: 0; transform: translateY(8px) scale(0.98); }
            to   { opacity: 1; transform: translateY(0)   scale(1); }
        }
        .us-modal__title {
            font-family: 'Poppins', sans-serif;
            font-size: 18px;
            font-weight: 700;
            color: #FFFFFF;
            margin: 0 0 10px;
            line-height: 1.3;
        }
        .us-modal__body {
            font-size: 14px;
            color: rgba(255,255,255,0.7);
            line-height: 1.55;
            margin: 0 0 22px;
        }
        .us-modal__actions {
            display: flex;
            flex-direction: column;
            gap: 10px;
        }
        .us-modal__actions .us-submit { margin-top: 0; }
        @media (min-width: 440px) {
            .us-modal__actions { flex-direction: row-reverse; }
            .us-modal__actions .us-submit { flex: 1; }
        }

        .us-link-btn {
            background: transparent; border: 0;
            color: rgba(255,255,255,0.65);
            font-family: 'Poppins', sans-serif;
            font-size: 13px; font-weight: 500;
            cursor: pointer;
            padding: 8px 16px;
            margin-top: 4px;
            border-radius: 100px;
            transition: color 0.15s ease;
        }
        .us-link-btn:hover { color: #FFFFFF; }

        .us-banner {
            background: rgba(192,57,43,0.12);
            border: 1px solid rgba(192,57,43,0.30);
            border-radius: 12px;
            color: #FFB7B0;
            padding: 12px 16px;
            font-size: 13px;
            margin-bottom: 20px;
            display: flex; flex-direction: column; gap: 4px;
        }

        .us-notice {
            border-radius: 12px;
            padding: 14px 16px;
            font-size: 13px;
            line-height: 1.6;
            margin-bottom: 20px;
            display: flex; flex-direction: column; gap: 4px;
        }
        .us-notice strong { color: #FFFFFF; font-weight: 600; }
        .us-notice--info {
            background: rgba(90,143,141,0.14);
            border: 1px solid rgba(90,143,141,0.32);
            color: rgba(255,255,255,0.88);
        }
        .us-notice--soft {
            background: rgba(90,143,141,0.14);
            border: 1px solid rgba(90,143,141,0.32);
            color: rgba(255,255,255,0.92);
            font-weight: 500;
            flex-direction: row;
            align-items: flex-start;
            gap: 10px;
        }
        .us-notice__icon {
            display: flex;
            flex-shrink: 0;
            color: #5A8F8D;
            margin-top: 1px;
        }

        .us-icon-hero {
            width: 72px; height: 72px;
            border-radius: 50%;
            background: rgba(90,143,141,0.15);
            color: #5A8F8D;
            display: flex; align-items: center; justify-content: center;
            margin: 0 auto 20px;
        }
        .us-icon-hero--success { background: rgba(46,125,91,0.18); color: #4BCB8E; }

        .us-icon-sm { width: 16px; height: 16px; flex-shrink: 0; }
        .us-icon-md { width: 28px; height: 28px; }
        .us-icon-lg { width: 32px; height: 32px; }

        .us-cta-block { margin-top: 20px; }

        /* -----------------------------------------------------------
         * Loading overlay for step 3 (/verify-student). Ported from
         * views/ai-verify-css.php on the /ai-test page — same spinner,
         * same fade-through copy pattern. Kept .uv-* prefixed here on
         * purpose so the markup can be lifted between the two pages
         * without renaming, and so future signup CSS changes don't
         * accidentally alter it.
         * ----------------------------------------------------------- */
        .uv-loading {
            position: fixed; inset: 0;
            background: rgba(20,20,20,0.94);
            backdrop-filter: blur(8px);
            -webkit-backdrop-filter: blur(8px);
            display: none;
            align-items: center; justify-content: center;
            padding: 24px;
            z-index: 10000;
        }
        .uv-loading.is-open { display: flex; }
        .uv-loading__inner {
            text-align: center;
            max-width: 340px;
        }
        .uv-loading__spinner {
            width: 72px; height: 72px;
            border-radius: 50%;
            margin: 0 auto 28px;
            position: relative;
            background: radial-gradient(circle, rgba(90,143,141,0.45), transparent 65%);
            animation: uv-pulse 1.8s ease-in-out infinite;
        }
        .uv-loading__spinner::before {
            content: '';
            position: absolute;
            inset: 8px;
            border-radius: 50%;
            border: 2.5px solid transparent;
            border-top-color: #5A8F8D;
            border-right-color: #5A8F8D;
            animation: uv-spin 1.1s linear infinite;
        }
        @keyframes uv-pulse {
            0%, 100% { transform: scale(0.92); opacity: 0.55; }
            50%      { transform: scale(1.08); opacity: 1; }
        }
        @keyframes uv-spin {
            to { transform: rotate(360deg); }
        }
        .uv-loading__title {
            font-size: 20px; font-weight: 600;
            color: #FFFFFF; margin: 0 0 10px;
        }
        .uv-loading__copy {
            font-size: 14px;
            color: rgba(255,255,255,0.75);
            min-height: 42px;
            line-height: 1.5;
            transition: opacity 0.35s ease;
        }
        .uv-loading__copy.is-fading { opacity: 0; }
        .uv-loading__note {
            margin-top: 20px;
            font-size: 12px;
            color: rgba(255,255,255,0.4);
        }

        /* v0.50.0 (Task 4) — body scroll lock during the AI
         * verification step. iOS Safari doesn't honor overflow:hidden
         * on body alone while a fixed-position overlay is on screen
         * (rubber-band scroll still moves the page underneath), so
         * body is additionally pinned with position:fixed and a
         * negative top offset set inline by JS — see lockScroll() in
         * print_verify_student_js(). */
        html.unimap-scroll-locked,
        body.unimap-scroll-locked {
            overflow: hidden !important;
        }
        body.unimap-scroll-locked {
            position: fixed;
            width: 100%;
        }

        /* =============================================================
         * v0.95.0 — App-shell layout for phones.
         *
         * The floating-card model (a centered .us-card on a gradient) is
         * the DESKTOP presentation. On phones we dissolve the card chrome
         * and turn each auth screen into a full-height, edge-to-edge app
         * view, so the flow feels native and blends seamlessly with the
         * /onboarding carousel that leads into it (which is itself a
         * full-bleed #1C1C1C app screen). Desktop is deliberately left
         * untouched — every rule below lives inside this one query.
         * ----------------------------------------------------------- */
        @media (max-width: 640px) {
            /* Own the full viewport height (dvh dodges the iOS URL-bar jump). */
            .us-bg { min-height: 100vh; min-height: 100dvh; }

            .us-topbar {
                padding: 14px 18px;
                padding-top: calc(14px + env(safe-area-inset-top));
            }

            /* Vertical column: content pinned to the top like an app
               screen. */
            .us-main {
                justify-content: flex-start;
                align-items: stretch;
                padding: 4px 20px 16px;
                padding-bottom: calc(16px + env(safe-area-inset-bottom));
            }

            /* Card chrome (surface, border, radius, shadow, side padding)
               dissolves — the content runs flush with a comfortable
               gutter. flex:0 0 auto keeps form screens top-anchored. */
            .us-card {
                flex: 0 0 auto;
                width: 100%;
                max-width: 100%;
                background: transparent;
                border: 0;
                border-radius: 0;
                box-shadow: none;
                padding: 8px 0 0;
            }

            /* Heading sizes tuned for the taller app canvas. */
            .us-h1 { font-size: 23px; }

            /* Left-align the heading block on true FORM screens (signup,
               login, about-you/membership, verify-student, forgot/reset
               entry) for a native app feel. Icon-led screens
               (verify-email, welcome, application-received, not-member,
               reset-invalid) and the install promo have no .us-form OR
               carry a centered .us-icon-hero, so they stay centered. */
            .us-card:has(.us-form):not(:has(.us-icon-hero)) .us-h1,
            .us-card:has(.us-form):not(:has(.us-icon-hero)) .us-sub {
                text-align: left;
            }
            .us-card:has(.us-form):not(:has(.us-icon-hero)) .us-h1 { font-size: 26px; }

            /* /install is a short, icon-led promo (no .us-form), so the
               top-anchored form layout leaves it stranded at the top of
               the app canvas. Center it vertically instead. Auto margins
               (not justify-content:center on .us-main) so the taller iOS
               walkthrough still degrades to top-anchored + scrollable when
               it exceeds the viewport, rather than clipping off the top. */
            .us-main:has(.ui-install) .us-card { margin-top: auto; margin-bottom: auto; }

            /* Status / result screens (success "welcome", "application
               received", not-member, forgot-sent, reset-invalid) — icon +
               copy + CTA, no form. Grow to fill the canvas and centre the
               content vertically, matching the mockup's .center block,
               instead of sitting top-anchored like the form screens. */
            .us-card:has(.us-icon-hero):not(:has(.us-form)) {
                flex: 1 1 auto;
                display: flex;
                flex-direction: column;
                justify-content: center;
                padding-top: 0;
            }

            /* Full-width, connected step rail with visible labels
               (dots-only fallback on very narrow screens below). */
            .us-steps { justify-content: space-between; gap: 0; margin-bottom: 26px; }
            .us-step { min-width: 0; flex: 0 0 auto; }
            .us-step__label { display: block; font-size: 10px; letter-spacing: 0.2px; white-space: nowrap; }
            .us-step-line { flex: 1 1 auto; width: auto; margin: 0 8px 22px; }
        }

        /* Very narrow phones: drop the step labels so the connected rail
           never collides (esp. with longer Hungarian labels). */
        @media (max-width: 360px) {
            .us-step__label { display: none; }
            .us-step-line { margin-bottom: 0; }
        }

        /* =============================================================
         * v0.280.0 -- /install + /welcome.
         *
         * Moved here from the inline <style> block inside
         * Unimap_Signup::render_install(), which re-sent ~222 lines
         * uncached on every request. Same reasoning as the v0.263.0
         * extraction of this whole file: it is already linked (and
         * filemtime cache-busted) on every shell route, so the browser
         * caches it across pageviews instead.
         *
         * Palette is the shell's own: teal #5A8F8D, canvas #1C1C1C,
         * surface #252525, pill radius 100px, Poppins. No page-wide
         * radial glow -- see the .us-bg comment near the top of this
         * file for why that was deliberately removed.
         * ----------------------------------------------------------- */

        /* ---- Shared head ---- */
        .ui-app-icon {
            width: 72px; height: 72px;
            margin: 0 auto 20px;
            border-radius: 18px;
            background: linear-gradient(155deg, #6fa39e, #5A8F8D 60%, #3f6866);
            display: flex; align-items: center; justify-content: center;
            box-shadow: 0 10px 24px -6px rgba(90,143,141,.45);
            overflow: hidden;
        }
        .ui-app-icon img { width: 100%; height: 100%; object-fit: cover; display: block; }

        /* Slightly more presence than the shared 26px, scoped to these two
           screens only -- they are single-message pages, not forms. */
        .ui-h1, .uw-h1 { font-size: 30px; letter-spacing: -0.02em; }

        .ui-install { margin-top: 8px; }

        /* Desktop (pointer:fine + big screen) can't do a home-screen
           install, so swap the phone install UI for the QR-to-phone block.
           Mobile is the mirror image: QR hidden, install shown. Enforced in
           CSS as well as JS so a JS failure doesn't show desktop visitors
           instructions they cannot follow. */
        .ui-desktop { display: none; }
        @media (pointer: fine) and (min-width: 900px) {
            .ui-install { display: none !important; }
            .ui-desktop { display: block; text-align: center; }
            /* The bottom pointer is an iOS-Safari affordance; it must never
               reach a desktop viewport even if the UA test somehow passes. */
            .ui-hint { display: none !important; }
        }

        /* ---- Raised plate: the page's one primary action ---- */
        .ui-plate {
            background: #252525;
            border: 1px solid rgba(255,255,255,0.07);
            border-radius: 22px;
            padding: 26px 22px 20px;
            text-align: center;
            box-shadow: 0 12px 32px -14px rgba(0,0,0,0.7);
        }
        .ui-plate--warn { border-color: rgba(232,168,56,0.28); }
        .ui-plate__note {
            margin: 14px auto 0;
            max-width: 260px;
            font-size: 12.5px; line-height: 1.5;
            color: rgba(255,255,255,0.5);
        }

        /* ---- Android: Google Play badge ----
           text-align on the wrapper, not margin:auto on the badge -- the
           anchor is inline-level, so auto margins do nothing and the badge
           used to sit flush left. */
        .ui-android { text-align: center; }
        .ui-play { display: inline-block; line-height: 0; }
        .ui-play__badge {
            width: 220px; max-width: 100%; height: auto;
            display: block;
            transition: transform 0.15s ease;
        }
        .ui-play:hover .ui-play__badge { transform: translateY(-2px); }
        .ui-play:active .ui-play__badge { transform: translateY(0); }

        /* ---- iOS: animated Safari walkthrough ----
           Demonstrates the one genuinely non-obvious step: Add to Home Screen
           sits below the fold of the share sheet and has to be scrolled to.

           Proportions matter here -- an earlier pass used a 196x264 screen,
           which is a 0.74 ratio and reads as a squashed tablet, not a phone.
           This is 168x340 (0.49), within a hair of a real iPhone's 0.46.

           No chunky device bezel either: the screen sits on a soft shadow
           with rounded corners, so it doesn't become a hard box inside the
           .us-card box on desktop.

           One shared cycle (--ui-cycle) drives the sheet, the ... button and
           the three step badges off the same timeline. The version before
           this chained setTimeouts that drifted against the CSS transitions
           they triggered, which is what made it stutter. */
        .ui-phone {
            --ui-cycle: 8s;
            width: 168px;
            margin: 0 auto 26px;
            border-radius: 26px;
            background: #0b0b0d;
            padding: 5px;
            box-shadow: 0 20px 44px -18px rgba(0,0,0,.85),
                        0 0 0 1px rgba(255,255,255,.07);
        }
        .ui-phone__screen {
            background: #f5f5f4;
            border-radius: 22px;
            height: 340px;
            position: relative;
            overflow: hidden;
        }

        /* The card page sitting behind the sheet. Textless: nothing here
           needs translating and grey bars read as "a page" without
           competing with the sheet. */
        .ui-phone__page {
            display: flex; flex-direction: column; align-items: center;
            gap: 7px;
            padding: 40px 16px 0;
        }
        .ui-phone__logo {
            width: 40px; height: 40px;
            border-radius: 10px;
            overflow: hidden; display: block;
            margin-bottom: 4px;
            box-shadow: 0 5px 12px -3px rgba(90,143,141,.55);
        }
        .ui-phone__logo img { width: 100%; height: 100%; object-fit: cover; display: block; }
        .ui-phone__bar {
            width: 92px; height: 6px;
            border-radius: 3px;
            background: #dededc;
            display: block;
        }
        .ui-phone__bar--short { width: 58px; }

        /* iOS 26 Compact toolbar: a floating pill with the ... menu at its
           right edge. No Share icon -- that is exactly the change that made
           the old step 1 wrong. */
        .ui-phone__omni {
            position: absolute;
            left: 12px; right: 12px; bottom: 12px;
            height: 30px;
            background: #ffffff;
            border-radius: 100px;
            box-shadow: 0 3px 10px -2px rgba(0,0,0,.22);
            display: flex; align-items: center; justify-content: center;
            padding: 0 12px;
        }
        .ui-phone__omni-url {
            font-size: 9px; font-weight: 600; color: #4a4b4d;
        }
        /* Square box, not padding around the three dots. The dots are a
           horizontal row, so a padded box is wider than it is tall and
           border-radius:50% draws an oval -- and the highlight box-shadow
           traces that same oval. Fixed equal width/height keeps both the
           button and its ring circular. */
        .ui-phone__dots {
            position: absolute; right: 7px;
            width: 18px; height: 18px;
            display: flex; align-items: center; justify-content: center; gap: 2px;
            border-radius: 50%;
            animation: ui-dots var(--ui-cycle) ease-in-out infinite;
        }
        .ui-phone__dots i {
            width: 2.5px; height: 2.5px; border-radius: 50%;
            background: #6f7072; display: block;
        }
        @keyframes ui-dots {
            0%, 4%    { transform: scale(1);    box-shadow: 0 0 0 0 rgba(90,143,141,0); }
            9%        { transform: scale(1.35); box-shadow: 0 0 0 7px rgba(90,143,141,.3); }
            15%, 100% { transform: scale(1);    box-shadow: 0 0 0 0 rgba(90,143,141,0); }
        }

        .ui-phone__sheet {
            position: absolute;
            left: 0; right: 0; bottom: 0;
            height: 208px;
            background: #f7f7f6;
            border-radius: 16px 16px 0 0;
            box-shadow: 0 -8px 26px -8px rgba(0,0,0,.3);
            padding: 8px 0 0;
            transform: translateY(100%);
            animation: ui-sheet var(--ui-cycle) cubic-bezier(.32,.72,0,1) infinite;
        }
        @keyframes ui-sheet {
            0%, 14%   { transform: translateY(100%); }
            23%, 84%  { transform: translateY(0); }
            92%, 100% { transform: translateY(100%); }
        }
        .ui-phone__sheet-handle {
            width: 32px; height: 3.5px;
            border-radius: 3px;
            background: #cfcfcd;
            margin: 0 auto 9px;
        }

        /* The scroll. .ui-phone__window clips; .ui-phone__list travels up so
           the target row rises from below the fold, which is the thing the
           written steps cannot show. */
        .ui-phone__window {
            height: 160px;
            overflow: hidden;
            position: relative;
        }
        .ui-phone__list {
            animation: ui-scroll var(--ui-cycle) cubic-bezier(.4,0,.2,1) infinite;
        }
        @keyframes ui-scroll {
            0%, 32%   { transform: translateY(0); }
            48%, 92%  { transform: translateY(-58px); }
            100%      { transform: translateY(0); }
        }

        /* Every row shares one padding box so the icons form a single column.
           The highlight is drawn with an inset ring and a background on the
           row itself -- an earlier pass gave the target row `margin: 0 6px`,
           which shifted only that row inward and knocked the whole list out
           of alignment. */
        .ui-phone__row {
            display: flex; align-items: center; gap: 9px;
            padding: 9px 14px;
            font-size: 8.5px;
            font-weight: 500;
            color: #3a3a3c;
            border-radius: 8px;
        }
        .ui-phone__row svg { width: 13px; height: 13px; flex-shrink: 0; }
        .ui-phone__ghost {
            height: 5px; border-radius: 3px;
            background: #dededc;
            flex: 0 0 auto;
            width: 66px;
        }
        .ui-phone__ghost--w2 { width: 50px; }
        .ui-phone__ghost--w3 { width: 58px; }

        .ui-phone__row--target {
            font-weight: 700;
            animation: ui-target var(--ui-cycle) ease-out infinite;
        }
        @keyframes ui-target {
            0%, 48%   { background: transparent;          color: #3a3a3c; box-shadow: 0 0 0 0 rgba(90,143,141,0) inset; }
            58%, 84%  { background: rgba(90,143,141,.15); color: #2f6f6b; box-shadow: 0 0 0 1.5px #5A8F8D inset; }
            92%, 100% { background: transparent;          color: #3a3a3c; box-shadow: 0 0 0 0 rgba(90,143,141,0) inset; }
        }

        /* ---- iOS numbered steps ----
           These render in their final, legible state at all times. An older
           version started them dimmed and only brightened them as the
           animation ran, which left every step failing contrast whenever it
           was paused or reduced. The travelling ring below marks the current
           step without ever touching legibility. */
        .ui-steps { margin: 0 0 4px; padding: 0; list-style: none; }
        .ui-steps li {
            display: flex;
            align-items: flex-start;
            gap: 13px;
            margin-bottom: 14px;
        }
        .ui-step-num {
            width: 26px; height: 26px;
            border-radius: 50%;
            background: #5A8F8D;
            color: #FFFFFF;
            font-size: 12.5px;
            font-weight: 700;
            display: flex; align-items: center; justify-content: center;
            flex-shrink: 0;
            margin-top: 1px;
            animation: ui-stepring var(--ui-cycle, 8s) ease-out infinite;
        }
        /* Offsets land each pulse as the phone above reaches that step:
           ... tap ~0.7s, list settled ~3.9s, confirm ~5.0s. */
        .ui-steps li:nth-child(1) .ui-step-num { animation-delay: 0.15s; }
        .ui-steps li:nth-child(2) .ui-step-num { animation-delay: 3.35s; }
        .ui-steps li:nth-child(3) .ui-step-num { animation-delay: 4.45s; }
        @keyframes ui-stepring {
            0%, 1%    { box-shadow: 0 0 0 0 rgba(90,143,141,0); }
            7%        { box-shadow: 0 0 0 7px rgba(90,143,141,.22); }
            15%, 100% { box-shadow: 0 0 0 0 rgba(90,143,141,0); }
        }
        .ui-steps li p {
            margin: 0;
            font-size: 14px;
            line-height: 1.45;
            color: rgba(255,255,255,0.88);
            padding-top: 2px;
        }
        .ui-steps li p b { color: #FFFFFF; font-weight: 700; }

        .ui-steps-note {
            margin: 2px 0 0;
            padding-left: 39px;
            font-size: 12.5px;
            line-height: 1.45;
            color: rgba(255,255,255,0.5);
        }

        /* ---- In-app browser escape hatch ---- */
        .ui-inapp__title {
            margin: 0 0 8px;
            font-size: 17px; font-weight: 700; color: #FFFFFF;
        }
        .ui-inapp__body {
            margin: 0 0 18px;
            font-size: 13.5px; line-height: 1.55;
            color: rgba(255,255,255,0.7);
        }
        .ui-copy-btn { margin-top: 0; }
        .ui-copy-btn.is-copied { border-color: #4BCB8E; color: #4BCB8E; }

        /* ---- Desktop QR-to-phone ---- */
        .ui-qr {
            width: 200px; height: 200px;
            margin: 4px auto 18px;
            background: #fff;
            border-radius: 18px;
            padding: 12px;
            display: flex; align-items: center; justify-content: center;
            box-shadow: 0 12px 30px -12px rgba(0,0,0,0.6);
        }
        .ui-qr img, .ui-qr canvas { display: block; width: 176px; height: 176px; }
        .ui-qr-cap {
            font-size: 14px; line-height: 1.55;
            color: rgba(255,255,255,.7);
            max-width: 280px; margin: 0 auto;
        }

        /* ---- Single escape link ----
           Replaced two equal-weight outlined cards ("my card" / "discounts").
           They out-shouted the install action and turned the end of
           onboarding into an unexplained fork; this only has to prove the
           page isn't a trap. */
        .ui-skip { margin-top: 26px; text-align: center; }
        .ui-skip__link {
            display: inline-flex; align-items: center; gap: 6px;
            font-size: 13.5px;
        }
        .ui-skip__link svg { width: 14px; height: 14px; }

        /* On desktop there IS no install action -- scanning the QR needs a
           second device most people don't have to hand -- so a page of quiet
           text would read as a trap. The escape link is the primary action
           there and gets promoted to a filled button, the way the old
           .ui-exit--card row was. */
        @media (pointer: fine) and (min-width: 900px) {
            .ui-skip { margin-top: 22px; }
            .ui-skip__link {
                width: 100%; max-width: 340px;
                justify-content: center;
                padding: 15px 24px;
                border-radius: 100px;
                background: #5A8F8D;
                color: #FFFFFF;
                font-size: 15px; font-weight: 600;
                transition: background .15s ease, transform .15s ease;
            }
            .ui-skip__link:hover {
                background: #6BA09E;
                color: #FFFFFF;
                transform: translateY(-1px);
            }
            .ui-skip__link:active { transform: translateY(0); }
        }

        /* ---- iOS Safari bottom pointer ----
           Safari's Share control lives in the bottom toolbar, so the arrow
           is aimed at the real control rather than at a drawing of one.
           The signup shell renders its own <body> without firing
           wp_body_open, so Unimap_Bottom_Nav never mounts here and there is
           nothing at the bottom of /install for this to collide with. */
        .ui-hint {
            position: fixed;
            left: 0; right: 0;
            /* Pinned to 0 and absorbing the inset as PADDING, not as a
               bottom offset. The shell sets viewport-fit=cover, and in iOS
               Safari's browsing mode env(safe-area-inset-bottom) is 0 while
               the toolbar is expanded and ~34px once it collapses on scroll
               -- so `bottom: env(...)` makes the pill visibly jump the first
               time the student scrolls, on the exact page whose arrow is
               pointing at that toolbar. */
            bottom: 0;
            padding: 0 12px calc(10px + env(safe-area-inset-bottom));
            z-index: 60;
            display: flex; flex-direction: column; align-items: center; gap: 2px;
            pointer-events: none;
            opacity: 0;
            transform: translateY(14px);
            transition: opacity .26s ease, transform .26s cubic-bezier(.16,1,.3,1);
        }
        /* The hint is out of flow, so nothing reserves space for it and the
           last of the content would scroll underneath. Class is set by the
           boot script only when the hint actually mounts. */
        body.ui-has-hint .us-main { padding-bottom: calc(112px + env(safe-area-inset-bottom)); }
        .ui-hint.is-in { opacity: 1; transform: translateY(0); }
        .ui-hint__inner {
            pointer-events: auto;
            display: flex; align-items: center; gap: 10px;
            max-width: 420px; width: 100%;
            padding: 11px 12px 11px 14px;
            border-radius: 100px;
            background: #5A8F8D;
            color: #FFFFFF;
            box-shadow: 0 14px 34px -10px rgba(0,0,0,.65);
        }
        .ui-hint__glyph { display: inline-flex; flex: 0 0 auto; }
        .ui-hint__glyph svg { width: 18px; height: 18px; }
        .ui-hint__text {
            flex: 1 1 auto; min-width: 0;
            font-size: 13.5px; font-weight: 600; line-height: 1.3;
        }
        .ui-hint__dismiss {
            flex: 0 0 auto;
            border: 0; cursor: pointer;
            font-family: 'Poppins', sans-serif;
            font-size: 12.5px; font-weight: 600;
            color: #FFFFFF;
            background: rgba(255,255,255,0.2);
            border-radius: 100px;
            padding: 6px 12px;
        }
        .ui-hint__dismiss:hover { background: rgba(255,255,255,0.3); }
        .ui-hint__arrow { color: #5A8F8D; animation: ui-arrow-bob 1.4s ease-in-out infinite; }
        .ui-hint__arrow svg { width: 22px; height: 22px; display: block; }
        @keyframes ui-arrow-bob {
            0%, 100% { transform: translateY(0); }
            50%      { transform: translateY(5px); }
        }


        /* ---- /welcome hero ----
           The confirmation tick, given a halo so it glows instead of sitting
           in a flat chip. A card-face hero was tried here in v0.280.0 and
           pulled: the headline already says "you're in", so a graphic on top
           only competed with the button. .us-icon-hero stays on the wrapper
           because the <=640px block above keys this screen's vertical
           centring off it. */
        .us-icon-hero--halo {
            box-shadow: 0 0 0 10px rgba(75,203,142,0.05),
                        0 16px 38px -14px rgba(75,203,142,0.45);
            animation: uw-hero-in .5s cubic-bezier(.16,1,.3,1) both;
        }
        @keyframes uw-hero-in {
            from { opacity: 0; transform: scale(.82); }
            to   { opacity: 1; transform: scale(1); }
        }

        /* Motion is decorative on both screens -- the layout, colour and
           copy carry the whole message without it. (The /welcome confetti
           burst is gated separately, in render_welcome()'s own script.)

           The Safari walkthrough is the one thing here that carries meaning
           as well as motion, so it isn't simply switched off: it settles into
           its most informative frame instead, with the sheet already open and
           Add to Home Screen highlighted. Stopping it mid-cycle would have
           left the sheet off-screen and the mockup showing nothing. */
        @media (prefers-reduced-motion: reduce) {
            .us-icon-hero--halo,
            .ui-phone__dots,
            .ui-step-num,
            .ui-hint__arrow {
                animation: none;
            }
            .ui-hint { transition: none; }

            .ui-phone__sheet {
                animation: none;
                transform: translateY(0);
            }
            /* Park the list at its scrolled position so the target row is
               visible rather than sitting below the fold. */
            .ui-phone__list {
                animation: none;
                transform: translateY(-58px);
            }
            .ui-phone__row--target {
                animation: none;
                background: rgba(90,143,141,.15);
                color: #2f6f6b;
                box-shadow: 0 0 0 1.5px #5A8F8D inset;
            }
        }

        .ui-inapp__url {
            margin: 0 0 14px;
            padding: 10px 12px;
            border-radius: 10px;
            background: #1C1C1C;
            border: 1px solid rgba(255,255,255,0.10);
            font-family: 'JetBrains Mono', ui-monospace, monospace;
            font-size: 12px;
            line-height: 1.4;
            color: rgba(255,255,255,0.8);
            word-break: break-all;
            -webkit-user-select: all;
            user-select: all;
        }
