/* ════════════════════════════════════════════════════════════════════════ table.css — Day tabs, filter profiles, column toggles, hourly table, now-row and night-row decorations. ════════════════════════════════════════════════════════════════════════ */ /* ── 5. DAY TABS (today / tomorrow / etc.) ─────────────────────────── */ /* Note: each tab's background colour comes from inline styles in app.js (the confidence bands). This file only handles spacing, typography, and the active-tab underline. */ /* Wrapper that hosts the scrollable strip, edge fades, and chevrons. */ .utci-day-tabs-wrap { position: relative; margin-top: 14px; } /* Edge fade gradients — only show when there's content to scroll to. */ .utci-day-tabs-wrap::before, .utci-day-tabs-wrap::after { content: ''; position: absolute; top: 0; bottom: 2px; /* leave the underline border visible */ width: 40px; pointer-events: none; z-index: 1; opacity: 0; transition: opacity 0.2s; } .utci-day-tabs-wrap::before { left: 0; background: linear-gradient(to right, #f5edd6 0%, rgba(245,237,214,0) 100%); } .utci-day-tabs-wrap::after { right: 0; background: linear-gradient(to left, #f5edd6 0%, rgba(245,237,214,0) 100%); } .utci-day-tabs-wrap.fade-left::before { opacity: 1; } .utci-day-tabs-wrap.fade-right::after { opacity: 1; } /* Chevron buttons — sit on top of the fades. */ .utci-day-scroll { position: absolute; top: 50%; transform: translateY(-50%); width: 30px; height: 30px; border-radius: 50%; border: 1px solid #d4c0a0; background: #fffcf2; color: #6b4f2a; font-size: 20px; font-family: Fraunces, serif; line-height: 1; cursor: pointer; z-index: 2; display: flex; align-items: center; justify-content: center; padding: 0 0 2px 0; box-shadow: 0 1px 4px rgba(80,55,20,0.12); transition: opacity 0.2s, background 0.15s, transform 0.15s; } .utci-day-scroll:hover { background: #fef3dc; } .utci-day-scroll.left { left: -2px; } .utci-day-scroll.right { right: -2px; } .utci-day-scroll.hidden { opacity: 0; pointer-events: none; } .utci-day-tabs { display: flex; overflow-x: auto; scroll-behavior: smooth; scrollbar-width: none; /* Firefox */ -ms-overflow-style: none; /* old Edge */ } .utci-day-tabs::-webkit-scrollbar { display: none; /* Chrome/Safari */ } .utci-day-tab { flex: 1 0 auto; padding: 12px 24px; cursor: pointer; font-family: Manrope, sans-serif; font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.08em; background: transparent; border: 1px solid #c9b08a; color: #b09870; transition: color 0.2s, border-color 0.2s, background-color 0.2s, filter 0.15s; } .utci-day-tab + .utci-day-tab { border-left: none; } /* Each tab's background is an inline per-day weather gradient, so we darken the whole tab with a filter on hover (!important to beat the inline filter). */ .utci-day-tab:hover { filter: brightness(0.93) !important; } .utci-day-tab.active { color: #c8922a; border-bottom-color: #c8922a; } /* The "Mon 12 May" date underneath each tab name */ .utci-day-date { font-family: Fraunces, serif; font-style: italic; font-size: 13px; text-transform: none; letter-spacing: 0; display: block; margin-top: 3px; color: inherit; } /* ── 5b. FILTER PROFILES (the "Profile: Basic Urban …" bar) ───────── */ .filter-profiles { display: flex; flex-direction: column; gap: 0; margin-bottom: 0; padding: 0 14px 0; background: transparent; border: none; } .filter-profiles-label { font-family: Manrope, sans-serif; font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.08em; color: #7a5c2a; margin-bottom: 6px; white-space: nowrap; text-align: center; } /* Single scrollable row of profile cards */ .profile-scroll { display: flex; flex-wrap: nowrap; gap: 6px; align-items: center; pointer-events: none; justify-content: center; /* centre when content fits */ justify-content: safe center; /* fall back to flex-start if it overflows */ overflow-x: auto; overflow-y: auto; /* forced by browser when overflow-x is non-visible */ padding-bottom: 400px; /* extends clip boundary so the tallest dropdown (Activities) isn't cut off */ margin-bottom: -400px; /* cancel that extra space in the layout */ scrollbar-width: none; -ms-overflow-style: none; padding-right: 4px; /* breathing room at right edge */ } .profile-scroll::-webkit-scrollbar { display: none; } .profile-scroll > * { pointer-events: auto; } /* Fade-edge wrapper — hosts the ::before/::after gradient overlays */ .profile-scroll-wrap { position: relative; width: 100%; } .profile-scroll-wrap::before, .profile-scroll-wrap::after { content: ''; position: absolute; top: 0; bottom: 0; width: 52px; pointer-events: none; opacity: 0; transition: opacity 0.2s ease; z-index: 2; } .profile-scroll-wrap::before { left: 0; background: linear-gradient(to right, #f5edd6 10%, transparent 100%); } .profile-scroll-wrap::after { right: 0; background: linear-gradient(to left, #f5edd6 10%, transparent 100%); } .profile-scroll-wrap.fade-left::before { opacity: 1; } .profile-scroll-wrap.fade-right::after { opacity: 1; } /* Vertical rule separating general-use profiles from technical ones */ .profile-divider { display: inline-block; width: 1px; align-self: stretch; background: #c9b08a; margin: 0 2px; opacity: 0.6; flex-shrink: 0; } .profile-btn { width: 100px; height: 100px; flex: none; /* never shrink below 100px — the row scrolls instead */ padding: 0; position: relative; display: inline-flex; flex-direction: column; align-items: stretch; overflow: hidden; cursor: pointer; border: 1.5px solid #c9b08a; background: transparent; border-radius: 3px; transition: border-color 0.15s, box-shadow 0.15s; -webkit-user-select: none; user-select: none; } .profile-btn-scene { flex: 1; background-size: cover; background-position: center; display: flex; align-items: center; justify-content: center; font-size: 22px; line-height: 1; opacity: 0.45; transition: opacity 0.2s; } .profile-btn:hover .profile-btn-scene { opacity: 0.7; } .profile-btn.active .profile-btn-scene { opacity: 1; } .profile-btn-label { position: absolute; bottom: 0; left: 0; right: 0; height: 24px; display: flex; align-items: center; justify-content: center; font-family: Manrope, sans-serif; font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; background: rgba(30,18,8,0.52); color: #fff; padding: 0 4px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .profile-btn:hover { border-color: #c8922a; box-shadow: 0 1px 4px rgba(200,146,42,0.25); } .profile-btn.active { border-color: #c8922a; } .profile-btn.active .profile-btn-label { background: rgba(200,146,42,0.82); color: #fff; } /* ── 6. COLUMN TOGGLES (the "Columns: Hour Air RH ..." bar) ────────── */ .col-toggles { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin-bottom: 0; padding: 10px 14px; background: #fdf8ee; border: 1.5px solid #d4c0a0; border-bottom: none; } .col-toggles-display-opts { display: flex; align-items: center; gap: 12px; margin-left: auto; padding-left: 10px; flex-shrink: 0; } .col-toggles-label { font-family: Manrope, sans-serif; font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.08em; color: #7a5c2a; margin-right: 4px; white-space: nowrap; } /* The little pill buttons */ .col-toggle { padding: 5px 13px; cursor: pointer; border: 1.5px solid #c9b08a; background: #f5edd6; color: #6b4228; font-family: Manrope, sans-serif; font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em; transition: all 0.15s; -webkit-user-select: none; user-select: none; } .col-toggle:hover { border-color: #c8922a; color: #6b4f2a; background: #fef3dc; } /* The "pressed-in" active look */ .col-toggle.on { background: #c8922a; border-color: #c8922a; color: #fff; } /* ── COLUMN TOGGLE - group colour tints ───────────────────────────────── Idle: light group tint bg + group text + group border. Hover: darker tint matching th hover palette. On: solid saturated group colour, white text. On-hover: slightly darker solid. */ .col-toggle.grp-felt { background: rgba(223,243,236,0.50); color: #075c3a; border-color: rgba(7,92,58,0.35); } .col-toggle.grp-surface { background: rgba(221,234,248,0.50); color: #0b3e72; border-color: rgba(11,62,114,0.30); } .col-toggle.grp-ambient { background: rgba(236,234,227,0.50); color: #3c3a35; border-color: rgba(60,58,53,0.30); } .col-toggle.grp-precip { background: rgba(247,228,238,0.50); color: #6b1e3a; border-color: rgba(107,30,58,0.30); } .col-toggle.grp-sky { background: rgba(234,232,252,0.50); color: #352e7a; border-color: rgba(53,46,122,0.30); } .col-toggle.grp-wind { background: rgba(250,230,224,0.50); color: #6a2210; border-color: rgba(106,34,16,0.30); } .col-toggle.grp-airqual { background: rgba(229,240,216,0.50); color: #244408; border-color: rgba(36,68,8,0.30); } .col-toggle.grp-solar { background: rgba(250,234,204,0.50); color: #5a3004; border-color: rgba(90,48,4,0.30); } .col-toggle.grp-felt:hover { background: rgba(213,233,226,0.80); color: #075c3a; border-color: rgba(7,92,58,0.55); } .col-toggle.grp-surface:hover { background: rgba(211,224,238,0.80); color: #0b3e72; border-color: rgba(11,62,114,0.50); } .col-toggle.grp-ambient:hover { background: rgba(226,224,217,0.80); color: #3c3a35; border-color: rgba(60,58,53,0.50); } .col-toggle.grp-precip:hover { background: rgba(237,218,228,0.80); color: #6b1e3a; border-color: rgba(107,30,58,0.50); } .col-toggle.grp-sky:hover { background: rgba(224,222,242,0.80); color: #352e7a; border-color: rgba(53,46,122,0.50); } .col-toggle.grp-wind:hover { background: rgba(240,220,214,0.80); color: #6a2210; border-color: rgba(106,34,16,0.50); } .col-toggle.grp-airqual:hover { background: rgba(219,230,206,0.80); color: #244408; border-color: rgba(36,68,8,0.50); } .col-toggle.grp-solar:hover { background: rgba(240,224,194,0.80); color: #5a3004; border-color: rgba(90,48,4,0.50); } .col-toggle.grp-felt.on { background: #0f9e63; border-color: #0f9e63; color: #fff; } .col-toggle.grp-surface.on { background: #2672c8; border-color: #2672c8; color: #fff; } .col-toggle.grp-ambient.on { background: #7a7870; border-color: #7a7870; color: #fff; } .col-toggle.grp-precip.on { background: #b03060; border-color: #b03060; color: #fff; } .col-toggle.grp-sky.on { background: #6058c8; border-color: #6058c8; color: #fff; } .col-toggle.grp-wind.on { background: #b04030; border-color: #b04030; color: #fff; } .col-toggle.grp-airqual.on { background: #4a8018; border-color: #4a8018; color: #fff; } .col-toggle.grp-solar.on { background: #b07820; border-color: #b07820; color: #fff; } .col-toggle.grp-felt.on:hover { background: #0c7d4e; border-color: #0c7d4e; color: #fff; } .col-toggle.grp-surface.on:hover { background: #1e5aa0; border-color: #1e5aa0; color: #fff; } .col-toggle.grp-ambient.on:hover { background: #5e5c56; border-color: #5e5c56; color: #fff; } .col-toggle.grp-precip.on:hover { background: #8c264c; border-color: #8c264c; color: #fff; } .col-toggle.grp-sky.on:hover { background: #4c48a8; border-color: #4c48a8; color: #fff; } .col-toggle.grp-wind.on:hover { background: #8c3226; border-color: #8c3226; color: #fff; } .col-toggle.grp-airqual.on:hover { background: #3a6412; border-color: #3a6412; color: #fff; } .col-toggle.grp-solar.on:hover { background: #8c5e18; border-color: #8c5e18; color: #fff; } /* ── Vehicle group: select + windows-open checkbox fused together ── */ .col-toggle-group { display: inline-flex; align-items: stretch; gap: 0; /* Collapse any whitespace-node gap between the cs-wrap span and cs-vent */ font-size: 0; } .col-toggle-group > * { font-size: 12px; /* restore font size for children */ } /* Remove the right border + radius on the cs-wrap/cs-btn so it butts flush with the VentPill. The cs-wrap is the direct child, so we target its inner cs-btn via the grouped-left class on the button. */ .col-toggle-group .cs-wrap { display: inline-flex; align-items: stretch; } .col-toggle-group .grouped-left { border-right: none !important; border-radius: 0 !important; } .col-toggle-group .cs-wrap:only-child .grouped-left, .col-toggle-group .cs-wrap:last-child .grouped-left { border-right: 1.5px solid #c9b08a !important; border-radius: 0 !important; } /* ── 7. HOURLY TABLE ────────────────────────────────────────────────── */ .utci-table-wrap { /* No overflow on this wrapper — having any overflow here would make the wrapper a scroll container, which would break sticky-to-viewport on the .utci-thead-sticky strip inside. The body scroller (.utci-tbody-scroll) owns the horizontal scrollbar. */ border: 1.5px solid #c9b08a; background: #fffcf2; position: relative; /* needed for ::before / ::after pseudo-element indicators */ } /* ── SCROLL INDICATORS ────────────────────────────────────────────────── Fade + chevron overlays on the left/right edges of the table wrap. They appear only when there is content to scroll in that direction, driven by the scroll-fade-left / scroll-fade-right classes toggled by JS. */ .utci-table-wrap::before, .utci-table-wrap::after { content: ''; position: absolute; top: 0; bottom: 0; width: 48px; pointer-events: none; opacity: 0; transition: opacity 0.2s ease; z-index: 6; /* above sticky header (z-index 5) */ } /* Left fade — warm cream fading to transparent rightward */ .utci-table-wrap::before { left: 0; background: linear-gradient(to right, rgba(240,228,196,0.92) 0%, transparent 100%); } /* Right fade — warm cream fading to transparent leftward */ .utci-table-wrap::after { right: 0; background: linear-gradient(to left, rgba(240,228,196,0.92) 0%, transparent 100%); } .utci-table-wrap.scroll-fade-left::before { opacity: 1; } .utci-table-wrap.scroll-fade-right::after { opacity: 1; } /* Chevron arrows — sit on top of the fade, centred vertically */ .utci-table-wrap .utci-scroll-chevron { position: absolute; top: 50%; transform: translateY(-50%); z-index: 7; pointer-events: none; color: #8a6a3a; font-size: 18px; line-height: 1; opacity: 0; transition: opacity 0.2s ease; user-select: none; } .utci-table-wrap .utci-scroll-chevron.left { left: 6px; } .utci-table-wrap .utci-scroll-chevron.right { right: 6px; } .utci-table-wrap.scroll-fade-left .utci-scroll-chevron.left { opacity: 1; } .utci-table-wrap.scroll-fade-right .utci-scroll-chevron.right { opacity: 1; } /* Grab cursor on the body scroller to hint drag-to-scroll */ .utci-tbody-scroll { cursor: grab; user-select: none; /* prevent text highlighting during drag */ -webkit-user-select: none; } .utci-tbody-scroll:active { cursor: grabbing; } /* ── STICKY HEADER STRIP ──────────────────────────────────────────────── Sits above the body and locks to the top of the viewport while the page scrolls. Has overflow:hidden so the inner .utci-thead-track can be translateX'd by JS to follow the body's scrollLeft. */ .utci-thead-sticky { position: sticky; top: 0; z-index: 5; overflow: hidden; background: #f0e4c4; border-bottom: 2px solid #c9b08a; box-shadow: 0 2px 5px rgba(74, 52, 32, 0.10); } /* On mobile the nav bar is fixed at 72px - sticky header must clear it */ @media (max-width: 640px) { .utci-thead-sticky { top: 72px; } } /* The shifted track inside the sticky header — JS sets transform:translate3d to keep its columns aligned with the body scroller's scrollLeft. */ .utci-thead-track { will-change: transform; } /* Body scroller — owns the horizontal scrollbar for the whole table. */ .utci-tbody-scroll { overflow-x: auto; overflow-y: visible; } .utci-table { width: 100%; border-collapse: collapse; font-size: 14px; /* Fixed layout so the explicit per-cell widths set by the JS width-sync (see useLayoutEffect in app.js) are actually enforced. Without this the browser's auto layout treats those widths as suggestions and redistributes space, which makes the header and body columns drift apart the further right you scroll. */ table-layout: fixed; } /* Column headings (Hour, Air, RH, Wind...). NOTE: stickiness is handled by the .utci-thead-sticky wrapper, not the itself — see the new wrapper rules higher up. */ .utci-table th { background: #f0e4c4; color: #6b4f2a; font-family: Manrope, sans-serif; font-size: 12px; text-align: center; text-transform: uppercase; letter-spacing: 0.07em; font-weight: 700; padding: 14px 12px; white-space: nowrap; } @media (max-width: 800px) { .utci-table th { font-size: 10px; letter-spacing: 0.08em; } } /* The Hour column aligns left, the rest align right */ .utci-table th:first-child, .utci-table td:first-child { text-align: left; } /* The "°C" / "m/s" etc. unit underneath each heading */ .utci-table th .col-unit { display: block; color: #c8922a; font-size: 10px; margin-top: 2px; } /* Environment modifier badge — shown in SunSoak th when non-default env active */ .col-env-badge { display: block; font-size: 9px; font-weight: 700; font-family: Manrope, sans-serif; letter-spacing: 0.04em; color: #a06828; opacity: 0.85; margin-top: 2px; white-space: nowrap; } /* col-unit header spans always visible - units toggle only affects body cells */ @media (max-width: 800px) { .utci-table th .col-unit { font-size: 9px; } } .utci-table tbody tr { border-bottom: 1px solid #ffffff; transition: background 0.1s; } .utci-table tbody tr:hover { background: #fef8ea; } .utci-table td { padding: 10px 12px; text-align: center; font-family: JetBrains Mono, monospace; font-variant-numeric: tabular-nums; /* stops digits jiggling between rows */ white-space: nowrap; color: #4a3420; /* Baseline minimum column width — the JS width-sync uses max(60, head, body) so very-narrow data columns ("Air 5.0") still feel comfortable to read instead of being squashed. */ min-width: 60px; } /* Subtle vertical column dividers — same pale cream as the row dividers so the table reads as a soft grid, not a hard one. The last column has no divider so it doesn't double-up with the container border. */ .utci-table th:not(:last-child), .utci-table td:not(:last-child) { border-right: 1px solid #ffffff; } /* The Dir column is centered on both desktop and mobile so the compass vane sits with even padding either side — especially important on mobile where the compass label is hidden and there's no text to balance the right-aligned content. */ .utci-table th.utci-dir-cell, .utci-table td.utci-dir-cell { text-align: center; } /* "Tight" header — for columns whose body content is narrower than the default tracked-out header would suggest (Air, Pcpt). Reducing the letter-spacing shrinks the heading's natural width so it stops driving the column wider than the body needs. Right-aligned values */ .utci-table th.utci-tight-head { letter-spacing: 0.04em; } /* ── CLICKABLE COLUMN HEADERS ─────────────────────────────────────────── .col-info-th makes every show a pointer cursor and a subtle hover tint to signal it can be clicked for a description popup. */ .utci-table th.col-info-th { cursor: pointer; transition: background 0.15s; } .utci-table th.col-info-th:hover { background: #e8d8a8; } /* ── COLUMN DESCRIPTION POPUP ─────────────────────────────────────────── Fixed-position card that appears below a clicked column header. JS sets left/top via inline style (centred on the clicked th). */ .col-info-popup { position: fixed; /* set by JS — stays in viewport regardless of scroll */ z-index: 200; width: 260px; max-height: 260px; display: flex; flex-direction: column; background: #fffcf2; border: 1.5px solid #c9b08a; border-radius: 6px; box-shadow: 0 4px 16px rgba(74,52,32,0.18); padding: 14px 16px 16px; pointer-events: all; } /* Arrow points DOWN toward the column header (default — popup is above the th) */ .col-info-popup::after { content: ''; position: absolute; bottom: -7px; left: var(--arrow-left, 50%); width: 12px; height: 12px; background: #fffcf2; border-right: 1.5px solid #c9b08a; border-bottom: 1.5px solid #c9b08a; transform: translateX(-50%) rotate(45deg); } /* Arrow points UP toward the column header (popup is below the th) */ .col-info-popup.col-info-popup--below::after { bottom: auto; top: -7px; border-right: none; border-bottom: none; border-left: 1.5px solid #c9b08a; border-top: 1.5px solid #c9b08a; transform: translateX(-50%) rotate(45deg); } .col-info-title { display: block; font-family: Manrope, sans-serif; font-size: 12px; font-weight: 700; color: #4a3420; margin-bottom: 6px; text-transform: none; letter-spacing: 0; } .col-info-desc { font-family: Manrope, sans-serif; font-size: 12px; color: #6b4f2a; line-height: 1.5; margin: 0; overflow-y: auto; /* scrolls when text exceeds max-height cap */ flex: 1 1 auto; } .col-info-close { position: absolute; top: 6px; right: 8px; background: none; border: none; font-size: 16px; color: #a08060; cursor: pointer; line-height: 1; padding: 0 2px; } .col-info-close:hover { color: #4a3420; } /* ── POPUP OPEN/CLOSE ANIMATION ───────────────────────────────────────── The popup mounts/unmounts instantly in JS, so we animate it via a scale + fade keyframe anchored to the arrow tip (transform-origin). Above-the-target: origin is bottom-center. Below: top-center. */ @keyframes popup-open { from { opacity: 0; transform: translateX(-50%) translateY(-100%) scaleY(0.6); } to { opacity: 1; transform: translateX(-50%) translateY(-100%) scaleY(1); } } @keyframes popup-open-below { from { opacity: 0; transform: translateX(-50%) scaleY(0.6); } to { opacity: 1; transform: translateX(-50%) scaleY(1); } } .col-info-popup:not(.col-info-popup--below) { transform-origin: bottom center; animation: popup-open 0.22s cubic-bezier(0.34, 1.4, 0.64, 1) both; } .col-info-popup.col-info-popup--below { transform-origin: top center; animation: popup-open-below 0.22s cubic-bezier(0.34, 1.4, 0.64, 1) both; } /* ── EVENT TAG POPUP — SLIDESHOW ──────────────────────────────────────── The stage holds the current slide. On transition, evTransition is set to 'exiting' (fade out) then 'entering' (fade in) via the hook. */ @keyframes ev-fade-in { from { opacity: 0; } to { opacity: 1; } } @keyframes ev-fade-out { from { opacity: 1; } to { opacity: 0; } } .ev-popup-stage { transition: opacity 0.38s ease; } .ev-popup-entering { animation: ev-fade-in 0.38s ease both; } .ev-popup-exiting { animation: ev-fade-out 0.38s ease both; } /* Slideshow navigation dots */ .ev-popup-dots { display: flex; gap: 5px; margin-top: 8px; justify-content: center; align-items: center; } .ev-popup-dot { width: 6px; height: 6px; border-radius: 50%; background: #c9b08a; opacity: 0.4; cursor: pointer; transition: opacity 0.2s, transform 0.2s; flex-shrink: 0; } .ev-popup-dot.active { opacity: 1; transform: scale(1.35); background: #7a5530; } .ev-popup-dot:hover { opacity: 0.75; } /* ── 8. NOW-ROW & NIGHT-ROW DECORATIONS ─────────────────────────────── */ /* "Currently this hour" — the highlighted row. The row gets a cream-yellow background and darker text. No left stripe or pip — the colour shift alone signals "this is now". */ .utci-table tbody tr.is-now { background: #fff8e4 !important; } .utci-table tbody tr.is-now td { color: #1e1208; /* Brass bracket framing the current-hour row top and bottom — clean, definitive, no left stripe needed. */ border-top: 2px solid #c8922a; border-bottom: 2px solid #c8922a; } /* Night-time hours get a slightly muted text colour */ .utci-table tbody tr.is-night td { color: #7a5c30; } /* The time cell — uses the display serif instead of monospace */ .utci-time { font-family: Fraunces, serif !important; font-weight: 500; font-size: 16px; color: #1e1208 !important; } .utci-time svg { margin: -6px 0; flex-shrink: 0; } @media (max-width: 800px) { .utci-time { font-size: 15px; } .utci-cell-hero { font-size: 15px !important; padding: 5px 12px; min-width: 60px; } } /* The coloured pill inside UTCI / UTCI+P cells. The pill's BACKGROUND comes from inline styles in app.js (the utciCategory() function decides which thermal-stress colour to apply). This rule just handles the pill shape. */ .utci-cell { display: inline-block; padding: 4px 12px; border-radius: 3px; font-weight: 600; min-width: 60px; text-align: center; font-size: 14px; } /* Hero variant used for the UTCI+P column — the headline number. Bigger, bolder, more breathing room so the eye lands here first. */ .utci-cell-hero { padding: 6px 4px; font-size: 17px; font-weight: 700; min-width: 63px; letter-spacing: 0.01em; box-shadow: 0 1px 0 rgba(0,0,0,0.15) inset, 0 0 0 1px rgba(255,255,255,0.08) inset; } .utci-band-label { font-family: Manrope, sans-serif; font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em; } /* Faint vertical divider before each new column group in the forecast table. */ .utci-table .col-group-start { border-left: 2px solid rgba(74, 50, 24, 0.18); } /* ── COLUMN GROUP COLOURS — header cell tints per group ───────────────── Each grp-* class gives the th a distinct background + text colour. The hover state darkens slightly. The col-unit underneath inherits a matching accent colour. */ .utci-table th.grp-felt { background: rgba(223,243,236,0.50); color: #075c3a; } .utci-table th.grp-surface { background: rgba(221,234,248,0.50); color: #0b3e72; } .utci-table th.grp-ambient { background: rgba(236,234,227,0.50); color: #3c3a35; } .utci-table th.grp-precip { background: rgba(247,228,238,0.50); color: #6b1e3a; } .utci-table th.grp-sky { background: rgba(234,232,252,0.50); color: #352e7a; } .utci-table th.grp-wind { background: rgba(250,230,224,0.50); color: #6a2210; } .utci-table th.grp-airqual { background: rgba(229,240,216,0.50); color: #244408; } .utci-table th.grp-solar { background: rgba(250,234,204,0.50); color: #5a3004; } .utci-table th.grp-felt.col-info-th:hover { background: rgba(213,233,226,0.80); } .utci-table th.grp-surface.col-info-th:hover { background: rgba(211,224,238,0.80); } .utci-table th.grp-ambient.col-info-th:hover { background: rgba(226,224,217,0.80); } .utci-table th.grp-precip.col-info-th:hover { background: rgba(237,218,228,0.80); } .utci-table th.grp-sky.col-info-th:hover { background: rgba(224,222,242,0.80); } .utci-table th.grp-wind.col-info-th:hover { background: rgba(240,220,214,0.80); } .utci-table th.grp-airqual.col-info-th:hover { background: rgba(219,230,206,0.80); } .utci-table th.grp-solar.col-info-th:hover { background: rgba(240,224,194,0.80); } .utci-table th.grp-felt .col-unit { color: #0f9e63; } .utci-table th.grp-surface .col-unit { color: #2672c8; } .utci-table th.grp-ambient .col-unit { color: #7a7870; } .utci-table th.grp-precip .col-unit { color: #b03060; } .utci-table th.grp-sky .col-unit { color: #6058c8; } .utci-table th.grp-wind .col-unit { color: #b04030; } .utci-table th.grp-airqual .col-unit { color: #4a8018; } .utci-table th.grp-solar .col-unit { color: #b07820; } /* ── GROUP LABEL ROW — spans above the column header row ──────────────── A second tr in the thead. Each cell spans all visible columns in its group. The Hour column gets a blank matching-background cell. */ .grp-label-row th { font-family: Manrope, sans-serif; font-size: 9px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.10em; padding: 4px 8px 2px; text-align: center; white-space: nowrap; border-bottom: 1px solid rgba(0,0,0,0.06); } .utci-table .grp-label-row th.grp-felt { background: rgba(223,243,236,0.50); border-left: 2px solid rgba(74,50,24,0.18); border-bottom: 1px solid rgba(74,50,24,0.18);} .utci-table .grp-label-row th.grp-surface { background: rgba(221,234,248,0.50); border-left: 2px solid rgba(74,50,24,0.18); border-bottom: 1px solid rgba(74,50,24,0.18);} .utci-table .grp-label-row th.grp-ambient { background: rgba(236,234,227,0.50); border-left: 2px solid rgba(74,50,24,0.18); border-bottom: 1px solid rgba(74,50,24,0.18);} .utci-table .grp-label-row th.grp-precip { background: rgba(247,228,238,0.50); border-left: 2px solid rgba(74,50,24,0.18); border-bottom: 1px solid rgba(74,50,24,0.18);} .utci-table .grp-label-row th.grp-sky { background: rgba(234,232,252,0.50); border-left: 2px solid rgba(74,50,24,0.18); border-bottom: 1px solid rgba(74,50,24,0.18);} .utci-table .grp-label-row th.grp-wind { background: rgba(250,230,224,0.50); border-left: 2px solid rgba(74,50,24,0.18); border-bottom: 1px solid rgba(74,50,24,0.18);} .utci-table .grp-label-row th.grp-airqual { background: rgba(229,240,216,0.50); border-left: 2px solid rgba(74,50,24,0.18); border-bottom: 1px solid rgba(74,50,24,0.18);} .utci-table .grp-label-row th.grp-solar { background: rgba(250,234,204,0.50); border-left: 2px solid rgba(74,50,24,0.18); border-bottom: 1px solid rgba(74,50,24,0.18);} /* ── POPUP — mobile centre-alignment ───────────────────────────────── */ @media (max-width: 640px) { .col-info-title, .col-info-desc { text-align: center; } } /* ── FILTER PROFILES + COLUMN TOGGLES — mobile fixes ───────────────── */ @media (max-width: 640px) { /* ── Profile bar — single scroll row on all screen sizes ─────────── No wrapping needed; scroll strip handles layout. Dividers stay. */ .filter-profiles { padding: 4px 10px 0; } /* Slightly smaller cards on mobile */ .profile-btn { width: 80px; height: 80px; flex: none; } .profile-btn-scene { font-size: 18px; } .profile-btn-label { height: 20px; font-size: 9px; } /* ── Column toggles bar ───────────────────────────────────────────── Same approach — label full row, toggles at ~31% each. */ .col-toggles { flex-wrap: wrap; gap: 6px; padding: 10px 10px; align-items: stretch; } .col-toggles-label { flex: 0 0 100%; margin-right: 0; margin-bottom: 0; } .col-toggle { flex: 0 0 calc((100% - 12px) / 3); min-width: 0; box-sizing: border-box; text-align: center; padding: 7px 2px; font-size: 11px; letter-spacing: 0.03em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } /* Pollen CustomSelect in col-toggles — match toggle width */ .col-toggles .cs-wrap { flex: 0 0 calc((100% - 12px) / 3); min-width: 0; } .col-toggles .cs-btn { width: 100%; min-width: 0; padding: 7px 6px; font-size: 11px; letter-spacing: 0.03em; justify-content: center; overflow: hidden; } /* Fused group: 1 slot by default, 2 slots when VentPill is active */ .col-toggle-group { flex: 0 0 calc((100% - 12px) / 3); min-width: 0; display: inline-flex; align-items: stretch; } .col-toggle-group--expanded { flex: 0 0 calc((100% - 12px) / 3 * 2 + 6px); } .col-toggle-group .cs-wrap { flex: 1 1 0; min-width: 0; width: 100%; } .col-toggle-group .cs-btn { width: 100%; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 11px; padding: 7px 6px; justify-content: center; } } /* ── MOBILE TABLE DENSITY — squeeze all basic profile columns in ──────── Target: 7 cols (hour air wind cloud utciP precip vis) on a 390px screen. Worst-case minimum width at these values: 366px - fits iPhone SE (375px). Levers: tighter cell padding, smaller min-width, reduced font sizes. The existing 800px and 640px blocks handle tablets and phablets above. DENSITY-BREAKPOINT - change 480px here to adjust where dense layout kicks in. -------------------------------------------------------------------- */ /* -- MOBILE TABLE DENSITY - squeeze all basic profile columns in -------- Target: 7 cols (hour air wind cloud utciP precip vis) on a 390px screen. Worst-case minimum width: 366px - fits iPhone SE (375px) with room to spare. DENSITY-BREAKPOINT - change 480px to adjust where dense layout kicks in. -------------------------------------------------------------------- */ @media (max-width: 480px) { /* -- Table header cells ----------------------------------------------- Reduce padding so headers do not drive columns wider than data needs. */ .utci-table th { font-size: 9px; padding: 10px 4px; letter-spacing: 0.04em; } .utci-table th .col-unit { font-size: 8px; } /* -- Table body cells ------------------------------------------------- Drop side padding 12px to 4px, shrink min-width 60px to 44px. JetBrains Mono at 11px reads cleanly on retina screens. */ .utci-table td { padding: 10px 4px; font-size: 11px; min-width: 44px; } /* -- Time (Hour) column ----------------------------------------------- Drop Fraunces from 16px to 13px and tighten the hour cell min-width. */ .utci-time { font-size: 13px; } .utci-table td:first-child { min-width: 42px; } /* -- SkyScope moon-sun icon in the hour cell --------------------------- JS renders at size=38. Clamp to 25px via CSS to stop it ballooning the hour column width and driving up row height. */ .utci-time svg { width: 34px !important; height: 34px !important; margin: -5px 0; flex-shrink: 0; } /* -- Cloud, wind-vane and precip icons in body cells ------------------- Clamp the 28px SVGs down to 20px on mobile to recover column width without touching the JS size prop. */ .utci-table td svg { width: 20px !important; height: 20px !important; flex-shrink: 0; } /* Override for SkyScope - keep it larger than other cell icons */ .utci-table td.utci-time svg { width: 26px !important; height: 26px !important; } /* -- Hero UTCI+P pill ------------------------------------------------- Shrink min-width and font - still the visual anchor but no longer forcing the column to be the widest. */ .utci-cell-hero { font-size: 14px; min-width: 50px; padding: 5px 2px; } /* -- Vis column ----------------------------------------------------------- Short values (8-99km) need less room than the default 44px min-width. */ .utci-vis-cell { min-width: 30px; } /* -- Standard UTCI pill (non-hero) ------------------------------------*/ .utci-cell { font-size: 12px; min-width: 44px; padding: 3px 5px; } /* -- Band label inside pills ------------------------------------------ Tighten letter-spacing to save a little width. */ .utci-band-label { font-size: 9px; letter-spacing: 0.03em; } }