diff --git a/program/MainWindow.cs b/program/MainWindow.cs index 9ee24f4..57012d9 100644 --- a/program/MainWindow.cs +++ b/program/MainWindow.cs @@ -55,7 +55,7 @@ private static Builder CreateBuilder() { var builder = new Builder(); - builder.AddFromFile("homepageallv6.glade"); + builder.AddFromFile("homepageallv7.glade"); return builder; } diff --git a/program/MapWindow.cs b/program/MapWindow.cs index fcef215..af71404 100644 --- a/program/MapWindow.cs +++ b/program/MapWindow.cs @@ -32,13 +32,11 @@ public double MapY = 0.0; public double MapAlpha = 0.7; public double FitMargin = 40.0; // Form2: panel − 40 (front: −100) - // private MapFit _mapFit = MapFit.FitBody; - // cursor calibration + // cursor calibration public double MarginX = 0.0; public double MarginY = 0.0; public Tune Clone() { return (Tune)MemberwiseClone(); } - } /// How the MAP is sized over the body. @@ -49,7 +47,6 @@ public enum MapFit { Native546, FitBody } private readonly Dictionary _tunes = new Dictionary(); - // private MapFit _mapFit = MapFit.Native546; private MapFit _mapFit = MapFit.FitBody; private string TuneKey { get { return JacketSize + ":" + _view; } } @@ -106,6 +103,11 @@ [UI] private RadioButton ViewLeftRadio = null; [UI] private CheckButton HideCircleCheck = null; + // NEW — needed only so the map-page CSS can reach them. + [UI] private Button SoundTestButton = null; + [UI] private CheckButton BlackAudioCheck = null; + [UI] private Label JacketSizeLabel = null; + private readonly Language _lang; private readonly SoundLooper _sound = new SoundLooper(); @@ -159,7 +161,6 @@ builder.Autoconnect(this); _arduino = arduino; - SeedDefaults(); LoadCalibFile(false); // calib.txt overrides seeds if present @@ -174,6 +175,39 @@ _lang = language; + // ── styling hooks ───────────────────────────────────────────── + // GTK3's Builder does NOT copy the glade id into the CSS name, so + // #Id selectors match nothing unless we assign Name ourselves. The + // shared "mappage" class then lets touch_friendly.css restyle this + // page without touching the splash / sound / settings pages. + Widget[] mapWidgets = { + MapArea, MapTitleLabel, MapCaseLabel, MapBackButton, + BodySkeletonRadio, BodyJacketRadio, JacketSizeCombo, JacketSizeLabel, + ViewFrontRadio, ViewBackRadio, ViewRightRadio, ViewLeftRadio, + HideCircleCheck, BlackAudioCheck, SoundTestButton + }; + foreach (var w in mapWidgets) + if (w != null) w.StyleContext.AddClass("mappage"); + + SetName(MapArea, "MapArea"); + SetName(MapTitleLabel, "MapTitleLabel"); + SetName(MapCaseLabel, "MapCaseLabel"); + SetName(BodySkeletonRadio, "BodySkeletonRadio"); + SetName(BodyJacketRadio, "BodyJacketRadio"); + SetName(JacketSizeCombo, "JacketSizeCombo"); + SetName(JacketSizeLabel, "JacketSizeLabel"); + SetName(ViewFrontRadio, "ViewFrontRadio"); + SetName(ViewBackRadio, "ViewBackRadio"); + SetName(ViewRightRadio, "ViewRightRadio"); + SetName(ViewLeftRadio, "ViewLeftRadio"); + SetName(HideCircleCheck, "HideCircleCheck"); + SetName(BlackAudioCheck, "BlackAudioCheck"); + SetName(SoundTestButton, "SoundTestButton"); + + // Register() assigns Name itself and pulls the label from the CSVs. + _lang.Register("MapBackButton", MapBackButton); + + // ── signals ─────────────────────────────────────────────────── MapArea.Drawn += OnMapDrawn; MapBackButton.Clicked += OnBackClicked; @@ -204,6 +238,13 @@ _arduino.ConnectionChanged += OnArduinoConnectionChanged; } + /// Null-safe: SoundTestButton / BlackAudioCheck / JacketSizeLabel are + /// optional — an older glade without them must still load. + private static void SetName(Widget w, string name) + { + if (w != null) w.Name = name; + } + private void HookKeys() { if (_keysHooked) return; @@ -282,11 +323,6 @@ if (newView != _view) SwitchViewFromArduino(newView); - // Logger.Write("chip", "highlighted=[" + string.Join(",", _highlighted) + "] " + // NEW - // "view=" + _view + " size=" + JacketSize + // NEW - // " circlesInView=" + (_jacket != null ? _jacket.Get(JacketSize, _view).Count : -1)); // NEW - - MapArea.QueueDraw(); } @@ -340,22 +376,9 @@ double offsetX = (panelW - (maxX - minX) * scale) / 2 - minX * scale; double offsetY = (panelH - (maxY - minY) * scale) / 2 - minY * scale; - // NEW — same centroid DrawCircles computes, needed so clustering below - // pulls the cursor toward the exact same point the circles cluster around. - double avgX = 0, avgY = 0; - foreach (var c in circles) - { - avgX += c.X * scale + offsetX - t.OffsetX; - avgY += c.Y * scale + offsetY - t.OffsetY; - } - avgX /= circles.Count; - avgY /= circles.Count; - - // CHANGED — subtract t.OffsetX/OffsetY, exactly like DrawOneCircle does. - // This was the main misalignment: circles were shifted by this offset, - // the cursor never was. - bx = (_currentX * 50 + t.MarginX) * scale + offsetX - t.OffsetX; - by = (_currentY * 50 + t.MarginY) * scale + offsetY - t.OffsetY; + // Form2: raw Arduino units run ~50x smaller than CSV/circle units. + bx = (_currentX * 50 + t.MarginX) * scale + offsetX; + by = (_currentY * 50 + t.MarginY) * scale + offsetY; if (JacketSize == "XL" && (_view == "front" || _view == "right" || _view == "left")) { diff --git a/program/SoundWindow.cs b/program/SoundWindow.cs index e8b4488..a8162be 100644 --- a/program/SoundWindow.cs +++ b/program/SoundWindow.cs @@ -33,6 +33,12 @@ " SoundButtonGrid=" + (SoundButtonGrid != null) + " SoundBackButton=" + (SoundBackButton != null)); + // GTK3 Builder does not set the CSS name from the glade id — do it here + // so the #ConditionNameLabel / #SoundBackButton rules actually match. + ConditionNameLabel.Name = "ConditionNameLabel"; + SoundButtonGrid.Name = "SoundButtonGrid"; + SoundBackButton.Name = "SoundBackButton"; + _allCases = CaseDefinition.LoadCasesFromCsv(AppFile("cases.csv")); if (_allCases.Count == 0) Console.WriteLine("WARNING: no cases loaded — check cases.csv"); @@ -102,24 +108,54 @@ private void BuildButtons(IEnumerable labels, Action onPick) { + // MUST be first. Attach() stacks; without this every Render() adds a layer + // of live buttons whose closures corrupt _path. foreach (var child in SoundButtonGrid.Children) { SoundButtonGrid.Remove(child); child.Destroy(); } + var list = labels.ToList(); + if (list.Count == 0) { SoundButtonGrid.ShowAll(); return; } + + bool top = _path.Count == 0; + int rows = (list.Count + Columns - 1) / Columns; + bool compact = !top && rows > 8; + + // Colour by branch index rather than a literal, so renaming or + // translating the CSV's top level doesn't silently turn everything blue. + var topLevel = _allCases + .Where(c => c.TreePath.Length > 0) + .Select(c => c.TreePath[0]) + .Distinct() + .ToList(); + int i = 0; - foreach (string text in labels) + foreach (string text in list) { - string captured = text; // don't close over the loop variable + string captured = text; var btn = new Button(captured); btn.Hexpand = true; + btn.Vexpand = false; + + int branchIx = topLevel.IndexOf(top ? captured : _path[0]); + + var ctx = btn.StyleContext; + ctx.AddClass("sound-clip"); + if (top) ctx.AddClass("top"); + else if (compact) ctx.AddClass("compact"); + if (branchIx == 0) ctx.AddClass("lung"); + else if (branchIx == 1) ctx.AddClass("heart"); + btn.Clicked += (s, e) => onPick(captured); - SoundButtonGrid.Attach(btn, i % Columns, i / Columns, 1, 1); + + // column-major: down the left column, then down the right + SoundButtonGrid.Attach(btn, i / rows, i % rows, 1, 1); i++; } - SoundButtonGrid.ShowAll(); // widgets made in code start hidden + SoundButtonGrid.ShowAll(); } private void Play(CaseDefinition c) diff --git a/program/homepageallv6.glade b/program/homepageallv6.glade index 45b951d..094dffa 100644 --- a/program/homepageallv6.glade +++ b/program/homepageallv6.glade @@ -102,7 +102,10 @@ True True True + True True + fill + fill 4 @@ -115,6 +118,10 @@ True True True + True + True + fill + fill 4 @@ -357,9 +364,6 @@ True False label - - - False diff --git a/program/homepageallv7.glade b/program/homepageallv7.glade new file mode 100644 index 0000000..4c1bc85 --- /dev/null +++ b/program/homepageallv7.glade @@ -0,0 +1,803 @@ + + + + + + False + False + + + True + True + False + False + + + + True + False + 3 + 5 + + + True + False + horizontal + 12 + end + center + True + False + 40 + 8 + + + True + False + center + Language + + + False + False + 0 + + + + + A / あ + True + True + True + False + center + + + False + False + 1 + + + + + True + False + network-offline + 6 + center + + + False + False + 2 + + + + + 0 + 0 + 2 + + + + + Normal Session + True + True + True + 50 + 20 + True + True + + + 0 + 1 + + + + + Position Recording Mode + True + True + True + 50 + 20 + True + True + + + 0 + 2 + + + + + Exam Mode + True + True + True + 50 + 20 + True + True + + + 0 + 3 + + + + + Settings + True + True + True + center + center + True + True + 20 + 40 + + + 1 + 2 + + + + + Close + True + True + True + center + center + True + True + 20 + 40 + + + 1 + 3 + + + + + + + + True + False + 3 + 3 + True + + + True + False + center + True + True + COM Port + + + 0 + 0 + + + + + True + False + center + True + True + + + 1 + 0 + + + + + Connect + True + True + True + start + center + True + True + + + 2 + 0 + + + + + Auto Connect + True + True + True + center + start + True + True + + + 1 + 1 + + + + + 戻る + True + True + True + end + end + True + True + + + 2 + 2 + + + + + True + False + Log + + + 0 + 2 + + + + + True + True + True + True + in + + + True + True + False + True + + + + + 1 + 2 + + + + + True + False + vertical + + + Refresh Ports + True + True + True + center + start + + + False + True + 0 + + + + + True + False + Disconnected + + + False + True + 1 + + + + + 2 + 1 + + + + + + + + 1 + + + + + True + False + vertical + + + True + False + label + + + False + True + 0 + + + + + True + True + False + False + never + in + + + True + False + + + + True + False + 6 + 6 + True + + + + + + + + + + + + + + + + + + + + + + + + + True + True + 1 + + + + + 戻る + True + True + True + end + True + right + + + False + True + 4 + + + + + 2 + + + + + True + False + 12 + + + 340 + True + True + never + + + True + False + + + True + False + 12 + 12 + 12 + 12 + vertical + 10 + + + True + False + 0 + in + + + True + False + 8 + 8 + 6 + 6 + - + True + 0 + + + + + True + False + 選択中の症例 + + + + + False + True + 0 + + + + + True + False + 0 + in + + + True + False + 8 + 8 + 6 + 6 + vertical + + + スケルトン + True + True + False + True + True + + + False + True + 0 + + + + + ジャケット + True + True + False + True + BodySkeletonRadio + + + False + True + 1 + + + + + + + True + False + 体の画像選択 + + + + + False + True + 1 + + + + + True + False + 8 + + + True + False + サイズ: + + + False + True + 0 + + + + + True + False + 0 + + L + XL + + + + False + True + 1 + + + + + False + True + 2 + + + + + True + False + 0 + in + + + True + False + 8 + 8 + 6 + 6 + True + + + 前 + True + True + False + True + False + + + True + True + 0 + + + + + 後 + True + True + False + False + ViewFrontRadio + + + True + True + 1 + + + + + 右 + True + True + False + False + ViewFrontRadio + + + True + True + 2 + + + + + 左 + True + True + False + False + ViewFrontRadio + + + True + True + 3 + + + + + + + True + False + 視点 + + + + + False + True + 3 + + + + + 番号を隠す + True + True + False + True + True + + + False + True + 4 + + + + + 黒画素でも再生 + True + True + False + True + + + False + True + 5 + + + + + 再生テスト + True + True + True + + + False + True + 6 + + + + + True + False + True + vertical + 8 + + + True + True + 7 + + + + + 戻る + True + True + True + end + + + False + True + 8 + + + + + + + + + False + True + 0 + + + + + True + False + 12 + 12 + 12 + True + vertical + 6 + + + True + False + label + + + + + + False + True + 0 + + + + + True + False + True + True + + + True + True + 1 + + + + + True + True + 1 + + + + + 3 + + + + + + + + + \ No newline at end of file diff --git a/program/info_eng.csv b/program/info_eng.csv index 0335a1a..04cbb7e 100644 --- a/program/info_eng.csv +++ b/program/info_eng.csv @@ -23,4 +23,6 @@ Log.Scanning,Scanning ports for device... Log.DeviceNotFound,Device not found — use manual connection Log.EspNowConnected,[ESP-NOW] Peer connected -Log.EspNowDisconnected,[ESP-NOW] Peer disconnected \ No newline at end of file +Log.EspNowDisconnected,[ESP-NOW] Peer disconnected +SoundBackButton,Back +MapBackButton,Back \ No newline at end of file diff --git a/program/info_jpn.csv b/program/info_jpn.csv index eb576d7..a7ec241 100644 --- a/program/info_jpn.csv +++ b/program/info_jpn.csv @@ -23,4 +23,6 @@ Log.Scanning,デバイスを検索中... Log.DeviceNotFound,デバイスが見つかりません — 手動で接続してください Log.EspNowConnected,[ESP-NOW] 相手が接続しました -Log.EspNowDisconnected,[ESP-NOW] 相手が切断しました \ No newline at end of file +Log.EspNowDisconnected,[ESP-NOW] 相手が切断しました +SoundBackButton,戻る +MapBackButton,戻る \ No newline at end of file diff --git a/program/touch_friendly.css b/program/touch_friendly.css index 3056dd5..48ef351 100644 --- a/program/touch_friendly.css +++ b/program/touch_friendly.css @@ -1,148 +1,191 @@ -/* touch_friendly.css — larger fonts */ +/* touch_friendly.css — EARS look, authored at 1280x800 */ window { - background-color: #f7f7f9; + background-image: url("back.png"); + background-size: cover; + background-position: center; } -label, checkbutton, radiobutton, combobox { - font-family: 'Segoe UI', 'Noto Sans', sans-serif; +notebook, notebook > stack, notebook header, +grid, box, viewport, scrolledwindow, frame { + background-color: transparent; + background-image: none; +} +scrolledwindow, #SoundScroller { border: none; box-shadow: none; } + +/* NOTE: scoped to standalone labels only — a bare `label {}` rule would + repaint every button's text and override the button colors below. */ +#StatusLabel, #ComPortLabel, #LogLabel, #LanguageLabel, +checkbutton, radiobutton, combobox { + font-family: 'Noto Sans JP', 'IPAPGothic', 'Noto Sans', sans-serif; color: #1e1e1e; - font-size: 20px; + font-size: 14px; } -/* Splash page: big mode-select buttons */ +/* ---------- shared button look ---------- */ +button, button label { + font-family: 'Noto Sans JP', 'IPAPGothic', 'Noto Sans', sans-serif; + font-weight: 700; + color: #ffffff; +} +button { + border-radius: 0; + border: 2px solid rgba(0,0,0,0.45); + background-image: none; + box-shadow: none; + text-shadow: none; + padding: 0; + min-height: 0; + min-width: 0; +} + +/* ---------- navy title banner ---------- */ +#ConditionNameLabel { + font-family: 'Noto Sans JP', 'IPAPGothic', sans-serif; + font-size: 46px; + font-weight: 700; + color: #ffffff; + background-color: #0B3B6B; + padding: 10px 26px; + margin: 14px 40px 24px 40px; +} + +/* ---------- splash / main menu ---------- */ #Option1Button, #Option2Button, #Option3Button { - font-size: 34px; /* was 26px */ - font-weight: 700; - border-radius: 16px; - background-color: #ffffff; - border: 1px solid #d8d8de; - box-shadow: 0 2px 4px rgba(0,0,0,0.08); + min-height: 95px; + background-color: #6A991A; } -#Option1Button:hover, #Option2Button:hover, #Option3Button:hover { - background-color: #eef3ff; - border-color: #a9c3ff; +#Option1Button label, #Option2Button label, #Option3Button label { font-size: 34px; } +#Option1Button:hover, #Option2Button:hover, #Option3Button:hover { background-color: #7BAE22; } +#Option1Button:active, #Option2Button:active, #Option3Button:active { background-color: #5A8315; } + +#SettingButton { min-height: 95px;min-width: 200px; background-color: #F97F00; } +#SettingButton label { font-size: 34px; } +#SettingButton:hover { background-color: #FF9020; } +#SettingButton:active { background-color: #D96C00; } + +#CloseButton { min-height: 95px;min-width: 200px; background-color: #808080; } +#CloseButton label { font-size: 34px; color: #ffffff; } +#CloseButton:hover { background-color: #909090; } +#CloseButton:active { background-color: #6E6E6E; } + +#LanguageToggle { min-height: 46px; min-width: 80px; background-color: #ffffff; } +#LanguageToggle label { font-size: 20px; color: #1e1e1e; } +#LanguageToggle:checked { background-color: #0B3B6B; } +#LanguageToggle:checked label { color: #ffffff; } + +/* ---------- back buttons ---------- */ +#SoundBackButton, #MapBackButton, #SettingBackButton { + min-width: 100px; + min-height: 58px; + background-color: #F0F0F0; + border: 2px solid #B5B5B5; } -#Option1Button:active, #Option2Button:active, #Option3Button:active { - background-color: #dbe6ff; +#SoundBackButton label, #MapBackButton label, #SettingBackButton label { + font-size: 20px; + color: #111111; +} +#SoundBackButton:hover, #MapBackButton:hover, #SettingBackButton:hover { + background-color: #E2E2E2; } -#SettingButton, #CloseButton { - min-height: 56px; - min-width: 120px; - font-size: 24px; /* was 18px */ - font-weight: 600; - border-radius: 10px; - padding: 8px 18px; -} -#CloseButton { - background-color: #fdeaea; - border: 1px solid #f2b8b8; - color: #a12727; -} -#CloseButton:hover { background-color: #fbd6d6; } +/* ---------- dynamic sound-list buttons ---------- */ +.sound-clip { min-height: 74px; background-color: #3592C8; } +.sound-clip label { font-size: 20px; color: #ffffff; } +.sound-clip.heart { background-color: #CE3733; } +.sound-clip.lung { background-color: #3592C8; } -#LanguageToggle { - min-height: 52px; - min-width: 76px; - font-size: 24px; /* was 18px */ - border-radius: 26px; - padding: 6px 14px; -} +.sound-clip.compact { min-height: 52px; } +.sound-clip.compact label { font-size: 19px; } -#ConnectButton, #AutoConnectButton, #RefreshButton, #SettingBackButton { - min-height: 52px; - min-width: 160px; - font-size: 22px; /* was 18px */ - font-weight: 600; - border-radius: 10px; - padding: 8px 20px; -} -#ComPortComboBox { - min-height: 50px; - font-size: 22px; - padding: 6px 12px; - border-radius: 8px; -} -#StatusLabel.status-on { color: #2e7d32; font-weight: bold; } -#StatusLabel.status-off { color: #c62828; font-weight: bold; } +.sound-clip.top { min-height: 112px; } +.sound-clip.top label { font-size: 34px; } -#SoundBackButton, #SoundTestButton { - min-height: 52px; - min-width: 140px; - font-size: 22px; - font-weight: 600; - border-radius: 10px; - padding: 8px 20px; +/* ---------- settings page ---------- */ +#ConnectButton, #AutoConnectButton, #RefreshButton { + min-height: 46px; min-width: 150px; background-color: #0B3B6B; } +#ConnectButton label, #AutoConnectButton label, #RefreshButton label { font-size: 19px; } +#ComPortComboBox { min-height: 40px; font-size: 17px; } +#StatusLabel.status-on { color: #2e7d32; font-weight: bold; font-size: 17px; } +#StatusLabel.status-off { color: #c62828; font-weight: bold; font-size: 17px; } -.sound-clip { - min-height: 72px; - min-width: 140px; - font-size: 22px; - font-weight: 600; - border-radius: 12px; - padding: 10px 16px; -} +/* ══════════════════════════════════════════════════════════════════ + MAP PAGE ONLY — scoped under #MapBox, so nothing here can leak to + the splash, sound or settings pages. Sizes target the `label` node + directly because _scaleCssProvider emits a plain `label {}` rule + that beats any inherited value. + ══════════════════════════════════════════════════════════════════ */ -#MapBackButton { - min-height: 52px; - min-width: 140px; - font-size: 22px; - font-weight: 600; - border-radius: 10px; - padding: 8px 20px; -} +/* ── map page: composite widgets whose inner button node has no class ── */ -#CaseFrame > label, #BodyFrame > label, #ViewFrame > label { - font-size: 19px; - font-weight: 700; -} -#MapCaseLabel { - font-size: 21px; -} - -#BodySkeletonRadio, #BodyJacketRadio { - font-size: 21px; +/* GtkRadioButton with draw-indicator=False renders as a button node that + is a CHILD of the widget carrying .mappage, so button.mappage misses it. */ +#ViewFrontRadio, #ViewBackRadio, #ViewRightRadio, #ViewLeftRadio, +#ViewFrontRadio button, #ViewBackRadio button, +#ViewRightRadio button, #ViewLeftRadio button { + color: #111111; + background-color: #F0F0F0; + background-image: none; + border: 2px solid #B5B5B5; + border-radius: 0; min-height: 46px; } -#BodySkeletonRadio radio, #BodyJacketRadio radio { - min-width: 30px; - min-height: 30px; -} - -#ViewFrontRadio, #ViewBackRadio, #ViewRightRadio, #ViewLeftRadio { - min-height: 52px; - font-size: 21px; - font-weight: 600; - border-radius: 8px; - padding: 8px 4px; +#ViewFrontRadio label, #ViewBackRadio label, +#ViewRightRadio label, #ViewLeftRadio label { + color: #111111; + font-size: 18px; + font-weight: 700; } #ViewFrontRadio:checked, #ViewBackRadio:checked, -#ViewRightRadio:checked, #ViewLeftRadio:checked { +#ViewRightRadio:checked, #ViewLeftRadio:checked, +#ViewFrontRadio button:checked, #ViewBackRadio button:checked, +#ViewRightRadio button:checked, #ViewLeftRadio button:checked { background-color: #2e7d32; - color: white; + border-color: #1f5c23; +} +#ViewFrontRadio:checked label, #ViewBackRadio:checked label, +#ViewRightRadio:checked label, #ViewLeftRadio:checked label { + color: #ffffff; } -#HideCircleCheck, #BlackAudioCheck { - font-size: 20px; - min-height: 44px; +/* 再生テスト — accent fill, white text is correct here */ +#SoundTestButton { + background-color: #0B3B6B; + background-image: none; + border: 2px solid #072a4d; + border-radius: 0; + min-height: 46px; } -#HideCircleCheck check, #BlackAudioCheck check { - min-width: 30px; - min-height: 30px; -} +#SoundTestButton label { color: #ffffff; font-size: 18px; font-weight: 700; } +#SoundTestButton:hover { background-color: #14538F; } -#JacketSizeCombo { - min-height: 48px; - font-size: 20px; - border-radius: 8px; +/* サイズ combo — the visible box is a button node inside the combobox */ +#JacketSizeCombo, +#JacketSizeCombo button { + color: #111111; + background-color: #ffffff; + background-image: none; + border: 1px solid #B5B5B5; + border-radius: 0; + min-height: 36px; + min-width: 90px; } -#JacketSizeLabel { - font-size: 20px; +#JacketSizeCombo label, +#JacketSizeCombo button label, +#JacketSizeCombo cellview { + color: #111111; + font-size: 16px; + font-weight: 400; } +#JacketSizeCombo arrow { color: #111111; min-width: 16px; min-height: 16px; } -button { - min-height: 48px; - padding: 10px 18px; -} \ No newline at end of file +/* the popup list is a separate toplevel — style it too or it inherits white */ +#JacketSizeCombo window.popup, +#JacketSizeCombo window.popup list, +#JacketSizeCombo window.popup row label { + color: #111111; + background-color: #ffffff; + font-size: 16px; +} +window.popup list row label { color: #111111; } \ No newline at end of file