@import "tailwindcss"; @custom-variant dark (&:where(.dark, .dark *)); /* ------------------------------------------------------------------------------------------ DataCenterIndex — design tokens Near-monochrome: ink + warm graphite + paper. ONE accent (signal amber) for pipeline/emphasis. Semantic status scale is fixed and shared with the map (see lib/labels.ts). ------------------------------------------------------------------------------------------ */ @theme { --font-sans: var(--font-inter), ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; --font-mono: var(--font-jetbrains), ui-monospace, "JetBrains Mono", "SF Mono", Menlo, Consolas, monospace; --color-paper: var(--paper); --color-surface: var(--surface); --color-surface-2: var(--surface-2); --color-surface-3: var(--surface-3); --color-ink: var(--ink); --color-ink-2: var(--ink-2); --color-ink-3: var(--ink-3); --color-ink-4: var(--ink-4); --color-hair: var(--hair); --color-hair-2: var(--hair-2); --color-accent: var(--accent); --color-accent-ink: var(--accent-ink); --color-accent-soft: var(--accent-soft); --color-st-operational: var(--st-operational); --color-st-construction: var(--st-construction); --color-st-planned: var(--st-planned); --color-st-permitting: var(--st-permitting); --color-st-delayed: var(--st-delayed); --color-st-closed: var(--st-closed); --color-st-rumored: var(--st-rumored); --color-st-unknown: var(--st-unknown); --color-ok: var(--ok); --color-warn: var(--warn); --color-danger: var(--danger); --color-info: var(--info); --radius-xs: 2px; --radius-sm: 3px; --radius-md: 4px; --animate-fade-in: fade-in 0.18s ease-out both; --animate-sheet-up: sheet-up 0.22s cubic-bezier(0.2, 0.8, 0.2, 1) both; --animate-sheet-side: sheet-side 0.22s cubic-bezier(0.2, 0.8, 0.2, 1) both; --animate-row-in: row-in 0.5s ease-out both; --animate-pulse-soft: pulse-soft 1.8s ease-in-out infinite; @keyframes fade-in { from { opacity: 0; transform: translateY(-2px); } to { opacity: 1; transform: translateY(0); } } @keyframes sheet-up { from { opacity: 0; transform: translateY(24px); } to { opacity: 1; transform: translateY(0); } } @keyframes sheet-side { from { opacity: 0; transform: translateX(16px); } to { opacity: 1; transform: translateX(0); } } @keyframes row-in { from { background-color: color-mix(in oklab, var(--accent) 16%, transparent); } to { background-color: transparent; } } @keyframes pulse-soft { 0%, 100% { opacity: 1; } 50% { opacity: 0.45; } } } :root { color-scheme: light; --paper: #f5f4f1; --surface: #ffffff; --surface-2: #efeeea; --surface-3: #e6e4df; --ink: #0b0f14; --ink-2: #3b4148; --ink-3: #666c73; /* 5.1:1 on paper (was #6b7178 = 4.49:1) */ --ink-4: #9a9fa5; /* hint level only (placeholders, kbd, "/total") — below 4.5:1 by design */ --hair: #e3e1dc; --hair-2: #c9c6bf; --accent: #c8541a; --accent-ink: #a3420f; --accent-soft: #f7e6dc; /* status scale — validated (dataviz six checks): lightness-separated blue/violet, labels always accompany colour */ --st-operational: #1f6b3a; --st-construction: #b87a0a; --st-planned: #5f8fc4; --st-permitting: #5b3f8f; --st-delayed: #a94a2a; --st-closed: #858a90; --st-rumored: #8f95a0; --st-unknown: #b3b6ba; --ok: #1f6b3a; --warn: #b87a0a; --danger: #a94a2a; --info: #3f5b7a; --map-water: #e9ecef; } .dark { color-scheme: dark; --paper: #0b0f14; --surface: #10161d; --surface-2: #161d25; --surface-3: #1d252e; --ink: #eceae5; --ink-2: #b9b6ae; --ink-3: #8f959c; /* 6.2:1 on paper (was #858a90 = 5.4:1) */ --ink-4: #7a8189; /* 4.8:1 on paper, 4.6:1 on surface (was #5b6168 = 3.1:1) */ --hair: #1f272f; --hair-2: #2f3941; --accent: #e8763a; --accent-ink: #f08b52; --accent-soft: #2a1a10; --st-operational: #3fa465; --st-construction: #d4962a; --st-planned: #7fb0e6; --st-permitting: #8a6bc9; --st-delayed: #d9704a; --st-closed: #6f757c; --st-rumored: #7b828c; --st-unknown: #4d545b; --ok: #3fa465; --warn: #d4962a; --danger: #d9704a; --info: #7f9bb8; } @layer base { html { -webkit-text-size-adjust: 100%; text-rendering: optimizeLegibility; scroll-padding-top: 4rem; } body { background: var(--paper); color: var(--ink); font-family: var(--font-sans); font-size: 14px; line-height: 1.45; font-feature-settings: "cv11", "ss01"; overflow-x: hidden; } ::selection { background: color-mix(in oklab, var(--accent) 28%, transparent); } :focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 2px; } button, [role="button"] { cursor: pointer; } a { text-underline-offset: 3px; } h1, h2, h3, h4 { letter-spacing: -0.01em; } table { border-collapse: separate; border-spacing: 0; } input::-webkit-search-cancel-button { -webkit-appearance: none; } @media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; scroll-behavior: auto !important; } } } @utility tnum { font-variant-numeric: tabular-nums lining-nums; } @utility figure { font-family: var(--font-mono); font-variant-numeric: tabular-nums lining-nums; letter-spacing: -0.02em; } @utility no-scrollbar { scrollbar-width: none; &::-webkit-scrollbar { display: none; } } @utility hair-b { border-bottom: 1px solid var(--hair); } @utility safe-b { padding-bottom: env(safe-area-inset-bottom); } @utility label-caps { font-size: 10.5px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--ink-3); font-weight: 500; } /* Graticule texture for the home hero — thin lines, low contrast, never noisy. */ .graticule { background-image: linear-gradient(to right, color-mix(in oklab, var(--ink) 6%, transparent) 1px, transparent 1px), linear-gradient(to bottom, color-mix(in oklab, var(--ink) 6%, transparent) 1px, transparent 1px); background-size: 48px 48px; mask-image: linear-gradient(to bottom, rgba(0, 0, 0, 0.9), transparent 90%); } /* Responsive table → compact two-line rows under 640 px (each cell carries data-label). Line 1: [data-primary] cell (name + meta) with the [data-lead] figure on the right. Line 2: the remaining cells wrap as "LABEL value" pairs. Cells hidden via `hidden sm:table-cell` stay hidden. */ .dci-table { width: 100%; } .dci-table th { position: sticky; top: 0; z-index: 1; background: var(--surface); } @media (max-width: 639.98px) { .dci-table.responsive thead { display: none; } .dci-table.responsive, .dci-table.responsive tbody { display: block; width: 100%; } .dci-table.responsive tr { display: flex; flex-wrap: wrap; align-items: baseline; column-gap: 12px; row-gap: 3px; width: 100%; border-bottom: 1px solid var(--hair); padding: 11px 0; min-height: 40px; } .dci-table.responsive td { order: 2; display: inline-flex; flex: 0 0 auto; align-items: baseline; gap: 5px; min-width: 0; max-width: 100%; padding: 0 !important; border: 0 !important; font-size: 12px; line-height: 1.35; text-align: left; } .dci-table.responsive td.hidden { display: none; } .dci-table.responsive td[data-label]::before { content: attr(data-label); color: var(--ink-3); font-family: var(--font-inter), ui-sans-serif, system-ui, sans-serif; font-size: 10px; letter-spacing: 0.06em; text-transform: uppercase; flex: 0 0 auto; } .dci-table.responsive td[data-primary] { order: 0; display: block; flex: 1 1 55%; font-size: 13px; line-height: 1.35; font-weight: 500; } .dci-table.responsive tr:not(:has(td[data-lead])) td[data-primary] { flex-basis: 100%; } .dci-table.responsive td[data-primary]::before { display: none; } .dci-table.responsive td[data-lead] { order: 1; flex: 1 0 auto; justify-content: flex-end; font-size: 13px; color: var(--ink); } .dci-table.responsive td[data-lead]::before { color: var(--ink-4); } /* Whole row = tap target for the primary RowLink (≥ 40 px); other links in the row stay clickable above it. */ .dci-table.responsive tr { position: relative; } .dci-table.responsive td a { position: relative; z-index: 1; } .dci-table.responsive td[data-primary] a.dci-rowlink { position: static; } .dci-table.responsive td[data-primary] a.dci-rowlink::after { content: ""; position: absolute; inset: 0; z-index: 0; } /* Collapsed long lists: only the first 10 rows until "Show all N" (see ). */ .dci-collapse[data-collapsed] tbody > tr:nth-child(n + 11), .dci-collapse[data-collapsed] > :is(ol, ul) > li:nth-child(n + 11) { display: none; } } /* Dual range slider — two overlaid native inputs, only the thumbs are visible. */ .dual-range { pointer-events: none; } .dual-range::-webkit-slider-runnable-track { background: transparent; height: 2px; } .dual-range::-moz-range-track { background: transparent; height: 2px; } .dual-range::-webkit-slider-thumb { pointer-events: auto; -webkit-appearance: none; appearance: none; width: 22px; height: 22px; margin-top: -10px; border-radius: 50%; background: var(--surface); border: 2px solid var(--ink); cursor: grab; } .dual-range::-moz-range-thumb { pointer-events: auto; width: 18px; height: 18px; border-radius: 50%; background: var(--surface); border: 2px solid var(--ink); cursor: grab; } .dual-range:focus-visible::-webkit-slider-thumb { outline: 2px solid var(--accent); outline-offset: 2px; } /* MapLibre overrides — keep controls on brand and small. */ .maplibregl-ctrl-group { border-radius: 3px !important; box-shadow: none !important; border: 1px solid var(--hair-2); background: var(--surface) !important; } .maplibregl-ctrl-group button { width: 32px !important; height: 32px !important; } @media (max-width: 767.98px) { .maplibregl-ctrl-group button { width: 40px !important; height: 40px !important; } .maplibregl-ctrl-group button .maplibregl-ctrl-icon { background-size: 20px; } } .dark .maplibregl-ctrl-group button .maplibregl-ctrl-icon { filter: invert(1); } .maplibregl-ctrl-attrib { font-size: 10px !important; background: color-mix(in oklab, var(--surface) 85%, transparent) !important; color: var(--ink-3) !important; } .maplibregl-ctrl-attrib a { color: var(--ink-2) !important; } .maplibregl-canvas:focus { outline: none; } /* Keep MapLibre controls above the fixed mobile bottom nav. */ @media (max-width: 767.98px) { body:not([data-hide-mobile-nav]) .maplibregl-ctrl-bottom-right, body:not([data-hide-mobile-nav]) .maplibregl-ctrl-bottom-left { bottom: calc(3.5rem + env(safe-area-inset-bottom)); } }