Files
orca/src/renderer/src/assets/mobile-page.css
T
Jinjing 787670736c fix(relay): refuse silent fallback when pairing invite fails
When Orca Relay pairing fails, don't silently degrade to a LAN-only QR under the Relay label. Instead, surface structured failure information so the UI can clearly inform the user and offer recovery options.
2026-07-30 01:34:02 -07:00

2161 lines
44 KiB
CSS
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* Why: ported from mobile/orca-mobile-sidebar-mock-v3.html. The mock is the
1:1 design spec for the in-app Mobile page; styles are scoped under
.mobile-page-root so they don't leak into the rest of the app shell. */
.mobile-page-root .mp-page-toolbar {
position: absolute;
top: 12px;
left: 12px;
right: 12px;
z-index: 3;
display: flex;
align-items: flex-start;
justify-content: space-between;
gap: 12px;
}
.mobile-page-root .mp-page-toolbar-primary {
max-width: min(100%, 22rem);
}
.mobile-page-root .mp-sidebar-toggle-btn {
max-width: 100%;
justify-content: flex-start;
font-weight: 600;
text-align: left;
white-space: normal;
}
.mobile-page-root .mp-page-toolbar-close {
margin-top: 1px;
}
.mobile-page-root {
/* Real mobile-app tokens (from mobile/src/theme/mobile-theme.ts) — used
inside .mp-device-screen so simulated screens match the app exactly. */
--mp-flow-card-padding: 24px;
--mp-flow-card-border-width: 1px;
--mp-flow-card-inset: calc(var(--mp-flow-card-padding) + var(--mp-flow-card-border-width));
--mp-flow-shell-height: 400px;
--mp-qr-large-size: 184px;
--m-bg-base: #111111;
--m-bg-panel: #1a1a1a;
--m-bg-raised: #242424;
--m-border: #2a2a2a;
--m-text-primary: #e0e0e0;
--m-text-secondary: #888888;
--m-text-muted: #555555;
--m-accent-blue: #3b82f6;
--m-status-green: #22c55e;
--m-status-amber: #f59e0b;
--m-status-red: #ef4444;
--m-mono: 'Menlo', 'SF Mono', monospace;
position: relative;
container-type: inline-size;
display: block;
width: 100%;
height: 100%;
overflow-x: hidden;
overflow-y: auto;
color: var(--foreground);
}
/* ── Hero ────────────────────────────────────────────────────────── */
.mobile-page-root .mp-hero {
position: relative;
display: grid;
grid-template-columns: minmax(360px, 560px) minmax(300px, 420px);
justify-content: center;
align-items: center;
/* Why: wide canvases need more separation between the intro copy and
phone preview, while narrower desktop widths keep their tighter fit. */
gap: clamp(56px, 7vw, 112px);
padding: 56px;
width: 100%;
min-height: 100%;
background-color: transparent;
/* Why: the page should feel branded without putting copy over decorative
blobs; a token-based dot texture stays quiet in both themes. */
background-image: radial-gradient(
circle,
color-mix(in srgb, var(--foreground) 8%, transparent) 1px,
transparent 1.2px
);
background-size: 5px 5px;
background-repeat: repeat;
}
.mobile-page-root .mp-hero-copy {
position: relative;
z-index: 1;
max-width: 560px;
display: flex;
flex-direction: column;
/* Why: min-height (rather than fixed height) keeps the intro/flow
screens at a uniform 400px box for centering, while letting the
paired view grow when the device list needs more room. */
min-height: var(--mp-flow-shell-height);
}
.mobile-page-root .mp-hero-copy > * {
flex: 1 1 auto;
display: flex;
flex-direction: column;
}
.mobile-page-root .mp-intro-shell,
.mobile-page-root .mp-flow-card {
min-height: var(--mp-flow-shell-height);
}
.mobile-page-root .mp-eyebrow-row {
display: flex;
align-items: center;
gap: 12px;
margin-bottom: 22px;
}
.mobile-page-root .mp-eyebrow {
color: var(--muted-foreground);
font-size: 14px;
font-weight: 600;
letter-spacing: 0;
text-transform: uppercase;
}
.mobile-page-root .mp-h1 {
margin: 0;
color: var(--foreground);
font-size: 60px;
font-weight: 650;
letter-spacing: 0;
line-height: 1.06;
}
.mobile-page-root .mp-lead {
max-width: 580px;
margin: 20px 0 22px;
color: var(--muted-foreground);
font-size: 18px;
font-weight: 450;
line-height: 1.55;
}
.mobile-page-root .mp-platform-badges {
display: flex;
align-items: center;
gap: 8px;
flex-wrap: wrap;
margin: 0 0 18px;
}
.mobile-page-root .mp-platform-label {
color: var(--muted-foreground);
font-size: 13px;
font-weight: 600;
}
.mobile-page-root .mp-platform-badge {
display: inline-flex;
align-items: center;
gap: 6px;
min-height: 30px;
padding: 0 11px;
border: 1px solid var(--border);
border-radius: 999px;
background: var(--card);
color: var(--foreground);
font-size: 13px;
font-weight: 600;
}
.mobile-page-root .mp-platform-brand-icon {
width: 16px;
height: 16px;
flex: 0 0 16px;
fill: currentColor;
}
.mobile-page-root .mp-paired-list {
list-style: none;
margin: 18px 0 0;
/* Why: right padding reserves space for the scrollbar so it doesn't
sit on top of the row's right edge when the list overflows. */
padding: 0 12px 0 0;
display: flex;
flex-direction: column;
gap: 8px;
max-width: 452px;
/* Why: cap so 4 rows fit fully and the 5th onward scrolls. Rows render
at ~64px each plus 8px gap, so 4 × 64 + 3 × 8 ≈ 280px. */
max-height: 288px;
overflow-y: auto;
scrollbar-width: none;
}
.mobile-page-root .mp-paired-list::-webkit-scrollbar {
display: none;
}
.mobile-page-root .mp-paired-row {
display: flex;
align-items: center;
gap: 12px;
padding: 10px 12px;
border: 1px solid var(--border);
border-radius: 10px;
background: var(--card);
}
.mobile-page-root .mp-paired-icon {
display: grid;
place-items: center;
width: 32px;
height: 32px;
border-radius: 8px;
background: color-mix(in srgb, var(--foreground) 6%, transparent);
color: var(--foreground);
}
.mobile-page-root .mp-paired-icon svg {
width: 16px;
height: 16px;
}
.mobile-page-root .mp-paired-main {
flex: 1 1 auto;
min-width: 0;
}
.mobile-page-root .mp-paired-name {
color: var(--foreground);
font-size: 14px;
font-weight: 600;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.mobile-page-root .mp-paired-meta {
color: var(--muted-foreground);
font-size: 12px;
margin-top: 2px;
}
.mobile-page-root .mp-paired-revoke {
display: inline-flex;
align-items: center;
justify-content: center;
width: 32px;
height: 32px;
border: 0;
border-radius: 8px;
background: transparent;
color: var(--muted-foreground);
cursor: pointer;
transition:
background-color 120ms ease,
color 120ms ease;
}
.mobile-page-root .mp-paired-revoke:hover:not([disabled]) {
background: color-mix(in srgb, var(--destructive, oklch(0.6 0.2 25)) 12%, transparent);
color: var(--destructive, oklch(0.6 0.2 25));
}
.mobile-page-root .mp-paired-revoke[disabled] {
opacity: 0.4;
cursor: not-allowed;
}
.mobile-page-root .mp-paired-revoke svg {
width: 14px;
height: 14px;
}
.mobile-page-root .mp-cta-row {
display: flex;
align-items: center;
justify-content: flex-start;
gap: 14px;
margin-top: auto;
padding-top: 16px;
/* Why: the intro CTA should scan with the hero copy, while step-flow
actions keep their own placement inside the card. */
padding-bottom: var(--mp-flow-card-inset);
}
.mobile-page-root .mp-primary-action {
box-sizing: border-box;
display: inline-flex;
align-items: center;
gap: 8px;
height: 40px;
border: 0;
border-radius: 999px;
background: var(--primary);
color: var(--primary-foreground);
padding: 0 18px;
font-size: 13px;
font-weight: 600;
line-height: 1;
cursor: pointer;
transition:
background 140ms ease,
color 140ms ease;
}
.mobile-page-root .mp-primary-action svg {
width: 13px;
height: 13px;
}
.mobile-page-root .mp-flow-primary-action {
width: 150px;
justify-content: center;
white-space: nowrap;
}
.mobile-page-root .mp-secondary-action {
box-sizing: border-box;
display: inline-flex;
align-items: center;
gap: 8px;
min-height: 36px;
border: 1px solid var(--border);
border-radius: 999px;
background: var(--card);
color: var(--foreground);
padding: 0 14px;
font-size: 13px;
font-weight: 600;
line-height: 1;
cursor: pointer;
transition:
background-color 140ms ease,
color 140ms ease;
}
.mobile-page-root .mp-secondary-action:hover {
background: var(--accent);
}
/* Step flow ─────────────────────────────────────────────────────── */
.mobile-page-root .mp-flow-card {
display: flex;
flex-direction: column;
flex: 1 1 auto;
padding: var(--mp-flow-card-padding);
border: var(--mp-flow-card-border-width) solid var(--border);
border-radius: var(--radius-xl);
background: color-mix(in srgb, var(--card) 94%, var(--background));
color: var(--card-foreground);
}
.mobile-page-root .mp-flow-header {
margin-bottom: 24px;
}
.mobile-page-root .mp-flow-step-head {
position: relative;
display: flex;
align-items: center;
gap: 12px;
}
.mobile-page-root .mp-step-num {
display: grid;
width: 26px;
height: 26px;
place-items: center;
border: 1px solid var(--border);
border-radius: 999px;
background: color-mix(in srgb, var(--foreground) 4%, transparent);
color: var(--foreground);
font-size: 12px;
font-weight: 600;
}
.mobile-page-root .mp-step-title {
font-size: 18px;
font-weight: 650;
color: var(--foreground);
}
/* Why: only the active step contributes to layout; the measured height lets
the card grow for Step 2 without making the shorter Step 1 oversized. */
.mobile-page-root .mp-flow-viewport {
position: relative;
overflow: hidden;
transition: height 280ms cubic-bezier(0.32, 0.72, 0.24, 1);
}
.mobile-page-root .mp-flow-screen {
position: absolute;
top: 0;
left: 0;
width: 100%;
transform: translateX(40px);
opacity: 0;
pointer-events: none;
transition:
transform 280ms cubic-bezier(0.32, 0.72, 0.24, 1),
opacity 200ms ease;
}
.mobile-page-root .mp-flow-screen.is-active {
position: relative;
transform: translateX(0);
opacity: 1;
pointer-events: auto;
}
.mobile-page-root .mp-flow-screen.is-past {
transform: translateX(-40px);
opacity: 0;
}
.mobile-page-root .mp-flow-actions {
display: flex;
align-items: center;
justify-content: space-between;
margin-top: auto;
padding-top: 16px;
/* Why: keep row height stable across steps so the back button doesn't jump
vertically when the right side switches between a 40px Continue button
and a placeholder span. */
min-height: calc(40px + 16px);
}
.mobile-page-root .mp-flow-continue {
box-sizing: border-box;
display: inline-flex;
align-items: center;
gap: 8px;
height: 40px;
padding: 0 18px;
border: 0;
border-radius: 999px;
font-size: 13px;
font-weight: 600;
line-height: 1;
cursor: pointer;
background: var(--primary);
color: var(--primary-foreground);
transition:
background 140ms ease,
color 140ms ease,
opacity 140ms ease;
}
.mobile-page-root .mp-flow-continue svg {
width: 13px;
height: 13px;
}
.mobile-page-root .mp-flow-back {
display: inline-flex;
align-items: center;
gap: 6px;
background: transparent;
border: 0;
padding: 0;
color: var(--muted-foreground);
font-size: 13px;
font-weight: 500;
text-decoration: underline;
text-underline-offset: 3px;
cursor: pointer;
transition: color 140ms ease;
}
.mobile-page-root .mp-flow-back:hover {
color: var(--foreground);
}
.mobile-page-root .mp-flow-back svg {
width: 12px;
height: 12px;
}
.mobile-page-root .mp-flow-continue.is-hidden {
visibility: hidden;
pointer-events: none;
}
.mobile-page-root .mp-step-body {
color: var(--muted-foreground);
font-size: 13px;
line-height: 1.55;
}
.mobile-page-root .mp-platform-toggle {
display: inline-flex;
margin: 12px 0;
padding: 3px;
border: 1px solid var(--border);
border-radius: 999px;
background: color-mix(in srgb, var(--foreground) 4%, transparent);
}
.mobile-page-root .mp-platform-toggle button {
display: inline-flex;
align-items: center;
gap: 6px;
border: 0;
padding: 5px 12px;
border-radius: 999px;
background: transparent;
color: var(--muted-foreground);
font-size: 12px;
font-weight: 600;
cursor: pointer;
}
.mobile-page-root .mp-platform-toggle button.is-active {
background: var(--foreground);
color: var(--background);
}
.mobile-page-root .mp-install-row {
display: flex;
align-items: center;
justify-content: space-between;
gap: 16px;
margin-top: 4px;
padding: 16px;
border: 1px solid var(--border);
border-radius: 12px;
background: color-mix(in srgb, var(--foreground) 3%, transparent);
color: var(--foreground);
font-size: 13px;
}
.mobile-page-root .mp-install-row > div:first-child {
flex: 1;
}
.mobile-page-root .mp-small-actions {
display: flex;
gap: 8px;
margin-top: 10px;
}
.mobile-page-root .mp-ghost-action {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 6px 12px;
border: 1px solid var(--border);
border-radius: 999px;
background: transparent;
color: var(--foreground);
font-size: 12px;
font-weight: 500;
cursor: pointer;
}
.mobile-page-root .mp-ghost-action:hover {
background: color-mix(in srgb, var(--foreground) 6%, transparent);
}
.mobile-page-root .mp-ghost-action svg {
width: 12px;
height: 12px;
}
.mobile-page-root .mp-qr {
position: relative;
display: grid;
place-items: center;
overflow: hidden;
padding: 8px;
border-radius: 12px;
background: #fafafa;
}
.mobile-page-root .mp-qr img {
display: block;
width: 116px;
height: 116px;
}
.mobile-page-root .mp-qr-large {
box-sizing: border-box;
width: var(--mp-qr-large-size);
height: var(--mp-qr-large-size);
/* Why: keep img size in lockstep with the box (padding 10px each side). */
padding: 10px;
}
.mobile-page-root .mp-qr-large img {
width: calc(var(--mp-qr-large-size) - 20px);
height: calc(var(--mp-qr-large-size) - 20px);
}
.mobile-page-root .mp-qr-refreshing {
filter: blur(5px);
opacity: 0.32;
}
.mobile-page-root .mp-qr-loading {
position: absolute;
inset: 10px;
display: grid;
place-items: center;
border-radius: 4px;
background: color-mix(in srgb, var(--background) 76%, transparent);
color: var(--foreground);
font-size: 12px;
font-weight: 600;
}
/* Why: empty QR frames need readable copy without looking like a stuck loader overlay. */
.mobile-page-root .mp-qr-empty {
position: absolute;
inset: 10px;
display: grid;
place-items: center;
border-radius: 4px;
color: var(--muted-foreground);
font-size: 12px;
font-weight: 500;
line-height: 1.35;
text-wrap: balance;
}
.mobile-page-root .mp-qr-stack {
display: flex;
flex-direction: column;
align-items: center;
gap: 10px;
/* Why: stack sits in a fixed QR grid track; fill the track so under-QR copy
has a definite width to wrap against. */
box-sizing: border-box;
width: 100%;
min-width: 0;
}
/* Why: align-items:center sizes children to max-content. Cap width AND set
min-width:0 so max-width can actually win over flex/grid min-size:auto and
long under-QR copy (relay-degraded notice, regenerate label) wraps. */
.mobile-page-root .mp-qr-stack > * {
max-width: 100%;
min-width: 0;
}
.mobile-page-root .mp-link-under {
background: transparent;
border: 0;
padding: 0;
color: var(--muted-foreground);
font-size: 12px;
font-weight: 500;
text-decoration: underline;
text-underline-offset: 3px;
cursor: pointer;
transition: color 140ms ease;
}
.mobile-page-root .mp-link-under:hover:not([disabled]) {
color: var(--foreground);
}
.mobile-page-root .mp-link-under[disabled] {
opacity: 0.5;
cursor: not-allowed;
}
/* Step 1 (Get the app) + Step 2 (Pair) — QR column width */
/* Why: pin the QR column to the QR's own width rather than `auto`. When the flow
card is narrow (mp-hero pins it to minmax(360px,560px)) an `auto` track grows
to its content's max-content — the relay-degraded notice under the pairing QR
is an unwrapped single line — starving the minmax(0,1fr) copy column to ~1 char
wide, so CJK copy wrapped one glyph per line (#9700). A fixed track stops that
starvation; .mp-qr-stack min-width:0 + max-width:100% (and the notice's
min-w-0 text span) stop the notice overflowing the track. */
.mobile-page-root .mp-step2-layout {
display: grid;
grid-template-columns: minmax(0, 1fr) var(--mp-qr-large-size);
gap: 28px;
align-items: start;
}
.mobile-page-root .mp-pairing-layout {
display: grid;
grid-template-columns: minmax(0, 1fr) var(--mp-qr-large-size);
grid-template-areas:
'copy qr'
'relay qr'
'controls controls';
column-gap: 32px;
row-gap: 18px;
align-items: start;
}
.mobile-page-root .mp-pairing-layout.has-failure {
grid-template-areas:
'copy qr'
'relay qr'
'failure failure'
'controls controls';
}
.mobile-page-root .mp-pairing-copy {
grid-area: copy;
min-width: 0;
}
.mobile-page-root .mp-pairing-qr {
grid-area: qr;
min-width: 0;
/* Why: the QR belongs to the pairing heading, not the paragraph below it. */
margin-top: 48px;
}
.mobile-page-root .mp-pairing-relay {
grid-area: relay;
min-width: 0;
}
.mobile-page-root .mp-pairing-controls {
grid-area: controls;
min-width: 0;
}
.mobile-page-root .mp-pairing-failure {
grid-area: failure;
}
/* Why: align the QR's top with the body copy ("Scan the QR…") instead
of the eyebrow row above it. The eyebrow row is ~22px tall + 22px
margin-bottom, and the h2 is ~38px line-height with no top margin —
so push the QR down by roughly that combined height. */
.mobile-page-root .mp-step2-layout > .mp-qr,
.mobile-page-root .mp-step2-layout > .mp-qr-stack {
margin-top: 72px;
}
.mobile-page-root .mp-step2-copy {
min-width: 0;
}
.mobile-page-root .mp-h2 {
margin: 0;
color: var(--foreground);
font-size: 34px;
font-weight: 650;
letter-spacing: 0;
line-height: 1.08;
}
.mobile-page-root .mp-lead-sm {
max-width: 420px;
margin: 14px 0 22px;
color: var(--muted-foreground);
font-size: 15px;
font-weight: 450;
line-height: 1.55;
}
.mobile-page-root .mp-tab-toggle {
display: inline-flex;
gap: 18px;
margin: 2px 0 22px;
}
.mobile-page-root .mp-tab-toggle button {
display: inline-flex;
align-items: center;
gap: 6px;
border: 0;
background: transparent;
padding: 0 0 6px;
color: var(--muted-foreground);
font-size: 13px;
font-weight: 600;
cursor: pointer;
border-bottom: 1.5px solid transparent;
transition:
color 140ms ease,
border-color 140ms ease;
}
.mobile-page-root .mp-tab-toggle button.is-active {
color: var(--foreground);
border-bottom-color: var(--foreground);
}
/* iOS release-channel switch (Preview vs Stable), shown above the install CTA */
.mobile-page-root .mp-channel-toggle {
display: inline-flex;
align-items: center;
gap: 4px;
margin: -8px 0 18px;
flex-wrap: wrap;
}
.mobile-page-root .mp-channel-toggle button {
border: 1px solid var(--border);
background: transparent;
padding: 4px 12px;
border-radius: 999px;
color: var(--muted-foreground);
font-size: 12px;
font-weight: 600;
cursor: pointer;
transition:
background-color 140ms ease,
color 140ms ease,
border-color 140ms ease;
}
.mobile-page-root .mp-channel-toggle button.is-active {
background: color-mix(in srgb, var(--foreground) 8%, transparent);
border-color: color-mix(in srgb, var(--foreground) 20%, transparent);
color: var(--foreground);
}
.mobile-page-root .mp-channel-tagline {
margin-left: 6px;
color: var(--muted-foreground);
font-size: 12px;
}
.mobile-page-root .mp-inline-actions {
display: flex;
align-items: center;
gap: 14px;
flex-wrap: wrap;
}
.mobile-page-root .mp-text-link {
display: inline-flex;
align-items: center;
gap: 6px;
background: transparent;
border: 0;
padding: 0;
color: var(--foreground);
font-size: 13px;
font-weight: 600;
cursor: pointer;
opacity: 0.85;
transition: opacity 140ms ease;
}
.mobile-page-root .mp-text-link:hover {
opacity: 1;
}
.mobile-page-root .mp-text-link svg {
width: 13px;
height: 13px;
}
.mobile-page-root .mp-text-link[disabled] {
opacity: 0.45;
cursor: not-allowed;
}
.mobile-page-root .mp-network-row {
display: flex;
align-items: center;
gap: 10px;
margin: 0 0 18px;
flex-wrap: wrap;
font-size: 13px;
}
.mobile-page-root .mp-network-label {
color: var(--muted-foreground);
font-weight: 600;
}
.mobile-page-root .mp-network-select {
flex: 1 1 180px;
min-width: 0;
max-width: 240px;
}
.mobile-page-root .mp-network-refresh {
display: inline-flex;
align-items: center;
justify-content: center;
width: 28px;
height: 28px;
border: 1px solid var(--border);
border-radius: 8px;
background: transparent;
color: var(--muted-foreground);
cursor: pointer;
transition:
background-color 120ms ease,
color 120ms ease;
}
.mobile-page-root .mp-network-refresh:hover:not([disabled]) {
background-color: color-mix(in srgb, var(--foreground) 6%, transparent);
color: var(--foreground);
}
.mobile-page-root .mp-network-refresh[disabled] {
opacity: 0.5;
cursor: not-allowed;
}
.mobile-page-root .mp-network-refresh svg {
width: 14px;
height: 14px;
}
.mobile-page-root .mp-network-refresh.is-spinning svg {
animation: mp-network-refresh-spin 900ms linear infinite;
}
@keyframes mp-network-refresh-spin {
to {
transform: rotate(360deg);
}
}
.mobile-page-root .mp-action-divider {
color: var(--muted-foreground);
font-size: 12px;
opacity: 0.6;
}
/* Pairing settings card */
.mobile-page-root .mp-pair-settings {
margin-top: 12px;
background: var(--m-bg-panel);
border-radius: 12px;
overflow: hidden;
}
.mobile-page-root .mp-pair-settings + .mp-pair-settings {
margin-top: 12px;
}
.mobile-page-root .mp-pair-row {
display: flex;
align-items: center;
gap: 10px;
padding: 12px 14px;
color: var(--m-text-primary);
font-size: 14px;
font-weight: 500;
}
.mobile-page-root .mp-pair-row .mp-pair-icon {
display: grid;
place-items: center;
width: 16px;
height: 16px;
color: var(--m-text-secondary);
flex-shrink: 0;
}
.mobile-page-root .mp-pair-row .mp-pair-icon svg {
width: 16px;
height: 16px;
}
.mobile-page-root .mp-pair-row .mp-pair-label {
flex: 1;
color: var(--m-text-primary);
font-size: 14px;
font-weight: 500;
}
.mobile-page-root .mp-pair-row .mp-pair-value {
color: var(--m-text-muted);
font-family: var(--m-mono);
font-size: 12px;
}
.mobile-page-root .mp-pair-row.mp-pair-row-qr {
align-items: flex-start;
}
.mobile-page-root .mp-pair-row.mp-pair-row-qr .mp-pair-label {
padding-top: 4px;
}
.mobile-page-root .mp-pair-separator {
height: 1px;
background: var(--m-border);
margin: 0 14px;
}
.mobile-page-root .mp-pair-action-row {
display: flex;
align-items: center;
gap: 10px;
width: 100%;
padding: 12px 14px;
background: transparent;
border: 0;
color: var(--m-text-primary);
font-size: 14px;
font-weight: 500;
text-align: left;
cursor: pointer;
}
.mobile-page-root .mp-pair-action-row:hover {
background: var(--m-bg-raised);
}
.mobile-page-root .mp-pair-action-row .mp-pair-icon svg {
width: 16px;
height: 16px;
}
.mobile-page-root .mp-pair-action-row .mp-pair-label {
flex: 1;
}
.mobile-page-root .mp-pair-action-row .mp-pair-meta {
color: var(--m-text-muted);
font-size: 12px;
}
.mobile-page-root .mp-pair-action-row:disabled {
cursor: default;
opacity: 0.6;
}
/* ── Phone stage ────────────────────────────────────────────────── */
.mobile-page-root .mp-stage {
position: relative;
z-index: 1;
display: grid;
place-items: center;
min-height: 0;
height: min(100%, calc(100vh - 112px));
}
.mobile-page-root .mp-phone-frame {
position: relative;
width: min(100%, 420px, calc((100vh - 112px) * 9 / 19.5));
aspect-ratio: 9 / 19.5;
border-radius: 48px;
background: #0a0a0a;
padding: 7px;
box-shadow:
0 0 0 1px color-mix(in srgb, var(--foreground) 14%, transparent),
0 50px 100px -30px rgba(0, 0, 0, 0.7);
}
.mobile-page-root .mp-phone-screen {
position: relative;
width: 100%;
height: 100%;
overflow: hidden;
border-radius: 41px;
background: var(--m-bg-base);
/* Why: Chromium occasionally fails to clip transformed children to a
rounded-corner overflow:hidden ancestor. Forcing a paint containment
boundary guarantees the off-screen slide can't leak past the bezel. */
contain: paint;
isolation: isolate;
}
.mobile-page-root .mp-screen-slide {
position: absolute;
inset: 0;
transform: translateX(100%);
transition: transform 320ms cubic-bezier(0.32, 0.72, 0.24, 1);
pointer-events: none;
will-change: transform;
}
.mobile-page-root .mp-screen-slide.is-active {
transform: translateX(0);
pointer-events: auto;
}
.mobile-page-root .mp-screen-slide.is-past {
transform: translateX(-22%);
}
.mobile-page-root .mp-screen-slide.is-reset {
transition: none;
}
@keyframes mp-tap-pulse {
0%,
100% {
box-shadow: inset 0 0 0 0 transparent;
}
20%,
70% {
box-shadow: inset 0 0 0 200px var(--m-bg-raised);
}
}
.mobile-page-root .is-tapping {
animation: mp-tap-pulse 280ms ease-out;
}
/* ── Simulated mobile-app screens (real tokens) ─────────────────── */
.mobile-page-root .mp-device-screen {
display: flex;
width: 100%;
height: 100%;
flex-direction: column;
background: var(--m-bg-base);
color: var(--m-text-primary);
font-family:
'Geist',
-apple-system,
BlinkMacSystemFont,
'Segoe UI',
sans-serif;
font-size: 13px;
box-sizing: border-box;
/* Why: the phone frame is viewport-fit now; the preview content must stay
legible without reintroducing the clipped, over-zoomed mobile mock. */
zoom: 1.08;
}
.mobile-page-root .mp-wl-chrome,
.mobile-page-root .mp-session-chrome {
padding-top: 18px;
}
/* Top bar */
.mobile-page-root .mp-app-topbar {
display: flex;
align-items: center;
justify-content: space-between;
padding: 26px 16px 12px;
}
.mobile-page-root .mp-app-brand {
display: flex;
align-items: center;
gap: 8px;
}
.mobile-page-root .mp-app-brand .mp-orca-logo {
width: 28px;
height: 18px;
color: var(--m-text-primary);
}
.mobile-page-root .mp-app-brand-name {
color: var(--m-text-primary);
font-size: 17px;
font-weight: 700;
}
.mobile-page-root .mp-icon-button {
display: grid;
width: 36px;
height: 36px;
place-items: center;
border: 0;
border-radius: 18px;
background: transparent;
color: var(--m-text-secondary);
}
.mobile-page-root .mp-icon-button svg {
width: 18px;
height: 18px;
stroke-width: 1.75;
}
.mobile-page-root .mp-scroll-region {
flex: 1;
overflow: hidden;
padding: 0 16px 16px;
}
.mobile-page-root .mp-greeting {
padding: 6px 4px 10px;
}
.mobile-page-root .mp-greeting-title {
color: var(--m-text-primary);
font-size: 22px;
font-weight: 800;
letter-spacing: 0;
}
.mobile-page-root .mp-stat-row {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 8px;
margin-bottom: 16px;
}
.mobile-page-root .mp-stat-card {
border: 1px solid var(--m-border);
border-radius: 10px;
background: rgba(26, 26, 26, 0.6);
padding: 8px 10px;
}
.mobile-page-root .mp-stat-value {
color: var(--m-text-primary);
font-size: 17px;
font-weight: 700;
letter-spacing: 0;
}
.mobile-page-root .mp-stat-label {
margin-top: 1px;
color: var(--m-text-muted);
font-size: 10px;
font-weight: 500;
white-space: nowrap;
}
.mobile-page-root .mp-section-label {
margin: 0 0 6px;
padding-left: 4px;
color: var(--m-text-muted);
font-size: 10px;
font-weight: 600;
letter-spacing: 0.06em;
text-transform: uppercase;
}
/* Host card */
.mobile-page-root .mp-host-card {
display: flex;
align-items: center;
min-height: 60px;
padding: 10px 12px;
gap: 12px;
border: 1px solid var(--m-border);
border-radius: 14px;
background: var(--m-bg-panel);
}
.mobile-page-root .mp-host-card + .mp-host-card {
margin-top: 6px;
}
.mobile-page-root .mp-host-icon {
display: grid;
width: 38px;
height: 38px;
place-items: center;
border-radius: 11px;
background: var(--m-bg-raised);
color: var(--m-text-primary);
}
.mobile-page-root .mp-host-icon svg {
width: 18px;
height: 18px;
stroke-width: 1.75;
}
.mobile-page-root .mp-host-icon.is-dim {
color: var(--m-text-secondary);
}
.mobile-page-root .mp-host-main {
flex: 1;
min-width: 0;
}
.mobile-page-root .mp-host-name {
color: var(--m-text-primary);
font-size: 14px;
font-weight: 600;
line-height: 18px;
}
.mobile-page-root .mp-host-name.is-dim {
color: var(--m-text-secondary);
}
.mobile-page-root .mp-host-meta {
display: flex;
align-items: center;
gap: 6px;
margin-top: 2px;
color: var(--m-text-secondary);
font-size: 11px;
white-space: nowrap;
}
.mobile-page-root .mp-status-dot {
width: 7px;
height: 7px;
border-radius: 999px;
flex: 0 0 auto;
}
.mobile-page-root .mp-status-dot.is-green {
background: var(--m-status-green);
}
.mobile-page-root .mp-status-dot.is-amber {
background: var(--m-status-amber);
}
.mobile-page-root .mp-status-dot.is-muted {
background: var(--m-text-muted);
}
.mobile-page-root .mp-chevron-right {
color: var(--m-text-muted);
}
.mobile-page-root .mp-chevron-right svg {
width: 16px;
height: 16px;
stroke-width: 1.75;
}
/* Resume card */
.mobile-page-root .mp-resume-card {
display: flex;
align-items: center;
padding: 10px 12px;
gap: 12px;
border: 1px solid var(--m-border);
border-radius: 14px;
background: var(--m-bg-panel);
}
.mobile-page-root .mp-resume-icon {
display: grid;
width: 38px;
height: 38px;
place-items: center;
border-radius: 11px;
background: var(--m-bg-raised);
color: var(--m-text-secondary);
}
.mobile-page-root .mp-resume-icon svg {
width: 16px;
height: 16px;
stroke-width: 1.75;
}
.mobile-page-root .mp-resume-title {
color: var(--m-text-primary);
font-size: 13px;
font-weight: 600;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.mobile-page-root .mp-resume-sub {
display: flex;
align-items: center;
gap: 6px;
margin-top: 2px;
color: var(--m-text-secondary);
font-size: 11px;
min-width: 0;
}
/* Why: keep long repo/branch labels inside the phone frame (matches RN numberOfLines={1}). */
.mobile-page-root .mp-resume-sub > span:not(.mp-repo-dot) {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
min-width: 0;
}
.mobile-page-root .mp-repo-dot {
width: 7px;
height: 7px;
border-radius: 999px;
flex: 0 0 auto;
}
/* Quick actions */
.mobile-page-root .mp-quick-actions {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 8px;
margin-bottom: 8px;
}
.mobile-page-root .mp-quick-action {
display: flex;
align-items: center;
gap: 10px;
padding: 10px 12px;
border: 1px solid var(--m-border);
border-radius: 14px;
background: var(--m-bg-panel);
}
.mobile-page-root .mp-quick-action-icon {
display: grid;
width: 28px;
height: 28px;
place-items: center;
border-radius: 9px;
background: rgba(255, 255, 255, 0.04);
color: var(--m-text-secondary);
}
.mobile-page-root .mp-quick-action-icon svg {
width: 16px;
height: 16px;
stroke-width: 1.75;
}
.mobile-page-root .mp-quick-action-label {
color: var(--m-text-secondary);
font-size: 12px;
font-weight: 600;
white-space: nowrap;
}
/* Tasks home card */
.mobile-page-root .mp-task-home-card {
display: flex;
align-items: center;
padding: 10px 12px;
gap: 12px;
border: 1px solid var(--m-border);
border-radius: 14px;
background: var(--m-bg-panel);
}
.mobile-page-root .mp-task-home-icon {
display: grid;
width: 38px;
height: 38px;
place-items: center;
border-radius: 11px;
background: var(--m-bg-raised);
color: var(--m-text-secondary);
}
.mobile-page-root .mp-task-home-icon svg {
width: 16px;
height: 16px;
stroke-width: 1.75;
}
.mobile-page-root .mp-task-home-title {
color: var(--m-text-primary);
font-size: 13px;
font-weight: 600;
}
.mobile-page-root .mp-task-home-subtitle {
margin-top: 2px;
color: var(--m-text-secondary);
font-size: 11px;
}
.mobile-page-root .mp-task-home-providers {
display: flex;
align-items: center;
gap: 2px;
margin-left: 8px;
}
.mobile-page-root .mp-task-home-provider-button {
display: grid;
width: 34px;
height: 34px;
place-items: center;
border-radius: 6px;
color: var(--m-text-secondary);
}
.mobile-page-root .mp-task-home-provider-button svg {
width: 22px;
height: 22px;
stroke-width: 1.75;
}
/* Account usage */
.mobile-page-root .mp-accounts-card {
background: var(--m-bg-panel);
border: 1px solid var(--m-border);
border-radius: 14px;
padding: 10px 12px;
display: flex;
flex-direction: column;
gap: 8px;
}
.mobile-page-root .mp-accounts-row {
display: flex;
align-items: center;
gap: 10px;
}
.mobile-page-root .mp-accounts-icon {
display: grid;
width: 32px;
height: 32px;
place-items: center;
border-radius: 9px;
background: var(--m-bg-raised);
color: var(--m-text-primary);
}
.mobile-page-root .mp-accounts-icon svg {
width: 18px;
height: 18px;
}
.mobile-page-root .mp-accounts-info {
flex: 1;
min-width: 0;
display: flex;
flex-direction: column;
gap: 2px;
}
.mobile-page-root .mp-accounts-email {
color: var(--m-text-primary);
font-size: 13px;
font-weight: 600;
}
.mobile-page-root .mp-accounts-bars {
display: flex;
gap: 12px;
margin-top: 4px;
}
.mobile-page-root .mp-usage-bar {
flex: 1;
display: flex;
align-items: center;
gap: 6px;
}
.mobile-page-root .mp-usage-bar-label {
color: var(--m-text-muted);
font-size: 11px;
font-weight: 600;
min-width: 16px;
}
.mobile-page-root .mp-usage-bar-track {
flex: 1;
height: 4px;
border-radius: 999px;
background: var(--m-bg-raised);
overflow: hidden;
}
.mobile-page-root .mp-usage-bar-fill {
height: 100%;
background: var(--m-text-secondary);
border-radius: inherit;
}
/* ── Worktree-list screen ───────────────────────────────────────── */
.mobile-page-root .mp-wl-chrome {
background: var(--m-bg-panel);
border-bottom: 1px solid var(--m-border);
}
.mobile-page-root .mp-wl-statusrow {
display: flex;
align-items: center;
gap: 10px;
padding: 4px 16px 0;
min-height: 34px;
}
.mobile-page-root .mp-wl-back {
display: grid;
width: 32px;
height: 32px;
place-items: center;
margin-right: 4px;
color: var(--m-text-primary);
}
.mobile-page-root .mp-wl-back svg {
width: 22px;
height: 22px;
stroke-width: 1.75;
}
.mobile-page-root .mp-wl-host {
display: flex;
align-items: center;
gap: 8px;
flex: 1;
min-width: 0;
}
.mobile-page-root .mp-wl-host-name {
color: var(--m-text-primary);
font-size: 15px;
font-weight: 600;
}
.mobile-page-root .mp-wl-toolbar {
display: flex;
align-items: center;
gap: 8px;
padding: 6px 12px;
border-bottom: 1px solid var(--m-border);
}
.mobile-page-root .mp-wl-chip {
display: flex;
align-items: center;
gap: 4px;
padding: 4px 10px;
border: 1px solid var(--m-border);
border-radius: 12px;
color: var(--m-text-secondary);
font-size: 12px;
}
.mobile-page-root .mp-wl-chip svg {
width: 12px;
height: 12px;
stroke-width: 1.75;
}
.mobile-page-root .mp-wl-button {
display: flex;
align-items: center;
gap: 4px;
padding: 4px 8px;
color: var(--m-text-secondary);
font-size: 12px;
}
.mobile-page-root .mp-wl-button svg {
width: 14px;
height: 14px;
stroke-width: 1.75;
}
.mobile-page-root .mp-wl-spacer {
flex: 1;
}
.mobile-page-root .mp-wl-icon {
display: grid;
width: 24px;
height: 24px;
place-items: center;
color: var(--m-text-secondary);
}
.mobile-page-root .mp-wl-icon svg {
width: 16px;
height: 16px;
stroke-width: 1.75;
}
.mobile-page-root .mp-wl-section {
display: flex;
align-items: center;
gap: 4px;
padding: 12px 16px 4px;
color: var(--m-text-muted);
font-size: 11px;
font-weight: 600;
letter-spacing: 0.06em;
text-transform: uppercase;
}
.mobile-page-root .mp-wl-section svg {
width: 12px;
height: 12px;
stroke-width: 2;
}
.mobile-page-root .mp-wl-list {
display: flex;
flex-direction: column;
}
.mobile-page-root .mp-wl-row {
display: flex;
align-items: flex-start;
padding: 10px 16px;
gap: 8px;
}
.mobile-page-root .mp-wl-sep {
height: 1px;
margin-left: 40px;
margin-right: 16px;
background: var(--m-border);
}
.mobile-page-root .mp-wl-indicator {
display: grid;
width: 20px;
place-items: center;
padding-top: 6px;
}
.mobile-page-root .mp-wl-spinner {
width: 8px;
height: 8px;
border-radius: 4px;
border: 2px solid #eab308;
border-top-color: transparent;
animation: mp-wl-spin 1s linear infinite;
}
.mobile-page-root .mp-wl-dot {
width: 8px;
height: 8px;
border-radius: 4px;
}
.mobile-page-root .mp-wl-dot.is-green {
background: #10b981;
}
.mobile-page-root .mp-wl-dot.is-muted {
background: rgba(115, 115, 115, 0.4);
}
.mobile-page-root .mp-wl-dot.is-red {
background: #ef4444;
}
@keyframes mp-wl-spin {
to {
transform: rotate(360deg);
}
}
.mobile-page-root .mp-wl-main {
flex: 1;
min-width: 0;
}
.mobile-page-root .mp-wl-name-row {
display: flex;
align-items: center;
gap: 8px;
}
.mobile-page-root .mp-wl-name {
color: var(--m-text-primary);
font-size: 14px;
font-weight: 600;
}
.mobile-page-root .mp-wl-pr {
display: inline-flex;
align-items: center;
gap: 3px;
padding: 1px 5px;
border-radius: 4px;
background: var(--m-bg-raised);
color: var(--m-text-secondary);
font-size: 10px;
}
.mobile-page-root .mp-wl-pr svg {
width: 10px;
height: 10px;
stroke-width: 1.75;
}
.mobile-page-root .mp-wl-meta-row {
display: flex;
align-items: center;
gap: 4px;
margin-top: 2px;
color: var(--m-text-secondary);
font-size: 11px;
}
.mobile-page-root .mp-wl-meta-row .mp-repo-dot {
width: 6px;
height: 6px;
}
.mobile-page-root .mp-wl-branch {
color: var(--m-text-muted);
font-family: var(--m-mono);
}
.mobile-page-root .mp-wl-preview {
margin-top: 2px;
color: var(--m-text-muted);
font-family: var(--m-mono);
font-size: 11px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.mobile-page-root .mp-wl-tcount {
min-width: 16px;
padding-top: 3px;
color: var(--m-text-muted);
font-size: 12px;
text-align: right;
}
/* ── Session / terminal screen ─────────────────────────────────── */
.mobile-page-root .mp-session-chrome {
background: var(--m-bg-panel);
border-bottom: 1px solid var(--m-border);
}
.mobile-page-root .mp-session-topbar {
display: flex;
align-items: center;
gap: 8px;
padding: 4px 12px 8px;
min-height: 48px;
}
.mobile-page-root .mp-session-back {
display: grid;
width: 32px;
height: 32px;
place-items: center;
color: var(--m-text-secondary);
}
.mobile-page-root .mp-session-back svg {
width: 22px;
height: 22px;
stroke-width: 2.2;
}
.mobile-page-root .mp-session-title-block {
flex: 1;
min-width: 0;
}
.mobile-page-root .mp-session-title {
color: var(--m-text-primary);
font-size: 15px;
font-weight: 600;
letter-spacing: 0;
}
.mobile-page-root .mp-session-meta-row {
display: flex;
align-items: center;
gap: 6px;
margin-top: 2px;
color: var(--m-text-secondary);
font-size: 12px;
}
.mobile-page-root .mp-session-iconbtn {
display: grid;
width: 32px;
height: 32px;
place-items: center;
color: var(--m-text-secondary);
}
.mobile-page-root .mp-session-iconbtn svg {
width: 18px;
height: 18px;
stroke-width: 2.1;
}
.mobile-page-root .mp-session-tabbar {
display: flex;
align-items: stretch;
border-top: 1px solid var(--m-border);
height: 36px;
}
.mobile-page-root .mp-session-tab {
max-width: 128px;
display: flex;
align-items: center;
justify-content: center;
gap: 4px;
padding: 0 12px;
border-bottom: 2px solid transparent;
color: var(--m-text-secondary);
font-size: 13px;
}
.mobile-page-root .mp-session-tab.is-active {
border-bottom-color: var(--m-accent-blue);
color: var(--m-text-primary);
}
.mobile-page-root .mp-session-tab svg {
width: 13px;
height: 13px;
stroke-width: 2.1;
}
.mobile-page-root .mp-session-tab-add {
width: 40px;
display: grid;
place-items: center;
color: var(--m-text-secondary);
}
.mobile-page-root .mp-session-tab-add svg {
width: 16px;
height: 16px;
stroke-width: 2.2;
}
/* Tokyonight terminal */
.mobile-page-root .mp-terminal {
flex: 1;
background: #1a1b26;
color: #c0caf5;
font-family: var(--m-mono);
font-size: 11px;
line-height: 1.55;
padding: 12px 14px;
overflow: hidden;
white-space: pre-wrap;
word-break: break-word;
overflow-wrap: anywhere;
}
.mobile-page-root .mp-term-line {
display: block;
}
.mobile-page-root .mp-term-prompt {
color: #7aa2f7;
}
.mobile-page-root .mp-term-cmd {
color: #c0caf5;
}
.mobile-page-root .mp-term-comment {
color: #565f89;
}
.mobile-page-root .mp-term-warn {
color: #e0af68;
}
.mobile-page-root .mp-term-ok {
color: #9ece6a;
}
.mobile-page-root .mp-term-tool {
color: #bb9af7;
}
.mobile-page-root .mp-term-mid {
color: #a9b1d6;
}
.mobile-page-root .mp-term-dim {
color: #565f89;
}
.mobile-page-root .mp-term-cursor {
display: inline-block;
width: 7px;
height: 13px;
background: #c0caf5;
vertical-align: text-bottom;
animation: mp-term-blink 1s steps(2, start) infinite;
}
@keyframes mp-term-blink {
to {
background: transparent;
}
}
/* Accessory + input bar */
.mobile-page-root .mp-accessory-bar {
background: var(--m-bg-panel);
border-top: 1px solid var(--m-border);
overflow: hidden;
}
.mobile-page-root .mp-accessory-content {
display: flex;
align-items: center;
gap: 4px;
padding: 4px 7px;
overflow: hidden;
}
.mobile-page-root .mp-accessory-key {
display: inline-flex;
align-items: center;
justify-content: center;
flex: 0 0 auto;
min-width: 24px;
padding: 4px 6px;
border-radius: 6px;
background: var(--m-bg-raised);
color: var(--m-text-secondary);
font-size: 11px;
font-family: var(--m-mono);
}
.mobile-page-root .mp-accessory-key.is-icon {
padding: 4px 8px;
}
.mobile-page-root .mp-accessory-key.is-icon svg {
width: 14px;
height: 14px;
stroke-width: 1.75;
}
.mobile-page-root .mp-accessory-key.is-add {
background: transparent;
color: var(--m-text-secondary);
}
.mobile-page-root .mp-input-bar {
display: flex;
align-items: center;
padding: 6px 12px;
border-top: 1px solid var(--m-border);
background: var(--m-bg-panel);
gap: 8px;
}
.mobile-page-root .mp-text-input {
flex: 1;
padding: 8px 12px;
border-radius: 6px;
background: var(--m-bg-raised);
color: var(--m-text-muted);
font-family: var(--m-mono);
font-size: 14px;
}
.mobile-page-root .mp-round-button {
display: grid;
width: 34px;
height: 34px;
place-items: center;
border-radius: 17px;
background: var(--m-bg-raised);
color: var(--m-text-secondary);
flex: 0 0 auto;
}
.mobile-page-root .mp-round-button svg {
width: 17px;
height: 17px;
stroke-width: 2.4;
}
/* Reduced motion: pin to home, no slide transitions */
@media (prefers-reduced-motion: reduce) {
.mobile-page-root .mp-screen-slide,
.mobile-page-root .mp-flow-viewport,
.mobile-page-root .mp-flow-screen {
transition: none;
}
}
/* Narrow viewport: stack the hero so the phone falls below the copy */
@media (max-width: 920px) {
.mobile-page-root {
--mp-flow-card-padding: 20px;
}
.mobile-page-root .mp-hero {
grid-template-columns: 1fr;
grid-template-rows: auto minmax(0, 1fr);
align-items: start;
gap: 24px;
padding: 52px 28px 28px;
}
.mobile-page-root .mp-hero-copy {
min-height: 0;
}
.mobile-page-root .mp-h1 {
font-size: 44px;
}
.mobile-page-root .mp-stage {
height: min(420px, 42vh);
}
.mobile-page-root .mp-phone-frame {
width: min(290px, 100%);
}
}
@media (max-width: 1180px) and (min-width: 921px) {
.mobile-page-root .mp-hero {
grid-template-columns: minmax(330px, 520px) minmax(280px, 360px);
gap: 40px;
padding: 52px 40px 40px;
}
.mobile-page-root .mp-h1 {
font-size: 52px;
}
}
@media (max-height: 840px) and (min-width: 921px) {
.mobile-page-root .mp-hero {
padding: 48px;
}
.mobile-page-root .mp-hero-copy {
min-height: var(--mp-flow-shell-height);
}
.mobile-page-root .mp-h1 {
font-size: 50px;
}
.mobile-page-root .mp-lead {
margin-bottom: 16px;
font-size: 17px;
}
}
/* Why: the app sidebar narrows this page without changing viewport media
queries; keep this after viewport rules so real page width wins. */
@container (max-width: 1080px) {
.mobile-page-root .mp-hero {
--mp-flow-card-padding: 20px;
grid-template-columns: 1fr;
grid-template-rows: auto minmax(0, 1fr);
align-items: start;
gap: 24px;
padding: 52px 28px 28px;
}
.mobile-page-root .mp-hero-copy {
min-height: 0;
}
.mobile-page-root .mp-h1 {
font-size: 44px;
}
.mobile-page-root .mp-stage {
height: min(420px, 42vh);
}
.mobile-page-root .mp-phone-frame {
width: min(290px, 100%);
}
}