stat2025 commited on
Commit
12b7371
·
verified ·
1 Parent(s): e9af8e8

Upload 6 files

Browse files
Files changed (3) hide show
  1. app.js +104 -42
  2. index.html +3 -4
  3. style.css +58 -15
app.js CHANGED
@@ -70,6 +70,7 @@ let allRows = [];
70
  let visibleRows = [];
71
  let failedAttempts = 0;
72
  let toastTimer;
 
73
 
74
  function base64ToBytes(value) {
75
  const binary = atob(value);
@@ -120,8 +121,20 @@ function normalize(value) {
120
  .toLowerCase();
121
  }
122
 
 
 
 
 
 
 
 
 
 
 
123
  function rowToObject(row) {
124
- return Object.fromEntries(FIELD_KEYS.map((key, index) => [key, row[index] ?? ""]));
 
 
125
  }
126
 
127
  function uniqueSorted(values) {
@@ -159,18 +172,35 @@ async function copyText(text, successMessage) {
159
  }
160
 
161
  function buildMessage(row, index = null) {
162
- const title = index === null ? "بيانات العينة المطلوبة للتواصل:" : `العينة رقم ${index}:`;
163
- const lines = [
164
  title,
 
165
  row.sampleName && `اسم العينة: ${row.sampleName}`,
166
  row.recordNumber && `رقم السجل: ${row.recordNumber}`,
167
  row.fulfillmentStatus && `حالة الاستيفاء: ${row.fulfillmentStatus}`,
168
  row.activity && `النشاط: ${row.activity}`,
169
- row.phone && `رقم التواصل: ${row.phone}`,
 
 
 
 
170
  row.email && `البريد الإلكتروني: ${row.email}`,
171
  row.location && `الموقع: ${row.location}`,
172
  ].filter(Boolean);
173
- return lines.join("\n");
 
 
 
 
 
 
 
 
 
 
 
 
174
  }
175
 
176
  function createDetail(key, label, isContact, value) {
@@ -257,20 +287,26 @@ function renderStatusChips(rows) {
257
  }
258
 
259
  function applyFilters() {
 
260
  const researcher = researcherSelect.value;
261
- if (!researcher) {
 
 
262
  resultsSection.hidden = true;
263
  emptyState.hidden = false;
264
  return;
265
  }
266
 
267
  const status = statusSelect.value;
268
- const query = normalize(searchInput.value);
269
- const researcherRows = allRows.filter(
270
- (row) => row.supervisor === supervisorSelect.value && row.researcher === researcher,
271
- );
272
-
273
- visibleRows = researcherRows.filter((row) => {
 
 
 
274
  const matchesStatus = !status || row.fulfillmentStatus === status;
275
  const matchesSearch =
276
  !query ||
@@ -281,10 +317,17 @@ function applyFilters() {
281
 
282
  emptyState.hidden = true;
283
  resultsSection.hidden = false;
284
- resultsTitle.textContent = researcher;
285
- resultsMeta.textContent = `${visibleRows.length} من أصل ${researcherRows.length} عينة`;
 
 
 
 
 
 
286
  copyAllButton.disabled = visibleRows.length === 0;
287
- renderStatusChips(researcherRows);
 
288
 
289
  samplesGrid.replaceChildren(
290
  ...visibleRows.map((row, index) => createSampleCard(row, index)),
@@ -293,29 +336,23 @@ function applyFilters() {
293
  }
294
 
295
  function resetResearcherControls() {
296
- setOptions(researcherSelect, [], "اختر الباحث");
297
  setOptions(statusSelect, [], "جميع الحالات");
298
  researcherSelect.disabled = true;
299
  statusSelect.disabled = true;
300
- searchInput.disabled = true;
301
- searchInput.value = "";
302
  resultsSection.hidden = true;
303
  emptyState.hidden = false;
304
- emptyState.querySelector("h3").textContent = supervisorSelect.value
305
- ? "اختر الباحث"
306
- : "ابدأ باختيار المشرف";
307
- emptyState.querySelector("p").textContent = supervisorSelect.value
308
- ? "اختر اسم الباحث لعرض العينات المسندة إليه."
309
- : "لن تظهر أي بيانات للعينات حتى يتم اختيار المشرف والباحث.";
310
  }
311
 
312
  function initializeDashboard(data) {
313
  allRows = data.rows.map(rowToObject);
314
- setOptions(
315
- supervisorSelect,
316
- uniqueSorted(allRows.map((row) => row.supervisor)),
317
- "اختر المشرف",
318
- );
319
  resetResearcherControls();
320
  }
321
 
@@ -367,28 +404,48 @@ logoutButton.addEventListener("click", () => {
367
 
368
  supervisorSelect.addEventListener("change", () => {
369
  resetResearcherControls();
370
- if (!supervisorSelect.value) return;
 
 
 
 
371
 
372
  const researchers = uniqueSorted(
373
  allRows
374
- .filter((row) => row.supervisor === supervisorSelect.value)
 
 
 
 
375
  .map((row) => row.researcher),
376
  );
377
- setOptions(researcherSelect, researchers, "اختر الباحث");
 
 
 
 
 
 
 
 
 
378
  researcherSelect.disabled = false;
 
 
379
  });
380
 
381
  researcherSelect.addEventListener("change", () => {
382
- const rows = allRows.filter(
383
- (row) =>
384
- row.supervisor === supervisorSelect.value &&
385
- row.researcher === researcherSelect.value,
386
- );
 
 
 
387
  const statuses = uniqueSorted(rows.map((row) => row.fulfillmentStatus));
388
  setOptions(statusSelect, statuses, "جميع الحالات");
389
- statusSelect.disabled = !researcherSelect.value;
390
- searchInput.disabled = !researcherSelect.value;
391
- searchInput.value = "";
392
  applyFilters();
393
  });
394
 
@@ -397,9 +454,14 @@ searchInput.addEventListener("input", applyFilters);
397
 
398
  copyAllButton.addEventListener("click", () => {
399
  if (!visibleRows.length) return;
400
- const heading = `بيانات العينات الخاصة بالباحث: ${researcherSelect.value}`;
 
 
401
  const messages = visibleRows.map((row, index) => buildMessage(row, index + 1));
402
- copyText([heading, ...messages].join("\n\n--------------------\n\n"), "تم نسخ جميع العينات المعروضة");
 
 
 
403
  });
404
 
405
  if (!window.crypto?.subtle || typeof ENCRYPTED_DATA === "undefined") {
 
70
  let visibleRows = [];
71
  let failedAttempts = 0;
72
  let toastTimer;
73
+ const ALL_SUPERVISORS_VALUE = "__all_supervisors__";
74
 
75
  function base64ToBytes(value) {
76
  const binary = atob(value);
 
121
  .toLowerCase();
122
  }
123
 
124
+ function formatPhone(value) {
125
+ const raw = String(value ?? "").trim();
126
+ if (!raw) return "";
127
+ const digits = raw.replace(/\D/g, "");
128
+ if (!digits) return raw;
129
+ if (digits.startsWith("0")) return digits;
130
+ if (digits.startsWith("966")) return `0${digits.slice(3)}`;
131
+ return `0${digits}`;
132
+ }
133
+
134
  function rowToObject(row) {
135
+ const item = Object.fromEntries(FIELD_KEYS.map((key, index) => [key, row[index] ?? ""]));
136
+ item.phone = formatPhone(item.phone);
137
+ return item;
138
  }
139
 
140
  function uniqueSorted(values) {
 
172
  }
173
 
174
  function buildMessage(row, index = null) {
175
+ const title = index === null ? "بيانات العينة للتواصل" : `العينة رقم (${index})`;
176
+ const sampleLines = [
177
  title,
178
+ "────────────────────",
179
  row.sampleName && `اسم العينة: ${row.sampleName}`,
180
  row.recordNumber && `رقم السجل: ${row.recordNumber}`,
181
  row.fulfillmentStatus && `حالة الاستيفاء: ${row.fulfillmentStatus}`,
182
  row.activity && `النشاط: ${row.activity}`,
183
+ ].filter(Boolean);
184
+ const contactLines = [
185
+ "بيانات التواصل",
186
+ "────────────────────",
187
+ row.phone && `رقم التواصل: ${formatPhone(row.phone)}`,
188
  row.email && `البريد الإلكتروني: ${row.email}`,
189
  row.location && `الموقع: ${row.location}`,
190
  ].filter(Boolean);
191
+ const sections = [];
192
+
193
+ if (index === null) {
194
+ sections.push(
195
+ "السلام عليكم ورحمة الله وبركاته،",
196
+ "نأمل التكرم بالتواصل مع العينة التالية واستكمال الإجراء اللازم:",
197
+ );
198
+ }
199
+
200
+ sections.push(sampleLines.join("\n"));
201
+ if (contactLines.length > 2) sections.push(contactLines.join("\n"));
202
+ if (index === null) sections.push("شاكرين لكم تعاونكم.");
203
+ return sections.join("\n\n");
204
  }
205
 
206
  function createDetail(key, label, isContact, value) {
 
287
  }
288
 
289
  function applyFilters() {
290
+ const supervisor = supervisorSelect.value;
291
  const researcher = researcherSelect.value;
292
+ const query = normalize(searchInput.value);
293
+
294
+ if (!supervisor && !query) {
295
  resultsSection.hidden = true;
296
  emptyState.hidden = false;
297
  return;
298
  }
299
 
300
  const status = statusSelect.value;
301
+ const supervisorRows =
302
+ !supervisor || supervisor === ALL_SUPERVISORS_VALUE
303
+ ? allRows
304
+ : allRows.filter((row) => row.supervisor === supervisor);
305
+ const scopedRows = researcher
306
+ ? supervisorRows.filter((row) => row.researcher === researcher)
307
+ : supervisorRows;
308
+
309
+ visibleRows = scopedRows.filter((row) => {
310
  const matchesStatus = !status || row.fulfillmentStatus === status;
311
  const matchesSearch =
312
  !query ||
 
317
 
318
  emptyState.hidden = true;
319
  resultsSection.hidden = false;
320
+ resultsTitle.textContent =
321
+ researcher ||
322
+ (supervisor === ALL_SUPERVISORS_VALUE
323
+ ? "جميع العينات"
324
+ : supervisor
325
+ ? `عينات المشرف: ${supervisor}`
326
+ : "نتائج البحث");
327
+ resultsMeta.textContent = `${visibleRows.length} من أصل ${scopedRows.length} عينة`;
328
  copyAllButton.disabled = visibleRows.length === 0;
329
+ copyAllButton.textContent = researcher ? "نسخ جميع عينات الباحث" : "نسخ جميع النتائج المعروضة";
330
+ renderStatusChips(scopedRows);
331
 
332
  samplesGrid.replaceChildren(
333
  ...visibleRows.map((row, index) => createSampleCard(row, index)),
 
336
  }
337
 
338
  function resetResearcherControls() {
339
+ setOptions(researcherSelect, [], "جميع الباحثين");
340
  setOptions(statusSelect, [], "جميع الحالات");
341
  researcherSelect.disabled = true;
342
  statusSelect.disabled = true;
 
 
343
  resultsSection.hidden = true;
344
  emptyState.hidden = false;
345
+ emptyState.querySelector("h3").textContent = "ابحث أو اختر المشرف";
346
+ emptyState.querySelector("p").textContent =
347
+ "يمكنك البحث مباشرة باسم العينة أو رقم السجل، أو اختيار المشرف لعرض كامل عيناته.";
 
 
 
348
  }
349
 
350
  function initializeDashboard(data) {
351
  allRows = data.rows.map(rowToObject);
352
+ setOptions(supervisorSelect, uniqueSorted(allRows.map((row) => row.supervisor)), "اختر المشرف");
353
+ supervisorSelect.add(new Option("إبراهيم - جميع العينات", ALL_SUPERVISORS_VALUE), 1);
354
+ searchInput.value = "";
355
+ searchInput.disabled = false;
 
356
  resetResearcherControls();
357
  }
358
 
 
404
 
405
  supervisorSelect.addEventListener("change", () => {
406
  resetResearcherControls();
407
+ searchInput.value = "";
408
+ if (!supervisorSelect.value) {
409
+ applyFilters();
410
+ return;
411
+ }
412
 
413
  const researchers = uniqueSorted(
414
  allRows
415
+ .filter(
416
+ (row) =>
417
+ supervisorSelect.value === ALL_SUPERVISORS_VALUE ||
418
+ row.supervisor === supervisorSelect.value,
419
+ )
420
  .map((row) => row.researcher),
421
  );
422
+ const scopeRows =
423
+ supervisorSelect.value === ALL_SUPERVISORS_VALUE
424
+ ? allRows
425
+ : allRows.filter((row) => row.supervisor === supervisorSelect.value);
426
+ setOptions(researcherSelect, researchers, "جميع الباحثين");
427
+ setOptions(
428
+ statusSelect,
429
+ uniqueSorted(scopeRows.map((row) => row.fulfillmentStatus)),
430
+ "جميع الحالات",
431
+ );
432
  researcherSelect.disabled = false;
433
+ statusSelect.disabled = false;
434
+ applyFilters();
435
  });
436
 
437
  researcherSelect.addEventListener("change", () => {
438
+ const rows = allRows.filter((row) => {
439
+ const matchesSupervisor =
440
+ supervisorSelect.value === ALL_SUPERVISORS_VALUE ||
441
+ row.supervisor === supervisorSelect.value;
442
+ const matchesResearcher =
443
+ !researcherSelect.value || row.researcher === researcherSelect.value;
444
+ return matchesSupervisor && matchesResearcher;
445
+ });
446
  const statuses = uniqueSorted(rows.map((row) => row.fulfillmentStatus));
447
  setOptions(statusSelect, statuses, "جميع الحالات");
448
+ statusSelect.disabled = false;
 
 
449
  applyFilters();
450
  });
451
 
 
454
 
455
  copyAllButton.addEventListener("click", () => {
456
  if (!visibleRows.length) return;
457
+ const heading = researcherSelect.value
458
+ ? `بيانات العينات الخاصة بالباحث: ${researcherSelect.value}`
459
+ : `بيانات العينات المعروضة (${visibleRows.length} عينة)`;
460
  const messages = visibleRows.map((row, index) => buildMessage(row, index + 1));
461
+ copyText(
462
+ [heading, "════════════════════", ...messages].join("\n\n"),
463
+ "تم نسخ جميع العينات المعروضة",
464
+ );
465
  });
466
 
467
  if (!window.crypto?.subtle || typeof ENCRYPTED_DATA === "undefined") {
index.html CHANGED
@@ -98,7 +98,7 @@
98
  <div>
99
  <p class="eyebrow">لوحة الاستعلام</p>
100
  <h2>الوصول إلى بيانات العينة بسهولة</h2>
101
- <p>اختر المشرف والباحث، ثم استخدم البحث والفلاتر للوصول إلى العينة المطلوبة.</p>
102
  </div>
103
  <div class="privacy-pill">
104
  <span class="status-dot"></span>
@@ -149,7 +149,6 @@
149
  id="searchInput"
150
  type="search"
151
  placeholder="اسم العينة أو رقم السجل"
152
- disabled
153
  />
154
  </div>
155
  </div>
@@ -163,8 +162,8 @@
163
  <path d="M15 8h18v10H15zM15 26h18M15 33h11" />
164
  </svg>
165
  </div>
166
- <h3>ابدأ باختيار المشرف</h3>
167
- <p>لن تظهر أي بيانات للعينات حتى يتم اختيار المشرف والباحث.</p>
168
  </section>
169
 
170
  <section id="resultsSection" class="results-section" hidden>
 
98
  <div>
99
  <p class="eyebrow">لوحة الاستعلام</p>
100
  <h2>الوصول إلى بيانات العينة بسهولة</h2>
101
+ <p>ابحث مباشرة، أو اختر المشرف لعرض عيناته ثم حدّد الباحث عند الحاجة.</p>
102
  </div>
103
  <div class="privacy-pill">
104
  <span class="status-dot"></span>
 
149
  id="searchInput"
150
  type="search"
151
  placeholder="اسم العينة أو رقم السجل"
 
152
  />
153
  </div>
154
  </div>
 
162
  <path d="M15 8h18v10H15zM15 26h18M15 33h11" />
163
  </svg>
164
  </div>
165
+ <h3>ابحث أو اختر المشرف</h3>
166
+ <p>اكتب اسم العينة أو رقم السجل مباشرة، أو اختر المشرف لعرض كامل عيناته.</p>
167
  </section>
168
 
169
  <section id="resultsSection" class="results-section" hidden>
style.css CHANGED
@@ -27,6 +27,7 @@ body {
27
  min-height: 100vh;
28
  margin: 0;
29
  color: var(--ink);
 
30
  font-family: "Tajawal", Arial, sans-serif;
31
  background:
32
  radial-gradient(circle at 10% 10%, rgba(41, 151, 173, 0.12), transparent 30%),
@@ -154,7 +155,7 @@ svg {
154
  max-width: 340px;
155
  margin: 12px auto 28px;
156
  color: var(--muted);
157
- font-size: 15px;
158
  line-height: 1.8;
159
  }
160
 
@@ -167,7 +168,7 @@ svg {
167
  display: block;
168
  margin-bottom: 8px;
169
  color: #314b5e;
170
- font-size: 14px;
171
  font-weight: 700;
172
  }
173
 
@@ -186,6 +187,7 @@ svg {
186
  background: #fbfdfe;
187
  border: 1px solid var(--line);
188
  border-radius: 14px;
 
189
  outline: none;
190
  transition: border-color 0.2s, box-shadow 0.2s, background 0.2s;
191
  }
@@ -353,8 +355,11 @@ svg {
353
  gap: 24px;
354
  padding: 24px 28px;
355
  color: white;
 
 
356
  background:
357
- linear-gradient(115deg, rgba(10, 44, 80, 0.98), rgba(29, 101, 155, 0.92)),
 
358
  var(--navy);
359
  border-radius: 22px;
360
  box-shadow: 0 14px 32px rgba(18, 60, 105, 0.17);
@@ -372,7 +377,7 @@ svg {
372
  .welcome-panel > div > p:last-child {
373
  margin: 0;
374
  color: rgba(255, 255, 255, 0.77);
375
- font-size: 14px;
376
  }
377
 
378
  .privacy-pill {
@@ -403,7 +408,7 @@ svg {
403
  background: var(--surface);
404
  border: 1px solid var(--line);
405
  border-radius: 20px;
406
- box-shadow: 0 10px 26px rgba(24, 66, 91, 0.06);
407
  }
408
 
409
  .filters-grid {
@@ -501,14 +506,14 @@ input:disabled {
501
  .results-meta {
502
  margin: 0 0 4px;
503
  color: var(--teal);
504
- font-size: 13px;
505
  font-weight: 800;
506
  }
507
 
508
  .results-header h2 {
509
  margin: 0;
510
  color: var(--navy-dark);
511
- font-size: 24px;
512
  }
513
 
514
  .copy-all {
@@ -527,7 +532,7 @@ input:disabled {
527
  .status-chip {
528
  padding: 7px 11px;
529
  color: #466071;
530
- font-size: 12px;
531
  font-weight: 700;
532
  background: white;
533
  border: 1px solid var(--line);
@@ -549,8 +554,8 @@ input:disabled {
549
  overflow: hidden;
550
  background: white;
551
  border: 1px solid var(--line);
552
- border-radius: 19px;
553
- box-shadow: 0 8px 24px rgba(26, 63, 87, 0.055);
554
  transition: transform 0.2s, box-shadow 0.2s, border-color 0.2s;
555
  }
556
 
@@ -568,20 +573,21 @@ input:disabled {
568
  padding: 18px 20px 15px;
569
  background: linear-gradient(180deg, #fbfdfe, white);
570
  border-bottom: 1px solid #edf2f5;
 
571
  }
572
 
573
  .sample-index {
574
  display: inline-block;
575
  margin-bottom: 5px;
576
  color: var(--teal);
577
- font-size: 11px;
578
  font-weight: 800;
579
  }
580
 
581
  .sample-card h3 {
582
  margin: 0;
583
  color: var(--navy-dark);
584
- font-size: 17px;
585
  line-height: 1.65;
586
  }
587
 
@@ -590,7 +596,7 @@ input:disabled {
590
  max-width: 155px;
591
  padding: 7px 10px;
592
  color: #8f4f16;
593
- font-size: 11px;
594
  font-weight: 800;
595
  line-height: 1.4;
596
  text-align: center;
@@ -625,7 +631,7 @@ input:disabled {
625
  display: block;
626
  margin-bottom: 5px;
627
  color: var(--muted);
628
- font-size: 11px;
629
  font-weight: 700;
630
  }
631
 
@@ -633,7 +639,7 @@ input:disabled {
633
  display: block;
634
  overflow-wrap: anywhere;
635
  color: #233d4f;
636
- font-size: 13px;
637
  font-weight: 600;
638
  line-height: 1.6;
639
  }
@@ -654,6 +660,7 @@ input:disabled {
654
  background: var(--sky);
655
  border: 1px solid #cde2ee;
656
  border-radius: 12px;
 
657
  }
658
 
659
  .copy-sample:hover {
@@ -728,6 +735,10 @@ footer {
728
  .copy-all {
729
  width: 100%;
730
  }
 
 
 
 
731
  }
732
 
733
  @media (max-width: 560px) {
@@ -766,6 +777,18 @@ footer {
766
 
767
  .filters-grid {
768
  grid-template-columns: 1fr;
 
 
 
 
 
 
 
 
 
 
 
 
769
  }
770
 
771
  .sample-card-header {
@@ -778,6 +801,7 @@ footer {
778
 
779
  .sample-details {
780
  grid-template-columns: 1fr;
 
781
  }
782
 
783
  .detail-item:nth-child(odd),
@@ -786,6 +810,25 @@ footer {
786
  padding-left: 0;
787
  border-left: 0;
788
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
789
  }
790
 
791
  @media (prefers-reduced-motion: reduce) {
 
27
  min-height: 100vh;
28
  margin: 0;
29
  color: var(--ink);
30
+ font-size: 16px;
31
  font-family: "Tajawal", Arial, sans-serif;
32
  background:
33
  radial-gradient(circle at 10% 10%, rgba(41, 151, 173, 0.12), transparent 30%),
 
155
  max-width: 340px;
156
  margin: 12px auto 28px;
157
  color: var(--muted);
158
+ font-size: 16px;
159
  line-height: 1.8;
160
  }
161
 
 
168
  display: block;
169
  margin-bottom: 8px;
170
  color: #314b5e;
171
+ font-size: 15px;
172
  font-weight: 700;
173
  }
174
 
 
187
  background: #fbfdfe;
188
  border: 1px solid var(--line);
189
  border-radius: 14px;
190
+ font-size: 16px;
191
  outline: none;
192
  transition: border-color 0.2s, box-shadow 0.2s, background 0.2s;
193
  }
 
355
  gap: 24px;
356
  padding: 24px 28px;
357
  color: white;
358
+ overflow: hidden;
359
+ position: relative;
360
  background:
361
+ radial-gradient(circle at 12% 130%, rgba(89, 223, 206, 0.28), transparent 32%),
362
+ linear-gradient(115deg, rgba(8, 39, 72, 0.99), rgba(25, 105, 161, 0.95)),
363
  var(--navy);
364
  border-radius: 22px;
365
  box-shadow: 0 14px 32px rgba(18, 60, 105, 0.17);
 
377
  .welcome-panel > div > p:last-child {
378
  margin: 0;
379
  color: rgba(255, 255, 255, 0.77);
380
+ font-size: 15px;
381
  }
382
 
383
  .privacy-pill {
 
408
  background: var(--surface);
409
  border: 1px solid var(--line);
410
  border-radius: 20px;
411
+ box-shadow: 0 14px 34px rgba(24, 66, 91, 0.08);
412
  }
413
 
414
  .filters-grid {
 
506
  .results-meta {
507
  margin: 0 0 4px;
508
  color: var(--teal);
509
+ font-size: 14px;
510
  font-weight: 800;
511
  }
512
 
513
  .results-header h2 {
514
  margin: 0;
515
  color: var(--navy-dark);
516
+ font-size: 26px;
517
  }
518
 
519
  .copy-all {
 
532
  .status-chip {
533
  padding: 7px 11px;
534
  color: #466071;
535
+ font-size: 13px;
536
  font-weight: 700;
537
  background: white;
538
  border: 1px solid var(--line);
 
554
  overflow: hidden;
555
  background: white;
556
  border: 1px solid var(--line);
557
+ border-radius: 21px;
558
+ box-shadow: 0 10px 28px rgba(26, 63, 87, 0.07);
559
  transition: transform 0.2s, box-shadow 0.2s, border-color 0.2s;
560
  }
561
 
 
573
  padding: 18px 20px 15px;
574
  background: linear-gradient(180deg, #fbfdfe, white);
575
  border-bottom: 1px solid #edf2f5;
576
+ border-top: 4px solid var(--teal);
577
  }
578
 
579
  .sample-index {
580
  display: inline-block;
581
  margin-bottom: 5px;
582
  color: var(--teal);
583
+ font-size: 12px;
584
  font-weight: 800;
585
  }
586
 
587
  .sample-card h3 {
588
  margin: 0;
589
  color: var(--navy-dark);
590
+ font-size: 19px;
591
  line-height: 1.65;
592
  }
593
 
 
596
  max-width: 155px;
597
  padding: 7px 10px;
598
  color: #8f4f16;
599
+ font-size: 12px;
600
  font-weight: 800;
601
  line-height: 1.4;
602
  text-align: center;
 
631
  display: block;
632
  margin-bottom: 5px;
633
  color: var(--muted);
634
+ font-size: 12px;
635
  font-weight: 700;
636
  }
637
 
 
639
  display: block;
640
  overflow-wrap: anywhere;
641
  color: #233d4f;
642
+ font-size: 15px;
643
  font-weight: 600;
644
  line-height: 1.6;
645
  }
 
660
  background: var(--sky);
661
  border: 1px solid #cde2ee;
662
  border-radius: 12px;
663
+ font-size: 15px;
664
  }
665
 
666
  .copy-sample:hover {
 
735
  .copy-all {
736
  width: 100%;
737
  }
738
+
739
+ .results-header h2 {
740
+ font-size: 23px;
741
+ }
742
  }
743
 
744
  @media (max-width: 560px) {
 
777
 
778
  .filters-grid {
779
  grid-template-columns: 1fr;
780
+ gap: 13px;
781
+ }
782
+
783
+ .search-group {
784
+ grid-row: 1;
785
+ }
786
+
787
+ .password-field input,
788
+ .search-wrap input,
789
+ .select-wrap select {
790
+ height: 56px;
791
+ font-size: 16px;
792
  }
793
 
794
  .sample-card-header {
 
801
 
802
  .sample-details {
803
  grid-template-columns: 1fr;
804
+ padding: 4px 17px;
805
  }
806
 
807
  .detail-item:nth-child(odd),
 
810
  padding-left: 0;
811
  border-left: 0;
812
  }
813
+
814
+ .sample-card-header,
815
+ .sample-card-footer {
816
+ padding-right: 17px;
817
+ padding-left: 17px;
818
+ }
819
+
820
+ .detail-label {
821
+ font-size: 13px;
822
+ }
823
+
824
+ .detail-value {
825
+ font-size: 16px;
826
+ }
827
+
828
+ .copy-sample {
829
+ min-height: 48px;
830
+ font-size: 16px;
831
+ }
832
  }
833
 
834
  @media (prefers-reduced-motion: reduce) {