/* * What the UI does differently inside the iOS and Android app, keyed on the * attributes native/nativeApp.ts puts on there (data-native-app, and * data-touch-input while a finger drives it). A browser never has them, so * none of this reaches it. Loaded after index.css (main.tsx). */ /* Inside the iOS and Android app (native/nativeApp.ts sets the attribute): a long press on a label, card or image does nothing, as in a native app, instead of starting a text selection, a magnifier or a "save image" callout. What the user types into stays selectable, or editing, pasting and moving the caret would break; text worth copying opts in with .trek-selectable. A browser keeps its default. */ html[data-native-app] body { -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; } html[data-native-app] :is(input, textarea, select, [contenteditable]:not([contenteditable='false']), .trek-selectable), html[data-native-app] :is([contenteditable]:not([contenteditable='false']), .trek-selectable) * { -webkit-user-select: text; user-select: text; -webkit-touch-callout: default; } html[data-native-app] img { -webkit-user-drag: none; } /* A picture still loading waits unseen and fades in once it is there (native/imageFade.ts). An animation rather than a transition, so an image's own transitions (a hover zoom, a crossfade) stay as they are. */ html[data-native-app] img[data-fading] { opacity: 0; } @keyframes trek-image-in { from { opacity: 0; } to { opacity: 1; } } @media (prefers-reduced-motion: no-preference) { html[data-native-app]:not([data-reduce-motion]) img[data-faded] { animation: trek-image-in 0.24s ease-out; } } /* The press a native button shows the moment a finger lands on it. Most of the UI says nothing until the finger lifts, which reads as lag. Only what has no press of its own (no active: class), only the innermost pressed control, not the card around a pressed button, and after a 60 ms wait, so a finger that lands on a row to scroll the list does not flash it. Draggable rows show their own pick-up; data-no-press opts a control out. */ html[data-native-app] :is(button, a[href], [role='button'], [role='tab'], [role='menuitem'], [role='option'], summary):not(:disabled):not( [aria-disabled='true'] ):not([class*='active:']):not([draggable='true']):not([data-no-press]):not([data-pressing]):not( :has(:is(button, a[href], [role='button']):active) ):active { opacity: 0.55; transition: opacity 0s linear 60ms; } /* A card held for its menu lifts a little under the finger (mobile/components/useLongPress.ts), as a native context menu does. */ html[data-native-app] [data-long-press] { transition: transform 0.3s cubic-bezier(0.32, 0.72, 0, 1); } html[data-native-app] [data-long-press][data-pressing] { transform: scale(0.97); } /* A tap focuses a button on Android, and a focus: ring (rather than focus-visible:) then stays round it, which no native control shows. Focus from a hardware keyboard is focus-visible and keeps its ring. */ html[data-touch-input] :is(button, a, [role='button'], [role='tab'], [role='menuitem'], [role='option'], [tabindex]):focus:not( :focus-visible ) { outline: none; --tw-ring-offset-shadow: 0 0 #0000; --tw-ring-shadow: 0 0 #0000; }