Upload 2 files
Browse files- depth_interactive_map_alpha.R +51 -21
- styles.css +30 -28
depth_interactive_map_alpha.R
CHANGED
|
@@ -54,6 +54,29 @@ source("helpers.R")
|
|
| 54 |
|
| 55 |
`%||%` <- function(x, y) if (is.null(x) || length(x) == 0) y else x
|
| 56 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 57 |
# Deployment edit (v10_HF): DuckDB path from env var, baked into the image.
|
| 58 |
DB_PATH <- Sys.getenv("DEPTH_DDB_PATH", "/app/depth_mexico.duckdb")
|
| 59 |
|
|
@@ -1297,14 +1320,14 @@ WEB_SPEC <- list(
|
|
| 1297 |
subtitle = "Summary of main indicators for migrants across Mexico.",
|
| 1298 |
groups = list(
|
| 1299 |
list(id = "hazards", label = "Hazards", open = TRUE, cards = list(
|
| 1300 |
-
list(title = "
|
| 1301 |
stats = list(
|
| 1302 |
list(id = "n_incidents", label = "Recorded incidents", color = COL_YEL),
|
| 1303 |
list(id = "n_fatalities", label = "Confirmed dead", color = COL_RED)
|
| 1304 |
),
|
| 1305 |
charts = list(
|
| 1306 |
list(id = "migrants_treemap_cause", label = "Cause of death",
|
| 1307 |
-
height = "
|
| 1308 |
list(id = "migrants_treemap_demo", label = "Demographics (children / female / male)",
|
| 1309 |
height = "44px")
|
| 1310 |
)),
|
|
@@ -1670,10 +1693,12 @@ LUCIDE_JS <- tags$head(
|
|
| 1670 |
};
|
| 1671 |
|
| 1672 |
// Format a ym integer back to year-dash-month (e.g. 2014-03) for the label.
|
|
|
|
|
|
|
| 1673 |
function _ymFmt(v) {
|
| 1674 |
var y = Math.floor(v / 12);
|
| 1675 |
-
var m =
|
| 1676 |
-
return
|
| 1677 |
}
|
| 1678 |
|
| 1679 |
function syncTemporalStrip(checkedIds) {
|
|
@@ -1791,7 +1816,7 @@ LUCIDE_JS <- tags$head(
|
|
| 1791 |
if (document.activeElement === startEl) { hi = lo; endEl.value = hi; }
|
| 1792 |
else { lo = hi; startEl.value = lo; }
|
| 1793 |
}
|
| 1794 |
-
if (label) label.textContent = _ymFmt(lo) + '
|
| 1795 |
if (fill) {
|
| 1796 |
var min = parseInt(startEl.min, 10);
|
| 1797 |
var max = parseInt(startEl.max, 10);
|
|
@@ -2706,7 +2731,8 @@ render_panel_groups <- function() {
|
|
| 2706 |
|
| 2707 |
ui <- page_fillable(
|
| 2708 |
theme = bs_theme(version = 5, bg = "#FAFAFB", fg = "#0F172A",
|
| 2709 |
-
primary = "#006B82",
|
|
|
|
| 2710 |
padding = 0,
|
| 2711 |
LUCIDE_JS,
|
| 2712 |
includeCSS("styles.css"),
|
|
@@ -4587,14 +4613,18 @@ server <- function(input, output, session) {
|
|
| 4587 |
# to the in-polygon subset when one is). Treemap geometry is a 2-row slice-
|
| 4588 |
# and-dice -- the dominant category gets the top row, smaller categories
|
| 4589 |
# tile the bottom row. Avoids the treemapify dependency.
|
| 4590 |
-
|
| 4591 |
-
|
| 4592 |
-
|
| 4593 |
-
"
|
| 4594 |
-
"
|
| 4595 |
-
|
| 4596 |
-
|
| 4597 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4598 |
|
| 4599 |
treemap_layout <- function(df) {
|
| 4600 |
# df: data.frame(label, value, color); returns df with xmin/xmax/ymin/ymax
|
|
@@ -4642,12 +4672,12 @@ server <- function(input, output, session) {
|
|
| 4642 |
ggplot(laid, aes(xmin = xmin, xmax = xmax,
|
| 4643 |
ymin = ymin, ymax = ymax,
|
| 4644 |
fill = label)) +
|
| 4645 |
-
geom_rect(color = "#
|
| 4646 |
geom_text(aes(x = cx, y = cy + 0.10, label = short),
|
| 4647 |
-
size = 2.2, color = "white",
|
| 4648 |
fontface = "bold", lineheight = 0.9) +
|
| 4649 |
geom_text(aes(x = cx, y = cy - 0.18, label = paste0(pct, "%")),
|
| 4650 |
-
size = 1.9, color = "white", alpha = 0.85) +
|
| 4651 |
scale_fill_manual(values = pal, na.value = "#334155") +
|
| 4652 |
coord_cartesian(expand = FALSE, xlim = c(0, 1), ylim = c(0, 1)) +
|
| 4653 |
theme_void() +
|
|
@@ -4727,7 +4757,7 @@ server <- function(input, output, session) {
|
|
| 4727 |
geom_point(data = df_sel, aes(x = yr, y = n),
|
| 4728 |
color = line_color, size = 1.6, shape = 21,
|
| 4729 |
fill = "white", stroke = 0.7)
|
| 4730 |
-
p + theme_minimal(base_size = 8) +
|
| 4731 |
theme(
|
| 4732 |
plot.background = element_rect(fill = "transparent", color = NA),
|
| 4733 |
panel.background = element_rect(fill = "transparent", color = NA),
|
|
@@ -4782,19 +4812,19 @@ server <- function(input, output, session) {
|
|
| 4782 |
|
| 4783 |
ggplot(df_all, aes(x = ym, y = n, fill = in_win)) +
|
| 4784 |
geom_col(width = 1, color = NA) +
|
| 4785 |
-
scale_fill_manual(values = c(`FALSE` = "#
|
| 4786 |
`TRUE` = bar_color)) +
|
| 4787 |
scale_x_continuous(breaks = yr_breaks, labels = yr_labels,
|
| 4788 |
limits = c(ym_data_lo - 0.5, ym_data_hi + 0.5),
|
| 4789 |
expand = expansion(mult = c(0, 0))) +
|
| 4790 |
scale_y_continuous(expand = expansion(mult = c(0, 0.05))) +
|
| 4791 |
labs(x = NULL, y = NULL) +
|
| 4792 |
-
theme_minimal(base_size = 8) +
|
| 4793 |
theme(plot.background = element_rect(fill = "transparent", color = NA),
|
| 4794 |
panel.background = element_rect(fill = "transparent", color = NA),
|
| 4795 |
panel.grid = element_blank(),
|
| 4796 |
axis.title = element_blank(),
|
| 4797 |
-
axis.text.x = element_text(size = 7.5, color = "#
|
| 4798 |
axis.text.y = element_blank(),
|
| 4799 |
axis.ticks = element_blank(),
|
| 4800 |
legend.position = "none",
|
|
|
|
| 54 |
|
| 55 |
`%||%` <- function(x, y) if (is.null(x) || length(x) == 0) y else x
|
| 56 |
|
| 57 |
+
# --- Plot fonts -----------------------------------------------------------------
|
| 58 |
+
# ggplot text (treemaps, temporal strip, mini-charts) uses the Rights Lab brand
|
| 59 |
+
# font when showtext + sysfonts are available in the image; otherwise it falls
|
| 60 |
+
# back to the device sans (never Inter). Guarded so a missing package or an
|
| 61 |
+
# offline Google fetch can never break the app at startup.
|
| 62 |
+
PLOT_FONT <- "sans"
|
| 63 |
+
if (requireNamespace("showtext", quietly = TRUE) &&
|
| 64 |
+
requireNamespace("sysfonts", quietly = TRUE)) {
|
| 65 |
+
font_ok <- tryCatch({
|
| 66 |
+
sysfonts::font_add_google("Source Sans 3", "depth_sans")
|
| 67 |
+
TRUE
|
| 68 |
+
}, error = function(e) {
|
| 69 |
+
message("[fonts] Google font fetch failed; using system sans: ",
|
| 70 |
+
conditionMessage(e))
|
| 71 |
+
FALSE
|
| 72 |
+
})
|
| 73 |
+
if (isTRUE(font_ok)) {
|
| 74 |
+
PLOT_FONT <- "depth_sans"
|
| 75 |
+
showtext::showtext_auto()
|
| 76 |
+
showtext::showtext_opts(dpi = 110)
|
| 77 |
+
}
|
| 78 |
+
}
|
| 79 |
+
|
| 80 |
# Deployment edit (v10_HF): DuckDB path from env var, baked into the image.
|
| 81 |
DB_PATH <- Sys.getenv("DEPTH_DDB_PATH", "/app/depth_mexico.duckdb")
|
| 82 |
|
|
|
|
| 1320 |
subtitle = "Summary of main indicators for migrants across Mexico.",
|
| 1321 |
groups = list(
|
| 1322 |
list(id = "hazards", label = "Hazards", open = TRUE, cards = list(
|
| 1323 |
+
list(title = "Deaths during migration", kind = "stat",
|
| 1324 |
stats = list(
|
| 1325 |
list(id = "n_incidents", label = "Recorded incidents", color = COL_YEL),
|
| 1326 |
list(id = "n_fatalities", label = "Confirmed dead", color = COL_RED)
|
| 1327 |
),
|
| 1328 |
charts = list(
|
| 1329 |
list(id = "migrants_treemap_cause", label = "Cause of death",
|
| 1330 |
+
height = "60px"),
|
| 1331 |
list(id = "migrants_treemap_demo", label = "Demographics (children / female / male)",
|
| 1332 |
height = "44px")
|
| 1333 |
)),
|
|
|
|
| 1693 |
};
|
| 1694 |
|
| 1695 |
// Format a ym integer back to year-dash-month (e.g. 2014-03) for the label.
|
| 1696 |
+
var _MONTHS = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug',
|
| 1697 |
+
'Sep','Oct','Nov','Dec'];
|
| 1698 |
function _ymFmt(v) {
|
| 1699 |
var y = Math.floor(v / 12);
|
| 1700 |
+
var m = v % 12; // 0 = January (ym packs month - 1)
|
| 1701 |
+
return _MONTHS[m] + ' ' + y;
|
| 1702 |
}
|
| 1703 |
|
| 1704 |
function syncTemporalStrip(checkedIds) {
|
|
|
|
| 1816 |
if (document.activeElement === startEl) { hi = lo; endEl.value = hi; }
|
| 1817 |
else { lo = hi; startEl.value = lo; }
|
| 1818 |
}
|
| 1819 |
+
if (label) label.textContent = _ymFmt(lo) + ' to ' + _ymFmt(hi);
|
| 1820 |
if (fill) {
|
| 1821 |
var min = parseInt(startEl.min, 10);
|
| 1822 |
var max = parseInt(startEl.max, 10);
|
|
|
|
| 2731 |
|
| 2732 |
ui <- page_fillable(
|
| 2733 |
theme = bs_theme(version = 5, bg = "#FAFAFB", fg = "#0F172A",
|
| 2734 |
+
primary = "#006B82",
|
| 2735 |
+
base_font = font_google("Source Sans 3")),
|
| 2736 |
padding = 0,
|
| 2737 |
LUCIDE_JS,
|
| 2738 |
includeCSS("styles.css"),
|
|
|
|
| 4613 |
# to the in-polygon subset when one is). Treemap geometry is a 2-row slice-
|
| 4614 |
# and-dice -- the dominant category gets the top row, smaller categories
|
| 4615 |
# tile the bottom row. Avoids the treemapify dependency.
|
| 4616 |
+
# Re-toned to the muted Spatial data palette so the treemaps speak the same
|
| 4617 |
+
# colour language as the map points (no Tailwind-bright sky / red / purple).
|
| 4618 |
+
CAUSE_PAL <- c("Other / unknown" = "#374151", # neutral slate (COL_COUNT)
|
| 4619 |
+
"Drowning" = "#0987A8", # teal-blue / water
|
| 4620 |
+
"Harsh environment" = "#B89307", # ochre / heat
|
| 4621 |
+
"Vehicle accident" = "#7E4A86", # mauve
|
| 4622 |
+
"Violence" = "#9E2A3A") # brick red
|
| 4623 |
+
# Demographics are nominal (not ordered) and carry no risk valence -- three
|
| 4624 |
+
# distinct muted hues, avoiding the pink = female / blue = male cliche.
|
| 4625 |
+
DEMO_PAL <- c(Children = "#B89307", # ochre
|
| 4626 |
+
Female = "#7E4A86", # mauve
|
| 4627 |
+
Male = "#3A4B5C") # slate
|
| 4628 |
|
| 4629 |
treemap_layout <- function(df) {
|
| 4630 |
# df: data.frame(label, value, color); returns df with xmin/xmax/ymin/ymax
|
|
|
|
| 4672 |
ggplot(laid, aes(xmin = xmin, xmax = xmax,
|
| 4673 |
ymin = ymin, ymax = ymax,
|
| 4674 |
fill = label)) +
|
| 4675 |
+
geom_rect(color = "#ffffff", linewidth = 0.7) +
|
| 4676 |
geom_text(aes(x = cx, y = cy + 0.10, label = short),
|
| 4677 |
+
size = 2.2, color = "white", family = PLOT_FONT,
|
| 4678 |
fontface = "bold", lineheight = 0.9) +
|
| 4679 |
geom_text(aes(x = cx, y = cy - 0.18, label = paste0(pct, "%")),
|
| 4680 |
+
size = 1.9, color = "white", family = PLOT_FONT, alpha = 0.85) +
|
| 4681 |
scale_fill_manual(values = pal, na.value = "#334155") +
|
| 4682 |
coord_cartesian(expand = FALSE, xlim = c(0, 1), ylim = c(0, 1)) +
|
| 4683 |
theme_void() +
|
|
|
|
| 4757 |
geom_point(data = df_sel, aes(x = yr, y = n),
|
| 4758 |
color = line_color, size = 1.6, shape = 21,
|
| 4759 |
fill = "white", stroke = 0.7)
|
| 4760 |
+
p + theme_minimal(base_size = 8, base_family = PLOT_FONT) +
|
| 4761 |
theme(
|
| 4762 |
plot.background = element_rect(fill = "transparent", color = NA),
|
| 4763 |
panel.background = element_rect(fill = "transparent", color = NA),
|
|
|
|
| 4812 |
|
| 4813 |
ggplot(df_all, aes(x = ym, y = n, fill = in_win)) +
|
| 4814 |
geom_col(width = 1, color = NA) +
|
| 4815 |
+
scale_fill_manual(values = c(`FALSE` = "#cdd3db",
|
| 4816 |
`TRUE` = bar_color)) +
|
| 4817 |
scale_x_continuous(breaks = yr_breaks, labels = yr_labels,
|
| 4818 |
limits = c(ym_data_lo - 0.5, ym_data_hi + 0.5),
|
| 4819 |
expand = expansion(mult = c(0, 0))) +
|
| 4820 |
scale_y_continuous(expand = expansion(mult = c(0, 0.05))) +
|
| 4821 |
labs(x = NULL, y = NULL) +
|
| 4822 |
+
theme_minimal(base_size = 8, base_family = PLOT_FONT) +
|
| 4823 |
theme(plot.background = element_rect(fill = "transparent", color = NA),
|
| 4824 |
panel.background = element_rect(fill = "transparent", color = NA),
|
| 4825 |
panel.grid = element_blank(),
|
| 4826 |
axis.title = element_blank(),
|
| 4827 |
+
axis.text.x = element_text(size = 7.5, color = "#475569"),
|
| 4828 |
axis.text.y = element_blank(),
|
| 4829 |
axis.ticks = element_blank(),
|
| 4830 |
legend.position = "none",
|
styles.css
CHANGED
|
@@ -3,7 +3,7 @@
|
|
| 3 |
Renamed from 10.08_styles.css on 2026-05-20.
|
| 4 |
============================================================================ */
|
| 5 |
|
| 6 |
-
@import url('https://fonts.googleapis.com/css2?family=
|
| 7 |
|
| 8 |
/* -- Design tokens --------------------------------------------------------- */
|
| 9 |
:root {
|
|
@@ -61,17 +61,18 @@
|
|
| 61 |
/* Glass blur */
|
| 62 |
--blur-glass: saturate(140%) blur(14px);
|
| 63 |
|
| 64 |
-
/* Typography —
|
| 65 |
-
|
| 66 |
-
--font-
|
|
|
|
| 67 |
|
| 68 |
-
/*
|
| 69 |
-
--font-label:
|
| 70 |
--font-body: var(--font-ui);
|
| 71 |
|
| 72 |
/* Motion — Spatial spring */
|
| 73 |
--ease-out: cubic-bezier(0.22, 1, 0.36, 1);
|
| 74 |
-
--ease-spring: cubic-bezier(0.
|
| 75 |
--t-fast: 140ms; --t-base: 220ms; --t-slow: 320ms;
|
| 76 |
|
| 77 |
/* Radii */
|
|
@@ -421,9 +422,9 @@
|
|
| 421 |
}
|
| 422 |
|
| 423 |
.stat-val {
|
| 424 |
-
font-family: var(--font-
|
| 425 |
font-size: 30px;
|
| 426 |
-
font-weight:
|
| 427 |
font-variant-numeric: tabular-nums;
|
| 428 |
line-height: 1;
|
| 429 |
margin-bottom: 4px;
|
|
@@ -628,7 +629,6 @@
|
|
| 628 |
}
|
| 629 |
|
| 630 |
.ind-card:hover {
|
| 631 |
-
transform: translateY(-1px);
|
| 632 |
box-shadow: var(--depth-2);
|
| 633 |
}
|
| 634 |
|
|
@@ -1358,9 +1358,10 @@ button.mapbox-gl-draw_uncombine { display: none !important; }
|
|
| 1358 |
|
| 1359 |
/* ---- Brand ---- */
|
| 1360 |
.nav-brand {
|
| 1361 |
-
font-
|
| 1362 |
-
font-
|
| 1363 |
-
|
|
|
|
| 1364 |
text-transform: uppercase;
|
| 1365 |
color: var(--c-text);
|
| 1366 |
padding: 0 var(--space-2);
|
|
@@ -2512,10 +2513,10 @@ body.tooltips-off .maplibregl-popup { display: none !important; }
|
|
| 2512 |
margin-left: auto;
|
| 2513 |
margin-right: auto;
|
| 2514 |
z-index: 950;
|
| 2515 |
-
background:
|
| 2516 |
-
backdrop-filter:
|
| 2517 |
-
-webkit-backdrop-filter:
|
| 2518 |
-
border: 1px solid
|
| 2519 |
border-radius: var(--radius-md);
|
| 2520 |
box-shadow: var(--depth-3);
|
| 2521 |
padding: 6px 12px 8px;
|
|
@@ -2558,8 +2559,8 @@ body.tooltips-off .maplibregl-popup { display: none !important; }
|
|
| 2558 |
.temporal-play-btn,
|
| 2559 |
.temporal-reset-btn {
|
| 2560 |
background: transparent;
|
| 2561 |
-
color:
|
| 2562 |
-
border: 1px solid
|
| 2563 |
cursor: pointer;
|
| 2564 |
font-family: var(--font-ui);
|
| 2565 |
transition: background var(--t-fast) var(--ease-out),
|
|
@@ -2586,8 +2587,9 @@ body.tooltips-off .maplibregl-popup { display: none !important; }
|
|
| 2586 |
}
|
| 2587 |
.temporal-play-btn:hover,
|
| 2588 |
.temporal-reset-btn:hover {
|
| 2589 |
-
background:
|
| 2590 |
-
border-color:
|
|
|
|
| 2591 |
}
|
| 2592 |
.temporal-play-btn:focus-visible,
|
| 2593 |
.temporal-reset-btn:focus-visible {
|
|
@@ -2609,7 +2611,7 @@ body.tooltips-off .maplibregl-popup { display: none !important; }
|
|
| 2609 |
top: 50%;
|
| 2610 |
transform: translateY(-50%);
|
| 2611 |
height: 3px;
|
| 2612 |
-
background:
|
| 2613 |
border-radius: 2px;
|
| 2614 |
pointer-events: none;
|
| 2615 |
}
|
|
@@ -2644,8 +2646,8 @@ body.tooltips-off .maplibregl-popup { display: none !important; }
|
|
| 2644 |
height: 14px;
|
| 2645 |
border-radius: 50%;
|
| 2646 |
background: #ffffff;
|
| 2647 |
-
border: 2px solid
|
| 2648 |
-
box-shadow:
|
| 2649 |
cursor: pointer;
|
| 2650 |
margin-top: 0;
|
| 2651 |
}
|
|
@@ -2655,8 +2657,8 @@ body.tooltips-off .maplibregl-popup { display: none !important; }
|
|
| 2655 |
height: 14px;
|
| 2656 |
border-radius: 50%;
|
| 2657 |
background: #ffffff;
|
| 2658 |
-
border: 2px solid
|
| 2659 |
-
box-shadow:
|
| 2660 |
cursor: pointer;
|
| 2661 |
}
|
| 2662 |
.temporal-slider-input::-webkit-slider-runnable-track,
|
|
@@ -2670,12 +2672,12 @@ body.tooltips-off .maplibregl-popup { display: none !important; }
|
|
| 2670 |
.temporal-slider-start { z-index: 1; }
|
| 2671 |
|
| 2672 |
.temporal-year-label {
|
| 2673 |
-
color:
|
| 2674 |
font-family: var(--font-mono);
|
| 2675 |
font-variant-numeric: tabular-nums;
|
| 2676 |
font-size: 12px;
|
| 2677 |
font-weight: 500;
|
| 2678 |
-
min-width:
|
| 2679 |
text-align: center;
|
| 2680 |
letter-spacing: -0.01em;
|
| 2681 |
flex-shrink: 0;
|
|
|
|
| 3 |
Renamed from 10.08_styles.css on 2026-05-20.
|
| 4 |
============================================================================ */
|
| 5 |
|
| 6 |
+
@import url('https://fonts.googleapis.com/css2?family=Source+Sans+3:wght@300;400;600;700&family=Barlow+Condensed:wght@500;600;700&family=Source+Code+Pro:wght@400;500;600&display=swap');
|
| 7 |
|
| 8 |
/* -- Design tokens --------------------------------------------------------- */
|
| 9 |
:root {
|
|
|
|
| 61 |
/* Glass blur */
|
| 62 |
--blur-glass: saturate(140%) blur(14px);
|
| 63 |
|
| 64 |
+
/* Typography — Rights Lab brand: Source Sans 3 (UI/body),
|
| 65 |
+
Barlow Condensed (display/labels/wordmark), Source Code Pro (data/coords) */
|
| 66 |
+
--font-ui: 'Source Sans 3', system-ui, -apple-system, sans-serif;
|
| 67 |
+
--font-mono: 'Source Code Pro', 'SF Mono', ui-monospace, monospace;
|
| 68 |
|
| 69 |
+
/* Condensed display face for labels + wordmark; body falls back to UI font */
|
| 70 |
+
--font-label: 'Barlow Condensed', 'Source Sans 3', system-ui, sans-serif;
|
| 71 |
--font-body: var(--font-ui);
|
| 72 |
|
| 73 |
/* Motion — Spatial spring */
|
| 74 |
--ease-out: cubic-bezier(0.22, 1, 0.36, 1);
|
| 75 |
+
--ease-spring: cubic-bezier(0.16, 1, 0.3, 1); /* calmed: ease-out, no overshoot */
|
| 76 |
--t-fast: 140ms; --t-base: 220ms; --t-slow: 320ms;
|
| 77 |
|
| 78 |
/* Radii */
|
|
|
|
| 422 |
}
|
| 423 |
|
| 424 |
.stat-val {
|
| 425 |
+
font-family: var(--font-ui);
|
| 426 |
font-size: 30px;
|
| 427 |
+
font-weight: 700;
|
| 428 |
font-variant-numeric: tabular-nums;
|
| 429 |
line-height: 1;
|
| 430 |
margin-bottom: 4px;
|
|
|
|
| 629 |
}
|
| 630 |
|
| 631 |
.ind-card:hover {
|
|
|
|
| 632 |
box-shadow: var(--depth-2);
|
| 633 |
}
|
| 634 |
|
|
|
|
| 1358 |
|
| 1359 |
/* ---- Brand ---- */
|
| 1360 |
.nav-brand {
|
| 1361 |
+
font-family: var(--font-label);
|
| 1362 |
+
font-size: 22px;
|
| 1363 |
+
font-weight: 700;
|
| 1364 |
+
letter-spacing: 0.14em;
|
| 1365 |
text-transform: uppercase;
|
| 1366 |
color: var(--c-text);
|
| 1367 |
padding: 0 var(--space-2);
|
|
|
|
| 2513 |
margin-left: auto;
|
| 2514 |
margin-right: auto;
|
| 2515 |
z-index: 950;
|
| 2516 |
+
background: var(--c-glass-2);
|
| 2517 |
+
backdrop-filter: var(--blur-glass);
|
| 2518 |
+
-webkit-backdrop-filter: var(--blur-glass);
|
| 2519 |
+
border: 1px solid var(--c-glass-stroke);
|
| 2520 |
border-radius: var(--radius-md);
|
| 2521 |
box-shadow: var(--depth-3);
|
| 2522 |
padding: 6px 12px 8px;
|
|
|
|
| 2559 |
.temporal-play-btn,
|
| 2560 |
.temporal-reset-btn {
|
| 2561 |
background: transparent;
|
| 2562 |
+
color: var(--c-text-mid);
|
| 2563 |
+
border: 1px solid var(--c-glass-stroke);
|
| 2564 |
cursor: pointer;
|
| 2565 |
font-family: var(--font-ui);
|
| 2566 |
transition: background var(--t-fast) var(--ease-out),
|
|
|
|
| 2587 |
}
|
| 2588 |
.temporal-play-btn:hover,
|
| 2589 |
.temporal-reset-btn:hover {
|
| 2590 |
+
background: var(--c-glass-hover);
|
| 2591 |
+
border-color: var(--c-glass-stroke-strong);
|
| 2592 |
+
color: var(--c-text);
|
| 2593 |
}
|
| 2594 |
.temporal-play-btn:focus-visible,
|
| 2595 |
.temporal-reset-btn:focus-visible {
|
|
|
|
| 2611 |
top: 50%;
|
| 2612 |
transform: translateY(-50%);
|
| 2613 |
height: 3px;
|
| 2614 |
+
background: var(--c-glass-stroke-strong);
|
| 2615 |
border-radius: 2px;
|
| 2616 |
pointer-events: none;
|
| 2617 |
}
|
|
|
|
| 2646 |
height: 14px;
|
| 2647 |
border-radius: 50%;
|
| 2648 |
background: #ffffff;
|
| 2649 |
+
border: 2px solid var(--c-accent);
|
| 2650 |
+
box-shadow: var(--depth-1);
|
| 2651 |
cursor: pointer;
|
| 2652 |
margin-top: 0;
|
| 2653 |
}
|
|
|
|
| 2657 |
height: 14px;
|
| 2658 |
border-radius: 50%;
|
| 2659 |
background: #ffffff;
|
| 2660 |
+
border: 2px solid var(--c-accent);
|
| 2661 |
+
box-shadow: var(--depth-1);
|
| 2662 |
cursor: pointer;
|
| 2663 |
}
|
| 2664 |
.temporal-slider-input::-webkit-slider-runnable-track,
|
|
|
|
| 2672 |
.temporal-slider-start { z-index: 1; }
|
| 2673 |
|
| 2674 |
.temporal-year-label {
|
| 2675 |
+
color: var(--c-text);
|
| 2676 |
font-family: var(--font-mono);
|
| 2677 |
font-variant-numeric: tabular-nums;
|
| 2678 |
font-size: 12px;
|
| 2679 |
font-weight: 500;
|
| 2680 |
+
min-width: 150px;
|
| 2681 |
text-align: center;
|
| 2682 |
letter-spacing: -0.01em;
|
| 2683 |
flex-shrink: 0;
|