mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-06 03:14:00 +00:00
fix(i18n): fix Russian layouts and the gaps the screenshot review found
A review of the Russian UI screenshots found ~90 places where longer words
broke the layout or text was still English. Fixed so they hold for any
language, then shortened where a control is short by design.
- Layout: label columns that size to their text (weather and wind settings,
Recent Imagery slots and opacity, style sliders, display panel), layer
list names and icons, buttons that wrap instead of overflowing (CCTV,
scenes, Bhote Koshi), voice header that always shows the cost, styled
EN | ES | RU chips, voice error tray above the dock.
- t() context: t('CLEAR', { context: 'action' }) is «СБРОСИТЬ» while the sky
stays «ЯСНО»; also used for radio categories, voice states and directions.
- Units and dates follow the locale through src/ui/unitLabels.js
(formatQuantity: localized number, translated unit, non-breaking space):
wind, pressure, cyclones, directions, CCTV, SDR gain, scene timing, flight
tooltip, Recent Imagery dates and resolution.
- Newly translated: directions turn-by-turn steps (built from the maneuver;
English matches the server word for word), HUD mode and summary, voice
card states, radio categories on the globe, CCTV status, layer source
lines, scene dialogs (Cancel, file pickers), Bhote Koshi statuses, titles,
comparison dates and caveat, Recent Imagery notices. Stored data and text
for AI tools stay English.
- es and ru: 1,885 messages each.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
3129e531e6
commit
2b6ccad732
71 files changed
+2435
-370
No files matched your search
@@ -12,7 +12,9 @@
|
||||
background: var(--glass-bg);
|
||||
border: 1px solid var(--glass-border);
|
||||
border-radius: 6px;
|
||||
box-shadow: 0 18px 52px rgba(0, 0, 0, 0.48), inset 0 0 28px rgba(14, 78, 92, 0.12);
|
||||
box-shadow:
|
||||
0 18px 52px rgba(0, 0, 0, 0.48),
|
||||
inset 0 0 28px rgba(14, 78, 92, 0.12);
|
||||
backdrop-filter: blur(24px) saturate(1.4);
|
||||
font-family: var(--font-mono);
|
||||
letter-spacing: 0;
|
||||
@@ -153,33 +155,69 @@
|
||||
}
|
||||
|
||||
@keyframes bhote-embedded-anchor-enter {
|
||||
from { opacity: 0; transform: scale(0.2); }
|
||||
to { opacity: 1; transform: scale(1); }
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: scale(0.2);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes bhote-embedded-leader-enter {
|
||||
from { opacity: 0; stroke-dashoffset: 1; }
|
||||
to { opacity: 1; stroke-dashoffset: 0; }
|
||||
from {
|
||||
opacity: 0;
|
||||
stroke-dashoffset: 1;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
stroke-dashoffset: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes bhote-embedded-body-enter {
|
||||
from { opacity: 0; transform: translateY(8px) scale(0.98); }
|
||||
to { opacity: 1; transform: translateY(0) scale(1); }
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(8px) scale(0.98);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0) scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes bhote-embedded-body-exit {
|
||||
from { opacity: 1; transform: translateY(0) scale(1); }
|
||||
to { opacity: 0; transform: translateY(6px) scale(0.985); }
|
||||
from {
|
||||
opacity: 1;
|
||||
transform: translateY(0) scale(1);
|
||||
}
|
||||
to {
|
||||
opacity: 0;
|
||||
transform: translateY(6px) scale(0.985);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes bhote-embedded-leader-exit {
|
||||
from { opacity: 1; stroke-dashoffset: 0; }
|
||||
to { opacity: 0; stroke-dashoffset: 1; }
|
||||
from {
|
||||
opacity: 1;
|
||||
stroke-dashoffset: 0;
|
||||
}
|
||||
to {
|
||||
opacity: 0;
|
||||
stroke-dashoffset: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes bhote-embedded-anchor-exit {
|
||||
from { opacity: 1; transform: scale(1); }
|
||||
to { opacity: 0; transform: scale(0.2); }
|
||||
from {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
}
|
||||
to {
|
||||
opacity: 0;
|
||||
transform: scale(0.2);
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
@@ -243,16 +281,20 @@
|
||||
border-top: 3px solid #6be8ff;
|
||||
}
|
||||
|
||||
/* Up to two lines, so a translated title is not cut to a stub. */
|
||||
.bhote-embedded-callout footer strong {
|
||||
display: -webkit-box;
|
||||
overflow: hidden;
|
||||
font-size: 11px;
|
||||
line-height: 1.25;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
overflow-wrap: anywhere;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
}
|
||||
|
||||
/* The status takes the full width under the title and link. */
|
||||
.bhote-embedded-callout footer small {
|
||||
grid-column: 1;
|
||||
grid-column: 1 / -1;
|
||||
color: rgba(151, 211, 224, 0.7);
|
||||
font-size: 8px;
|
||||
line-height: 1.35;
|
||||
@@ -260,8 +302,9 @@
|
||||
|
||||
.bhote-embedded-callout footer a {
|
||||
grid-column: 2;
|
||||
grid-row: 1 / span 2;
|
||||
grid-row: 1;
|
||||
align-self: center;
|
||||
white-space: nowrap;
|
||||
color: #6be8ff;
|
||||
font-size: 8px;
|
||||
text-decoration: none;
|
||||
@@ -372,6 +415,11 @@
|
||||
color: rgba(174, 208, 216, 0.62);
|
||||
}
|
||||
|
||||
/* Keep "16 OCT 2021" together so the year never wraps alone. */
|
||||
.bhote-event-date {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.bhote-event-story-nav {
|
||||
display: grid;
|
||||
grid-template-columns: 34px minmax(0, 1fr) 34px;
|
||||
@@ -388,7 +436,11 @@
|
||||
border-radius: 4px;
|
||||
color: var(--accent);
|
||||
background: rgba(7, 25, 35, 0.9);
|
||||
font: 22px/1 'JetBrains Mono', 'SFMono-Regular', Consolas, monospace;
|
||||
font:
|
||||
22px/1 'JetBrains Mono',
|
||||
'SFMono-Regular',
|
||||
Consolas,
|
||||
monospace;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
@@ -419,13 +471,15 @@
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* Phase / time / sources run long in translation: allow a second line. */
|
||||
.bhote-event-story-current small {
|
||||
display: -webkit-box;
|
||||
grid-column: 1 / -1;
|
||||
margin-top: 4px;
|
||||
overflow: hidden;
|
||||
color: rgba(116, 216, 235, 0.7);
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
}
|
||||
|
||||
.bhote-event-actions {
|
||||
@@ -448,14 +502,15 @@
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* One line in English; a longer translation wraps to a second line. */
|
||||
.bhote-event-actions button {
|
||||
min-width: 0;
|
||||
min-height: 30px;
|
||||
padding: 0 5px;
|
||||
padding: 3px 5px;
|
||||
overflow: hidden;
|
||||
font-size: 8px;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
line-height: 1.2;
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
|
||||
.bhote-event-actions button:disabled,
|
||||
@@ -469,7 +524,7 @@
|
||||
border-color: rgba(88, 196, 218, 0.36);
|
||||
}
|
||||
|
||||
.bhote-event-actions button[data-action="cinematic"][aria-pressed="true"] {
|
||||
.bhote-event-actions button[data-action='cinematic'][aria-pressed='true'] {
|
||||
color: #071017;
|
||||
border-color: var(--accent);
|
||||
background: var(--accent);
|
||||
@@ -593,7 +648,6 @@
|
||||
max-height: 48vh;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
* {
|
||||
@@ -602,7 +656,8 @@
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
html, body {
|
||||
html,
|
||||
body {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
|
||||
+14
-2
@@ -78,6 +78,14 @@ html[lang='es'] .cctv-controls {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
/* A translated label longer than its button wraps inside the button instead
|
||||
of running past the panel edge. English labels fit on one line, so the
|
||||
English layout is unchanged. */
|
||||
.cctv-controls .scene-btn {
|
||||
white-space: normal;
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
|
||||
.cctv-calibration-block {
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
border-radius: 9px;
|
||||
@@ -163,8 +171,12 @@ html[lang='es'] .cctv-controls {
|
||||
border-radius: 7px;
|
||||
color: var(--text-primary);
|
||||
padding: 6px 8px;
|
||||
font-family: var(--font-sans);
|
||||
font-size: 12px;
|
||||
font-family: var(--font-mono);
|
||||
font-size: 10px;
|
||||
letter-spacing: 0.04em;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
|
||||
@@ -1499,6 +1499,12 @@ body.cockpit-mode #view-switcher button {
|
||||
.cockpit-signal-header > div {
|
||||
display: grid;
|
||||
gap: 2px;
|
||||
min-width: 0;
|
||||
}
|
||||
.cockpit-signal-kicker {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.cockpit-signal-header strong {
|
||||
color: #fff;
|
||||
@@ -1526,6 +1532,11 @@ body.cockpit-mode #view-switcher button {
|
||||
align-items: center;
|
||||
gap: 3px;
|
||||
}
|
||||
/* A longer translated state label widens the cycle button; the other
|
||||
controls keep their size instead of being squeezed. */
|
||||
.cockpit-brief-actions > * {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.cockpit-brief-actions button {
|
||||
display: grid;
|
||||
width: 23px;
|
||||
@@ -1548,10 +1559,13 @@ body.cockpit-mode #view-switcher button {
|
||||
font-size: 14px;
|
||||
}
|
||||
#cockpit-brief-auto {
|
||||
width: 50px;
|
||||
width: auto;
|
||||
min-width: 50px;
|
||||
padding: 0 4px;
|
||||
color: rgba(244, 251, 255, 0.42);
|
||||
font: 700 6px/1 var(--font-mono);
|
||||
letter-spacing: 0.05em;
|
||||
white-space: nowrap;
|
||||
}
|
||||
#cockpit-brief-auto[aria-pressed='true'] {
|
||||
border-color: var(--cockpit-accent);
|
||||
@@ -1857,14 +1871,20 @@ body.cockpit-mode #view-switcher button {
|
||||
letter-spacing: 0.1em;
|
||||
}
|
||||
.cockpit-signal-footer > span {
|
||||
flex: 1 1 auto;
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.cockpit-brief-tabs {
|
||||
display: flex;
|
||||
flex: 0 0 auto;
|
||||
gap: 3px;
|
||||
}
|
||||
.cockpit-brief-tabs button {
|
||||
white-space: nowrap;
|
||||
}
|
||||
.cockpit-brief-tabs button {
|
||||
padding: 2px 4px;
|
||||
border: 0;
|
||||
|
||||
@@ -696,3 +696,54 @@
|
||||
rgba(232, 234, 237, 0.24)
|
||||
);
|
||||
}
|
||||
|
||||
/* Language switch under the Visual Presets title: small mono chips, the
|
||||
active language in accent like the other dock toggles. */
|
||||
#command-dock #control-panel .dock-locale-switch {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 0.2rem;
|
||||
margin-top: 0.22rem;
|
||||
}
|
||||
|
||||
#command-dock .dock-locale-btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-sizing: border-box;
|
||||
min-width: 1.35rem;
|
||||
height: 0.95rem;
|
||||
margin: 0;
|
||||
padding: 0 0.22rem;
|
||||
color: var(--text-secondary);
|
||||
background: rgba(255, 255, 255, 0.03);
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
border-radius: 0.18rem;
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.46rem;
|
||||
font-weight: 500;
|
||||
letter-spacing: 0.06rem;
|
||||
line-height: 1;
|
||||
cursor: pointer;
|
||||
transition:
|
||||
color var(--transition-fast),
|
||||
border-color var(--transition-fast),
|
||||
background var(--transition-fast);
|
||||
}
|
||||
|
||||
#command-dock .dock-locale-btn:hover {
|
||||
color: var(--text-primary);
|
||||
border-color: var(--glass-border-hover);
|
||||
background: rgba(255, 255, 255, 0.06);
|
||||
}
|
||||
|
||||
#command-dock .dock-locale-btn:focus-visible {
|
||||
outline: 1px solid var(--text-primary);
|
||||
outline-offset: 1px;
|
||||
}
|
||||
|
||||
#command-dock .dock-locale-btn.active {
|
||||
color: var(--accent);
|
||||
border-color: rgba(0, 212, 255, 0.55);
|
||||
background: var(--accent-dim);
|
||||
}
|
||||
@@ -392,6 +392,12 @@
|
||||
transform 220ms cubic-bezier(0.2, 0.8, 0.2, 1);
|
||||
}
|
||||
|
||||
/* The side wings sit at z-index 100 (controls.css, location.css), so their
|
||||
open trays would cover the alert; lift the voice column while it shows. */
|
||||
#command-dock > #gev-voice-control[data-status='error']:not(.error-dismissed) {
|
||||
z-index: 101;
|
||||
}
|
||||
|
||||
#command-dock
|
||||
#gev-voice-control[data-status='error']:not(.error-dismissed)
|
||||
.gev-voice-error-tray {
|
||||
|
||||
@@ -228,6 +228,8 @@
|
||||
}
|
||||
|
||||
.panel-collapse-btn {
|
||||
/* A long translated title must not squeeze the toggle into a sliver. */
|
||||
flex-shrink: 0;
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
border-radius: 6px;
|
||||
@@ -770,6 +772,15 @@
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* One label column across the Display rows: --pp-label-chars is the longest
|
||||
label of the active language (set by applicationShell), and the labels are
|
||||
monospace, so every slider track starts at the same x whatever the
|
||||
language. 0.125em is the 1px letter-spacing at 8px. */
|
||||
.pp-slider-row > .pp-slider-mini-label {
|
||||
flex: 0 0 auto;
|
||||
min-width: calc(var(--pp-label-chars, 0) * (1ch + 0.125em));
|
||||
}
|
||||
|
||||
.detection-slider-row {
|
||||
min-width: 170px;
|
||||
padding: 5px 8px 6px;
|
||||
@@ -987,8 +998,11 @@
|
||||
.pp-text-input:focus {
|
||||
border-color: var(--accent);
|
||||
}
|
||||
/* Sized to its longest colour name so a translated one is never clipped;
|
||||
74px keeps the English width. */
|
||||
.draw-color-select {
|
||||
flex: 0 0 74px;
|
||||
flex: 0 0 auto;
|
||||
min-width: 74px;
|
||||
}
|
||||
.draw-clear-btn {
|
||||
flex: 0 0 auto;
|
||||
@@ -1234,15 +1248,20 @@ body.ui-clean-view #scene-runtime.active {
|
||||
);
|
||||
}
|
||||
|
||||
.param-slider-row {
|
||||
display: flex;
|
||||
/* One label column for every parameter, as wide as the longest label in the
|
||||
active language, so all slider tracks start and end at the same x. */
|
||||
#param-sliders {
|
||||
display: grid;
|
||||
grid-template-columns: max-content minmax(0, 1fr) max-content;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.param-slider-row:last-child {
|
||||
margin-bottom: 0;
|
||||
.param-slider-row {
|
||||
display: grid;
|
||||
grid-column: 1 / -1;
|
||||
grid-template-columns: subgrid;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.param-label {
|
||||
|
||||
@@ -1371,10 +1371,12 @@
|
||||
padding: 2px 4px;
|
||||
}
|
||||
|
||||
/* ALPR keeps its nearby count in the legend while a wider status chip is shown. */
|
||||
/* ALPR keeps its nearby count in the legend while a wider status chip
|
||||
(including ENABLING / DISABLING) is shown. */
|
||||
.data-toggle-row[data-layer-id='alpr-cameras']
|
||||
.data-toggle-right:has(
|
||||
.data-toggle-btn:is(
|
||||
.transitioning,
|
||||
.feed-loading,
|
||||
.feed-degraded,
|
||||
.feed-stale,
|
||||
|
||||
+27
-4
@@ -250,8 +250,12 @@
|
||||
gap: 5px;
|
||||
}
|
||||
.radio-transport button {
|
||||
min-width: 0;
|
||||
min-height: 30px;
|
||||
padding: 6px 3px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
border: 1px solid rgba(65, 220, 231, 0.28);
|
||||
border-radius: 5px;
|
||||
color: #8feaf2;
|
||||
@@ -610,10 +614,14 @@
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
/* The name takes the room the status column leaves; a long word wraps inside
|
||||
it instead of pushing the toggle out of line. */
|
||||
.data-toggle-left {
|
||||
display: flex;
|
||||
flex: 1 1 auto;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.data-icon {
|
||||
@@ -621,16 +629,27 @@
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
/* A fixed icon box, so every name (and the meta line under it, 26px in)
|
||||
starts at the same x whatever the glyph's width. */
|
||||
.data-toggle-left .data-icon {
|
||||
flex: none;
|
||||
width: 18px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.data-name {
|
||||
min-width: 0;
|
||||
font-family: var(--font-sans);
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
color: var(--text-primary);
|
||||
letter-spacing: 0.3px;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.data-toggle-right {
|
||||
display: flex;
|
||||
flex: 0 1 auto;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
@@ -640,8 +659,8 @@
|
||||
font-size: 11px;
|
||||
letter-spacing: 0.5px;
|
||||
color: var(--text-secondary);
|
||||
min-width: 30px;
|
||||
text-align: right;
|
||||
text-wrap: balance;
|
||||
}
|
||||
|
||||
.data-toggle-btn {
|
||||
@@ -662,8 +681,10 @@
|
||||
min-width var(--transition-fast),
|
||||
letter-spacing var(--transition-fast);
|
||||
outline: none;
|
||||
flex: none;
|
||||
min-width: 38px;
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* An inset ring stays visible inside the scrolling layer list. */
|
||||
@@ -883,14 +904,16 @@
|
||||
.data-row-list-lead {
|
||||
min-width: 34px;
|
||||
flex: none;
|
||||
white-space: nowrap;
|
||||
opacity: 0.85;
|
||||
}
|
||||
|
||||
/* The whole instruction wraps under itself rather than losing its tail:
|
||||
"Turn right onto …" says nothing, and Russian or Spanish run longer. */
|
||||
.data-row-list-text {
|
||||
flex: 1 1 auto;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
min-width: 0;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
/* A list line that states a limit rather than offering an action. */
|
||||
|
||||
@@ -293,17 +293,34 @@
|
||||
height: 18px;
|
||||
font-weight: 700;
|
||||
}
|
||||
/* Outside A / B there is one chip (SHOW): it takes the whole row, so a long
|
||||
translation is not cut to a stub. */
|
||||
.recent-imagery-readout:not([data-mode='ab'])
|
||||
.ri-card-chips
|
||||
.ri-chip[data-slot='a'] {
|
||||
grid-column: 1 / -1;
|
||||
}
|
||||
.recent-imagery-readout:not([data-mode='ab'])
|
||||
.ri-card-chips
|
||||
.ri-chip[data-slot='b'] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* 4. The selection bar: mode, then two rows that are always there. */
|
||||
/* 4. The selection bar: mode, then two rows that are always there. The slot
|
||||
rows share the bar's columns (subgrid), so the tag column fits the longest
|
||||
tag in either row and both rows stay aligned. */
|
||||
.recent-imagery-readout .ri-selection {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(44px, max-content) minmax(0, 1fr) 22px;
|
||||
grid-template-rows: 20px 20px 20px;
|
||||
column-gap: 6px;
|
||||
row-gap: 4px;
|
||||
padding: 5px;
|
||||
border: 1px solid var(--weather-card-border);
|
||||
border-radius: 6px;
|
||||
}
|
||||
.recent-imagery-readout .ri-mode {
|
||||
grid-column: 1 / -1;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
gap: 4px;
|
||||
@@ -312,14 +329,16 @@
|
||||
height: 20px;
|
||||
}
|
||||
.recent-imagery-readout .ri-slot {
|
||||
grid-column: 1 / -1;
|
||||
display: grid;
|
||||
grid-template-columns: 44px minmax(0, 1fr) 22px;
|
||||
grid-template-columns: subgrid;
|
||||
align-items: center;
|
||||
column-gap: 6px;
|
||||
height: 20px;
|
||||
}
|
||||
.recent-imagery-readout .ri-slot-tag {
|
||||
height: 16px;
|
||||
padding: 0 3px;
|
||||
line-height: 16px;
|
||||
border: 1px solid rgba(255, 255, 255, 0.12);
|
||||
border-radius: 3px;
|
||||
@@ -355,19 +374,25 @@
|
||||
}
|
||||
|
||||
/* 5. Opacity (both images), SWAP and export, one row. SWAP keeps its slot
|
||||
while no swipe is live. */
|
||||
while no swipe is live. A label longer than its 76px column widens it to
|
||||
the label's longest word, and the value wraps under the label. */
|
||||
.recent-imagery-readout .ri-controls {
|
||||
display: grid;
|
||||
grid-template-columns: 76px minmax(0, 1fr) 40px 128px;
|
||||
grid-template-columns:
|
||||
minmax(76px, min-content) minmax(0, 1fr) minmax(40px, max-content)
|
||||
128px;
|
||||
align-items: center;
|
||||
column-gap: 6px;
|
||||
height: 22px;
|
||||
}
|
||||
.recent-imagery-readout .ri-opacity-label {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
gap: 4px;
|
||||
align-content: center;
|
||||
column-gap: 4px;
|
||||
font-size: 8px;
|
||||
line-height: 10px;
|
||||
letter-spacing: 1px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
@@ -385,7 +410,7 @@
|
||||
opacity: 0.35;
|
||||
}
|
||||
.recent-imagery-readout .ri-swap {
|
||||
width: 40px;
|
||||
min-width: 40px;
|
||||
padding: 0 2px;
|
||||
}
|
||||
.recent-imagery-readout .ri-exports .rail-card-actions {
|
||||
|
||||
@@ -158,11 +158,23 @@
|
||||
border-radius: 7px;
|
||||
color: var(--text-primary);
|
||||
padding: 6px 8px;
|
||||
font-family: var(--font-sans);
|
||||
font-size: 12px;
|
||||
font-family: var(--font-mono);
|
||||
font-size: 10px;
|
||||
letter-spacing: 0.04em;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
/* A translated action longer than its button wraps inside the button instead
|
||||
of running past it. English labels fit on one line, so the English layout
|
||||
is unchanged. */
|
||||
#scene-panel .scene-controls .scene-btn {
|
||||
white-space: normal;
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
|
||||
.scene-btn {
|
||||
background: rgba(255, 255, 255, 0.05);
|
||||
border: 1px solid rgba(255, 255, 255, 0.14);
|
||||
|
||||
@@ -82,3 +82,61 @@
|
||||
.gev-voice-cost-value[hidden] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* The dock heading row is only as wide as the voice column, so the cost
|
||||
cluster keeps its size and the state label gives way: a long translated
|
||||
state (ПОДКЛЮЧЕНИЕ, CONECTANDO) ends in an ellipsis instead of pushing the
|
||||
cost past the card edge. The kicker already collapses to zero width here;
|
||||
taking it out of the row returns its gap to the state label. The row also
|
||||
reaches left over the gutter beside the mic ring: at heading height the
|
||||
ring has already curved away. */
|
||||
#command-dock .gev-voice-heading {
|
||||
gap: 0.2rem;
|
||||
margin-left: -0.6rem;
|
||||
}
|
||||
|
||||
#command-dock .gev-voice-heading > .gev-voice-kicker {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#command-dock .gev-voice-heading > #gev-voice-status {
|
||||
flex: 0 1 auto;
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
letter-spacing: 0;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
#command-dock .gev-voice-cost {
|
||||
gap: 0.16rem;
|
||||
padding-left: 0.1rem;
|
||||
}
|
||||
|
||||
#command-dock .gev-voice-tier-btn {
|
||||
min-width: 0;
|
||||
padding: 0 0.2rem;
|
||||
}
|
||||
|
||||
#command-dock .gev-voice-cost-value {
|
||||
letter-spacing: 0;
|
||||
}
|
||||
|
||||
/* Live hints ("Ask or command", "Requesting microphone") run longer in other
|
||||
languages; give them a second line from the spare space under the readout
|
||||
rather than cutting them mid-word. */
|
||||
#command-dock
|
||||
#gev-voice-control:is(
|
||||
[data-status='connecting'],
|
||||
[data-status='listening'],
|
||||
[data-status='executing']
|
||||
)
|
||||
#gev-voice-detail {
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
line-clamp: 2;
|
||||
line-height: 1.15;
|
||||
white-space: normal;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
@@ -258,6 +258,7 @@ body.recording-mode .gev-wind-inspection-marker {
|
||||
top: 8px;
|
||||
left: 0;
|
||||
transform: translateX(-50%);
|
||||
white-space: nowrap;
|
||||
font: 9px/1.45 var(--font-mono);
|
||||
color: var(--text-dim);
|
||||
}
|
||||
@@ -311,9 +312,18 @@ body.recording-mode .gev-wind-inspection-marker {
|
||||
.rail-card-compact.status {
|
||||
color: var(--accent);
|
||||
}
|
||||
/* One label column per card, as wide as its longest label: chips line up
|
||||
across rows, and a long translated label never runs under its chips. */
|
||||
.rail-card-settings {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(56px, max-content) minmax(0, 1fr);
|
||||
column-gap: 6px;
|
||||
}
|
||||
.rail-card-setting {
|
||||
display: grid;
|
||||
grid-template-columns: 56px minmax(0, 1fr);
|
||||
grid-column: 1 / -1;
|
||||
grid-template-columns: minmax(56px, max-content) minmax(0, 1fr);
|
||||
grid-template-columns: subgrid;
|
||||
align-items: baseline;
|
||||
gap: 6px;
|
||||
margin-top: 6px;
|
||||
|
||||
Reference in new issue
Block a user