2113 lines
61 KiB
CSS
2113 lines
61 KiB
CSS
/* ════════════════════════════════════════════════════════════════════════
|
|
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: 12px;
|
|
margin-bottom: 15px;
|
|
border: 1px solid #c9b08a;
|
|
}
|
|
|
|
/* 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 0;
|
|
min-width: 90px;
|
|
padding: 10px 20px;
|
|
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;
|
|
overflow-wrap: break-word;
|
|
transition: color 0.2s, border-color 0.2s, background-color 0.2s, filter 0.15s;
|
|
}
|
|
|
|
.utci-day-tab + .utci-day-tab {
|
|
border-left: none;
|
|
}
|
|
|
|
.utci-day-tab:hover:not(.active):not(.locked) {
|
|
filter: brightness(1.05) !important;
|
|
}
|
|
|
|
.utci-day-tab.active {
|
|
color: #c8922a;
|
|
outline: 1px solid #000;
|
|
outline-offset: -1px;
|
|
z-index: 1;
|
|
}
|
|
|
|
/* Danger-band days breathe a slow dark-red inner glow */
|
|
.utci-day-tab.danger {
|
|
animation: dayTabDangerPulse 2.4s ease-in-out infinite;
|
|
}
|
|
|
|
@keyframes dayTabDangerPulse {
|
|
0%, 100% { box-shadow: inset 0 0 0 0 rgba(136, 0, 0, 0); }
|
|
50% { box-shadow: inset 0 0 34px 8px rgba(136, 0, 0, 0.6); }
|
|
}
|
|
|
|
@media (prefers-reduced-motion: reduce) {
|
|
.utci-day-tab.danger { animation: none; }
|
|
}
|
|
|
|
/* 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: 0px;
|
|
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;
|
|
}
|
|
|
|
/* Config strip - value-only pickers for the felt-model settings (vehicle
|
|
type, building type, fur colour, skin type, pollen type, SunSoak env).
|
|
Sits directly under the profile picker, always visible (not tucked away
|
|
in the collapsible Columns accordion) so these settings stay as
|
|
prominent as the profile choice that they belong to. */
|
|
.col-toggles-config {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
justify-content: center;
|
|
gap: 12px;
|
|
align-items: center;
|
|
margin-top: 0;
|
|
padding: 10px 14px;
|
|
background: #fffcf2;
|
|
border: 1.5px solid #c9b08a;
|
|
border-top: none;
|
|
}
|
|
|
|
.col-toggles-config-item {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
padding: 6px 10px;
|
|
background: rgba(255,255,255,0.6);
|
|
border: 1px solid #e6d7b8;
|
|
border-radius: 5px;
|
|
}
|
|
|
|
.config-item-label {
|
|
font-family: Manrope, sans-serif;
|
|
font-size: 11px;
|
|
font-weight: 700;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.05em;
|
|
color: #9a7a4a;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
/* Main thermal selection - the config item whose value also drives the
|
|
day-tab hi/lo readout. Always sorted first (see DayTabs.js) and marked
|
|
with a badge so it reads as distinct from the other config pickers. */
|
|
.col-toggles-config-item--main {
|
|
padding: 8px 8px;
|
|
border: 1.5px solid #c8922a;
|
|
border-radius: 4px;
|
|
background: rgba(200,146,42,0.08);
|
|
}
|
|
|
|
.config-item-main-badge {
|
|
display: block;
|
|
flex: 0 0 100%;
|
|
text-align: center;
|
|
font-family: Manrope, sans-serif;
|
|
font-size: 13px;
|
|
font-weight: 800;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.04em;
|
|
color: #9a6a1a;
|
|
padding: 0;
|
|
white-space: nowrap;
|
|
cursor: help;
|
|
}
|
|
|
|
/* 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: 6px;
|
|
margin-bottom: 0;
|
|
scrollbar-width: none;
|
|
-ms-overflow-style: none;
|
|
padding-left: 4px; /* breathing room at left edge */
|
|
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%;
|
|
padding-top:8px;
|
|
padding-bottom:1px;
|
|
background-color: #fffcf2;
|
|
border-top: 1.5px solid #c9b08a;
|
|
border-left: 1.5px solid #c9b08a;
|
|
border-right: 1.5px solid #c9b08a;
|
|
border-bottom: 1.5px solid #c9b08a;
|
|
}
|
|
|
|
.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; }
|
|
|
|
.profile-scroll-chevron {
|
|
position: absolute;
|
|
top: 50%;
|
|
transform: translateY(-50%);
|
|
z-index: 3;
|
|
pointer-events: none;
|
|
color: #8a6a3a;
|
|
font-size: 18px;
|
|
line-height: 1;
|
|
opacity: 0;
|
|
transition: opacity 0.2s ease;
|
|
user-select: none;
|
|
}
|
|
.profile-scroll-chevron.left { left: 4px; }
|
|
.profile-scroll-chevron.right { right: 4px; }
|
|
|
|
.profile-scroll-wrap.fade-left .profile-scroll-chevron.left { opacity: 1; }
|
|
.profile-scroll-wrap.fade-right .profile-scroll-chevron.right { opacity: 1; }
|
|
|
|
/* ── Profile & config nav dropdown ──────────────────────────────────────
|
|
The profile picker + config strip used to sit in a permanent full-width
|
|
band above the day tabs. They now live in a dropdown that expands
|
|
downward directly under the (now permanently floating) top nav, opened by
|
|
the profile trigger embedded in the middle of that nav. Keeps the
|
|
original full-width horizontal layout (profile tabs, horizontally
|
|
scrolling card row, config strip) - just collapsed by default. */
|
|
|
|
/* Floating trigger, fixed to the bottom of the viewport (the dropdown itself
|
|
now slides up from the bottom too — see .profile-dropdown below — so the
|
|
button sits right where the panel will appear from). Always visible,
|
|
independent of the nav/header, which has gone back to scrolling away
|
|
normally instead of floating. */
|
|
.floating-profile-btn {
|
|
position: fixed;
|
|
left: 50%;
|
|
bottom: 8px;
|
|
transform: translateX(-50%);
|
|
z-index: 98;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
max-width: 92vw;
|
|
padding: 10px 18px;
|
|
background: #fdf8ee;
|
|
border: 1.5px solid #c9b08a;
|
|
border-radius: 999px;
|
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.10);
|
|
cursor: pointer;
|
|
color: #6a4c1a;
|
|
transition: background 0.15s, border-color 0.15s, box-shadow 0.15s;
|
|
}
|
|
@media (min-width: 1024px) {
|
|
.floating-profile-btn {
|
|
display: none;
|
|
}
|
|
}
|
|
.floating-profile-btn:hover { background: #fff; border-color: #c8922a; box-shadow: 0 3px 10px rgba(0, 0, 0, 0.14); }
|
|
.floating-profile-btn.is-open { background: #fff; border-color: #c8922a; }
|
|
.floating-profile-icon { font-size: 16px; line-height: 1; flex: none; }
|
|
/* No fixed max-width — the pill grows to fit the label. Ellipsis only
|
|
kicks in once the whole button hits its 92vw cap (min-width:0 lets these
|
|
flex children actually shrink instead of forcing the button to overflow). */
|
|
.floating-profile-val {
|
|
font-family: Manrope, sans-serif;
|
|
font-size: 13px;
|
|
font-weight: 800;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.02em;
|
|
color: #1e1208;
|
|
min-width: 0;
|
|
flex: 0 1 auto;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
white-space: nowrap;
|
|
}
|
|
.floating-profile-sub {
|
|
font-family: Manrope, sans-serif;
|
|
font-size: 12px;
|
|
font-weight: 600;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.02em;
|
|
color: #6b4f2a;
|
|
min-width: 0;
|
|
flex: 0 1 auto;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
white-space: nowrap;
|
|
}
|
|
.floating-profile-caret {
|
|
font-size: 10px;
|
|
transition: transform 0.2s ease;
|
|
}
|
|
.floating-profile-btn.is-open .floating-profile-caret { transform: rotate(180deg); }
|
|
|
|
/* Backdrop + dropdown panel — always mounted once opened for the first time
|
|
(see ConfigPanel.js), visibility/position driven by the .is-open class so
|
|
both the open AND close transitions can animate (a conditionally-mounted
|
|
element only ever gets an entrance animation, never an exit one). */
|
|
.profile-dropdown-overlay {
|
|
position: fixed;
|
|
inset: 0;
|
|
background: rgba(0, 0, 0, 0.35);
|
|
z-index: 99;
|
|
opacity: 0;
|
|
visibility: hidden;
|
|
pointer-events: none;
|
|
transition: opacity 0.2s ease, visibility 0s linear 0.2s;
|
|
}
|
|
.profile-dropdown-overlay.is-open {
|
|
opacity: 1;
|
|
visibility: visible;
|
|
pointer-events: auto;
|
|
transition: opacity 0.2s ease, visibility 0s linear 0s;
|
|
}
|
|
.profile-dropdown {
|
|
position: fixed;
|
|
left: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
max-height: calc(100vh - 24px);
|
|
z-index: 101;
|
|
background: #f5edd6;
|
|
border-top: 1.5px solid #c9b08a;
|
|
box-shadow: 0 -10px 28px rgba(0, 0, 0, 0.18);
|
|
opacity: 0;
|
|
visibility: hidden;
|
|
pointer-events: none;
|
|
/* Scales up from the floating-profile-btn's position (bottom-centre) so
|
|
the panel reads as growing out of that button, and shrinks back into
|
|
it on close, instead of a generic slide. */
|
|
transform-origin: 50% 100%;
|
|
transform: scale(0.85);
|
|
transition: opacity 0.22s cubic-bezier(0.22, 1, 0.36, 1),
|
|
transform 0.22s cubic-bezier(0.22, 1, 0.36, 1),
|
|
visibility 0s linear 0.22s;
|
|
}
|
|
.profile-dropdown.is-open {
|
|
opacity: 1;
|
|
visibility: visible;
|
|
pointer-events: auto;
|
|
transform: scale(1);
|
|
transition: opacity 0.22s cubic-bezier(0.22, 1, 0.36, 1),
|
|
transform 0.22s cubic-bezier(0.22, 1, 0.36, 1),
|
|
visibility 0s linear 0s;
|
|
}
|
|
.profile-dropdown-body {
|
|
max-width: 900px;
|
|
margin: 0 auto;
|
|
max-height: calc(100vh - 24px);
|
|
overflow-y: auto;
|
|
padding: 12px 24px 16px;
|
|
}
|
|
.profile-dropdown-close {
|
|
position: absolute;
|
|
top: 10px;
|
|
right: 14px;
|
|
background: none;
|
|
border: none;
|
|
font-size: 24px;
|
|
line-height: 1;
|
|
color: #b09870;
|
|
cursor: pointer;
|
|
padding: 2px 8px;
|
|
border-radius: 6px;
|
|
transition: color 0.15s, background 0.15s;
|
|
}
|
|
.profile-dropdown-close:hover { color: #1e1208; background: rgba(176, 152, 112, 0.16); }
|
|
|
|
/* Read-only "what am I looking at" row above the day tabs — states the
|
|
active profile and the thermal basis (SunSoak env / vehicle / building /
|
|
fur colour) driving the numbers below. Clicking/Enter opens the same
|
|
profile & config dropdown as the nav trigger. */
|
|
.active-profile-row {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
flex-wrap: wrap;
|
|
gap: 12px;
|
|
padding: 2px 16px;
|
|
margin-bottom: 6px;
|
|
/* --row-bg is set inline per the exact selected option (see ROW_GRADIENTS
|
|
in DayTabs.js) — falls back to a flat parchment tone if unset. */
|
|
background: var(--row-bg, #fdf8ee);
|
|
border: 1.5px solid #d4c0a0;
|
|
border-radius: 6px;
|
|
cursor: pointer;
|
|
transition: filter 0.15s, border-color 0.15s;
|
|
}
|
|
/* Remove alpha from the default fallback color and any potential inherited
|
|
semi-transparent backgrounds while keeping the hue. */
|
|
.active-profile-row:not([style*="background"]) {
|
|
background-color: #fdf8ee;
|
|
}
|
|
@media (min-width: 1024px) {
|
|
.active-profile-row {
|
|
position: sticky;
|
|
top: 0 !important; /* Stick to the very top of the viewport */
|
|
z-index: 11;
|
|
}
|
|
.utci-thead-sticky {
|
|
position: sticky;
|
|
top: 28px !important; /* Corrected to match the height of the active-profile-row + margins */
|
|
z-index: 10;
|
|
}
|
|
}
|
|
.active-profile-row:hover,
|
|
.active-profile-row:focus-visible {
|
|
filter: brightness(1.06);
|
|
border-color: #c8922a;
|
|
outline: none;
|
|
}
|
|
.active-profile-row-item {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 7px;
|
|
}
|
|
.active-profile-row-label {
|
|
font-family: Manrope, sans-serif;
|
|
font-size: 12px;
|
|
font-weight: 700;
|
|
letter-spacing: 0.06em;
|
|
text-transform: uppercase;
|
|
color: #9a7d5a;
|
|
}
|
|
.active-profile-row-value {
|
|
font-family: Manrope, sans-serif;
|
|
font-size: 15px;
|
|
font-weight: 800;
|
|
letter-spacing: 0.02em;
|
|
text-transform: uppercase;
|
|
color: #1e1208;
|
|
}
|
|
.active-profile-row-sep { color: #c0a880; font-size: 16px; }
|
|
.active-profile-row-edit {
|
|
font-family: Manrope, sans-serif;
|
|
font-size: 13px;
|
|
font-weight: 700;
|
|
letter-spacing: 0.04em;
|
|
color: #9a6a1a;
|
|
margin-left: 4px;
|
|
}
|
|
|
|
/* Border + text accent per thermal-model group, reusing the same colour
|
|
groups the CustomSelect pickers use (see .cs-btn.grp-* in ui.css) — e.g.
|
|
SunSoak's "Solar model" dropdown is grp-felt. The background itself comes
|
|
from --row-bg (inline, per exact selection — see ROW_GRADIENTS); these
|
|
classes only set the border/text so the row still reads as belonging to
|
|
its category even though the gradient varies option-to-option. */
|
|
.active-profile-row.grp-felt { border-color: rgba(7,92,58,0.35); }
|
|
.active-profile-row.grp-wind { border-color: rgba(106,34,16,0.30); }
|
|
.active-profile-row.grp-ambient { border-color: rgba(60,58,53,0.30); }
|
|
.active-profile-row.grp-surface { border-color: rgba(11,62,114,0.30); }
|
|
|
|
.active-profile-row.grp-felt .active-profile-row-value { color: #075c3a; }
|
|
.active-profile-row.grp-wind .active-profile-row-value { color: #6a2210; }
|
|
.active-profile-row.grp-ambient .active-profile-row-value { color: #3c3a35; }
|
|
.active-profile-row.grp-surface .active-profile-row-value { color: #0b3e72; }
|
|
|
|
/* 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.7;
|
|
transition: opacity 0.2s;
|
|
}
|
|
|
|
.profile-btn:hover .profile-btn-scene {
|
|
opacity: 0.8;
|
|
}
|
|
|
|
.profile-btn.active .profile-btn-scene {
|
|
opacity: 1;
|
|
}
|
|
|
|
.profile-lock-badge {
|
|
position: absolute;
|
|
top: 4px;
|
|
right: 4px;
|
|
font-size: 11px;
|
|
line-height: 1;
|
|
pointer-events: none;
|
|
z-index: 1;
|
|
}
|
|
|
|
.profile-btn-label {
|
|
position: absolute;
|
|
bottom: 0;
|
|
left: 0;
|
|
right: 0;
|
|
height: 24px;
|
|
display: block;
|
|
line-height: 24px;
|
|
text-align: 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;
|
|
}
|
|
|
|
/* Tab strip above the profile scroll row */
|
|
.profile-tabs {
|
|
display: flex;
|
|
width: 360px;
|
|
margin-left: auto;
|
|
margin-right: auto;
|
|
margin-bottom: 0px;
|
|
}
|
|
.profile-tab {
|
|
flex: 1;
|
|
padding: 7px 4px;
|
|
background: transparent;
|
|
border: none;
|
|
border-bottom: 1.5px solid transparent;
|
|
border-left: 1.5px solid #f5edd6;
|
|
border-right: 1.5px solid #f5edd6;
|
|
border-top: 1.5px solid #f5edd6;
|
|
font-family: Manrope, sans-serif;
|
|
font-size: 11px;
|
|
font-weight: 700;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.06em;
|
|
color: #9a7a4a;
|
|
cursor: pointer;
|
|
transition: color 0.15s, border-color 0.15s;
|
|
white-space: nowrap;
|
|
border-radius:7px 7px 0px 0px;
|
|
z-index:1;
|
|
}
|
|
.profile-tab:hover {
|
|
color: #c8922a;
|
|
background: #f0e4c4;
|
|
}
|
|
.profile-tab.active {
|
|
color: #c8922a;
|
|
background-color: #fffcf2;
|
|
border-bottom-color: #fffcf2;
|
|
border-left: 1.5px solid #c9b08a;
|
|
border-right: 1.5px solid #c9b08a;
|
|
border-top: 1.5px solid #c9b08a;
|
|
margin-bottom: -1.5px;
|
|
}
|
|
|
|
|
|
/* ── 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;
|
|
position: relative;
|
|
}
|
|
|
|
/* Whole Columns bar (Hours + column pills) stays collapsed behind the
|
|
Edit columns / Hide Columns toggle in the toolbar row until opened.
|
|
Scoped to detailed (table) view — quick view keeps its own reduced
|
|
col-toggles bar (Hours only) visible regardless of this state. */
|
|
.table-main:not(.table-main--simple) .col-toggles {
|
|
display: none;
|
|
}
|
|
|
|
.table-main:not(.table-main--simple) .col-toggles.col-toggles--open {
|
|
display: flex;
|
|
}
|
|
|
|
|
|
.col-toggles-display-opts {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 12px;
|
|
margin-left: auto;
|
|
padding-left: 10px;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.col-toggles-label {
|
|
display: none;
|
|
}
|
|
|
|
.col-toggles-edit-btn {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
gap: 6px;
|
|
width: 150px;
|
|
padding: 6px 12px;
|
|
background: #f5edd6;
|
|
border: 1.5px solid #c9b08a;
|
|
color: #7a5c2a;
|
|
font-family: Manrope, sans-serif;
|
|
font-size: 10px;
|
|
font-weight: 700;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.08em;
|
|
cursor: pointer;
|
|
text-align: left;
|
|
}
|
|
|
|
.col-toggles-edit-btn-icon {
|
|
width: 12px;
|
|
height: 12px;
|
|
flex-shrink: 0;
|
|
transition: transform 0.2s ease;
|
|
}
|
|
|
|
.col-toggles-edit-btn--open .col-toggles-edit-btn-icon {
|
|
transform: rotate(180deg);
|
|
}
|
|
|
|
.col-toggles-body {
|
|
display: contents;
|
|
}
|
|
|
|
/* 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;
|
|
}
|
|
|
|
/* Profile/config dropdown - full width and scrollable on phones since it
|
|
can run taller than the viewport once the config strip wraps. */
|
|
.profile-dropdown-body {
|
|
max-height: calc(100vh - 16px);
|
|
overflow-y: auto;
|
|
}
|
|
.floating-profile-val { max-width: 90px; }
|
|
.floating-profile-sub { max-width: 90px; }
|
|
|
|
/* Shrink the day-tab labels on phones so more days stay readable
|
|
within the viewport before the tab strip needs to scroll. */
|
|
.utci-day-tab {
|
|
font-size: 9px;
|
|
padding: 10px 12px;
|
|
}
|
|
|
|
.utci-day-date {
|
|
font-size: 12px;
|
|
}
|
|
}
|
|
|
|
/* 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 <th> 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 <th> 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;
|
|
}
|
|
|
|
/* ── HOUR-INTERVAL SELECTOR ──────────────────────────────────────────────
|
|
Compact 1h/2h/3h/4h segmented control inside the "Hour" header. Buckets
|
|
the table into multi-hour rows (clock-aligned from midnight). Lives in the
|
|
header so it stays put while the body scrolls. */
|
|
.hour-interval {
|
|
display: flex;
|
|
justify-content: flex-start;
|
|
gap: 2px;
|
|
margin-top: 4px;
|
|
}
|
|
.hour-interval-btn {
|
|
font-family: Manrope, sans-serif;
|
|
font-size: 10px;
|
|
font-weight: 700;
|
|
line-height: 1;
|
|
padding: 3px 4px;
|
|
cursor: pointer;
|
|
border: 1px solid #c9b08a;
|
|
background: #f5edd6;
|
|
color: #6b4228;
|
|
border-radius: 3px;
|
|
transition: background 0.12s, border-color 0.12s, color 0.12s;
|
|
}
|
|
.hour-interval-btn:hover {
|
|
border-color: #c8922a;
|
|
background: #fef3dc;
|
|
}
|
|
.hour-interval-btn.on {
|
|
background: #c8922a;
|
|
border-color: #c8922a;
|
|
color: #fff;
|
|
}
|
|
|
|
/* ── 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 0 0;
|
|
}
|
|
|
|
.profile-tabs {
|
|
width: 100%;
|
|
margin-left: 0;
|
|
margin-right: 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,
|
|
.col-toggles-config {
|
|
flex-wrap: wrap;
|
|
gap: 6px;
|
|
padding: 10px 10px;
|
|
align-items: stretch;
|
|
}
|
|
|
|
|
|
.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;
|
|
}
|
|
|
|
/* Config strip - each labelled item becomes its own stacked card on
|
|
mobile (label above control) rather than a label crammed next to a
|
|
squeezed pill, so multiple pickers read as separate rows, not a
|
|
jumbled wall of controls. */
|
|
.col-toggles-config {
|
|
gap: 8px;
|
|
}
|
|
|
|
.col-toggles-config-item {
|
|
flex: 0 0 100%;
|
|
min-width: 0;
|
|
flex-direction: column;
|
|
align-items: stretch;
|
|
gap: 5px;
|
|
padding: 8px 10px;
|
|
background: rgba(255,255,255,0.55);
|
|
border: 1px solid #e6d7b8;
|
|
border-radius: 5px;
|
|
}
|
|
|
|
/* Re-affirm the gold emphasis for the "main" item so it still stands
|
|
out after the generic card border above. */
|
|
.col-toggles-config-item--main {
|
|
border-color: #c8922a;
|
|
background: rgba(200,146,42,0.10);
|
|
}
|
|
|
|
.config-item-label {
|
|
text-align: center;
|
|
}
|
|
|
|
/* The "SunSoak Config:" badge sits above the main item as its own
|
|
centred header row, instead of squeezed inline before the pill. */
|
|
.config-item-main-badge {
|
|
display: block;
|
|
flex: 0 0 100%;
|
|
width: 100%;
|
|
text-align: center;
|
|
padding: 0 0 2px;
|
|
}
|
|
|
|
.col-toggles-config-item .cs-wrap,
|
|
.col-toggles-config-item .col-toggle-group {
|
|
flex: 1 1 auto;
|
|
min-width: 0;
|
|
width: 100%;
|
|
}
|
|
.col-toggles-config-item .cs-btn {
|
|
width: 100%;
|
|
min-width: 0;
|
|
padding: 8px 6px;
|
|
font-size: 12px;
|
|
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);
|
|
}
|
|
/* Vehicle group fuses three children (select + speed + vent) — full row. */
|
|
.col-toggle-group--expanded.col-toggle-group--triple {
|
|
flex: 0 0 100%;
|
|
}
|
|
.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;
|
|
}
|
|
|
|
/* Vehicle's triple group (type + speed + vent) doesn't fit fused on one
|
|
line at phone widths — the vent pill won't shrink below its text, so
|
|
it either overflows or forces the row taller. Give the type select its
|
|
own full-width row and let speed+vent share the row below, still
|
|
fused to each other, so nothing has to fight for space. */
|
|
.col-toggle-group--triple {
|
|
flex-wrap: wrap;
|
|
align-content: flex-start;
|
|
row-gap: 6px;
|
|
}
|
|
.col-toggle-group--triple .cs-wrap:first-child {
|
|
flex: 0 0 100%;
|
|
}
|
|
.col-toggle-group--triple .cs-wrap:first-child .grouped-left {
|
|
border-right: 1.5px solid #c9b08a !important;
|
|
border-radius: 3px !important;
|
|
}
|
|
/* The base .col-toggle-group .cs-wrap rule sets min-width:0, which lets
|
|
this select shrink to nothing and get squeezed onto row 1 next to the
|
|
now-full-width type select instead of wrapping. Restore a real min
|
|
width so it's forced onto row 2 with the vent pill instead. */
|
|
.col-toggle-group--triple .cs-wrap:nth-child(2) {
|
|
flex: 1 1 0;
|
|
min-width: 80px;
|
|
width: auto;
|
|
}
|
|
.col-toggle-group--triple .cs-vent {
|
|
flex: 1 1 0;
|
|
min-width: 0;
|
|
}
|
|
|
|
}
|
|
|
|
/* ── 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;
|
|
}
|
|
}
|
|
|
|
/* ── SIMPLE / TABLE VIEW TOGGLE ─────────────────────────────────────────── */
|
|
|
|
.forecast-view-toggle-label {
|
|
font-family: Manrope, sans-serif;
|
|
font-size: 11px;
|
|
font-weight: 700;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.07em;
|
|
color: #7a5c2a;
|
|
margin-right: 5px;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.forecast-view-toggle {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
flex-shrink: 0;
|
|
margin-right: 8px;
|
|
}
|
|
.fvt-btn {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 3px;
|
|
font-family: Manrope, sans-serif;
|
|
font-size: 11px;
|
|
font-weight: 700;
|
|
line-height: 1;
|
|
padding: 6px 14px;
|
|
cursor: pointer;
|
|
border: 1.5px solid #c9b08a;
|
|
background: #f5edd6;
|
|
color: #6b4228;
|
|
transition: background 0.12s, border-color 0.12s, color 0.12s;
|
|
}
|
|
.fvt-btn:first-child {
|
|
border-radius: 3px 0 0 3px;
|
|
}
|
|
.fvt-btn:last-child {
|
|
border-left: none;
|
|
border-radius: 0 3px 3px 0;
|
|
}
|
|
.fvt-btn:hover {
|
|
border-color: #c8922a;
|
|
background: #fef3dc;
|
|
z-index: 1;
|
|
}
|
|
.fvt-btn.on {
|
|
background: #c8922a;
|
|
border-color: #c8922a;
|
|
color: #fff;
|
|
}
|
|
|
|
.fvt-btn-icon {
|
|
display: inline-block;
|
|
vertical-align: middle;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
/* Toolbar row sitting directly above col-toggles (zero gap, normal flow):
|
|
View toggle on the left, and — in Quick view — the thermal-model tabs
|
|
centered, touching the col-toggles top border so they read as folder
|
|
tabs attached to it. Kept as a 3-column grid (with an empty right
|
|
track) so the center tabs stay genuinely centered on the row rather
|
|
than just sitting flush after the View toggle. */
|
|
.table-toolbar-row {
|
|
display: grid;
|
|
grid-template-columns: 1fr auto 1fr;
|
|
align-items: end;
|
|
padding: 0 14px;
|
|
}
|
|
.fvt-toolbar-left {
|
|
grid-column: 1;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
justify-self: start;
|
|
padding-bottom: 8px;
|
|
}
|
|
.fvt-thermal-tabs {
|
|
grid-column: 2;
|
|
justify-self: center;
|
|
display: flex;
|
|
width: 360px;
|
|
align-items: center;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
/* Mobile: stack instead of two columns — View on top, thermal tabs
|
|
below it so they still sit flush against the col-toggles border
|
|
underneath. Placed after the base rules above so it wins the cascade
|
|
(equal specificity, later source order) regardless of where in the
|
|
file the @media block lives. */
|
|
@media (max-width: 640px) {
|
|
.table-toolbar-row {
|
|
grid-template-columns: 1fr;
|
|
justify-items: center;
|
|
row-gap: 6px;
|
|
padding: 6px 10px 0;
|
|
}
|
|
.fvt-toolbar-left {
|
|
grid-column: 1;
|
|
grid-row: 1;
|
|
justify-self: center;
|
|
padding-bottom: 0;
|
|
}
|
|
.fvt-thermal-tabs {
|
|
grid-column: 1;
|
|
grid-row: 2;
|
|
justify-self: stretch;
|
|
width: 100%;
|
|
}
|
|
}
|
|
|
|
.fvt-thermal-tab {
|
|
flex: 1;
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
font-family: Manrope, sans-serif;
|
|
font-size: 11px;
|
|
font-weight: 700;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.06em;
|
|
padding: 9px 2px;
|
|
cursor: pointer;
|
|
background: transparent;
|
|
border: 1.5px solid #f5edd6;
|
|
border-left: none;
|
|
border-bottom: 1.5px solid transparent;
|
|
color: #9a7a4a;
|
|
transition: color 0.15s, border-color 0.15s, background 0.15s;
|
|
border-radius: 7px 7px 0 0;
|
|
z-index: 1;
|
|
}
|
|
.fvt-thermal-tab:first-child {
|
|
border-left: 1.5px solid #f5edd6;
|
|
}
|
|
.fvt-thermal-tab:hover {
|
|
color: #c8922a;
|
|
background: #f0e4c4;
|
|
}
|
|
.fvt-thermal-tab.on {
|
|
color: #c8922a;
|
|
background-color: #fdf8ee;
|
|
border-bottom-color: #fdf8ee;
|
|
border-left: 1.5px solid #d4c0a0;
|
|
border-right: 1.5px solid #d4c0a0;
|
|
border-top: 1.5px solid #d4c0a0;
|
|
margin-bottom: -1.5px;
|
|
}
|
|
|
|
/* Interval buttons shown in the col-toggles bar in simple mode, pushed
|
|
to the far right since Columns/Edit controls are hidden there. */
|
|
.fvt-interval {
|
|
display: none;
|
|
align-items: center;
|
|
gap: 2px;
|
|
margin-left: auto;
|
|
flex-shrink: 0;
|
|
}
|
|
.table-main--simple .fvt-interval {
|
|
display: inline-flex;
|
|
}
|
|
.fvt-interval-label {
|
|
font-family: Manrope, sans-serif;
|
|
font-size: 11px;
|
|
font-weight: 700;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.07em;
|
|
color: #7a5c2a;
|
|
margin-right: 3px;
|
|
}
|
|
|
|
/* Hide table-mode column controls when in simple mode */
|
|
.table-main--simple .col-toggles-label,
|
|
.table-main--simple .col-toggles-edit-btn,
|
|
.table-main--simple .col-toggles-body {
|
|
display: none !important;
|
|
}
|
|
|
|
/* Show simple view, hide table; swap in table mode */
|
|
.forecast-simple-wrap {
|
|
display: none;
|
|
}
|
|
.table-main--simple {
|
|
display: block;
|
|
}
|
|
.table-main--simple .forecast-simple-wrap {
|
|
display: flex;
|
|
flex-direction: column;
|
|
height: 420px;
|
|
border: 1.5px solid #d4c0a0;
|
|
background: #fdf8ee;
|
|
}
|
|
.table-main--simple .utci-table-wrap {
|
|
display: none;
|
|
}
|
|
|
|
/* ── SIMPLE VIEW CARDS ───────────────────────────────────────────────────── */
|
|
|
|
.forecast-simple-scroll {
|
|
flex: 1;
|
|
display: flex;
|
|
flex-direction: column;
|
|
overflow-x: auto;
|
|
overflow-y: hidden;
|
|
scrollbar-width: thin;
|
|
scrollbar-color: #c9b08a transparent;
|
|
cursor: grab;
|
|
}
|
|
.forecast-simple-scroll:active {
|
|
cursor: grabbing;
|
|
}
|
|
.forecast-simple-scroll::-webkit-scrollbar {
|
|
height: 4px;
|
|
}
|
|
.forecast-simple-scroll::-webkit-scrollbar-track {
|
|
background: transparent;
|
|
}
|
|
.forecast-simple-scroll::-webkit-scrollbar-thumb {
|
|
background: #c9b08a;
|
|
border-radius: 2px;
|
|
}
|
|
.forecast-simple-inner {
|
|
flex: 1;
|
|
display: flex;
|
|
flex-direction: column;
|
|
width: max-content;
|
|
min-width: 100%;
|
|
}
|
|
/* Half-hour tracks across the whole day, plus a blank inset spacer at each
|
|
end (see fscPlot in app.js). Each card spans 2*interval tracks positioned
|
|
so it is centred on the hour it is labelled with; the outer cards overhang
|
|
into the spacers instead of off the edge. Columns are set inline. */
|
|
.forecast-simple-cards {
|
|
display: grid;
|
|
padding: 12px 0 0;
|
|
}
|
|
|
|
.fsc-card {
|
|
min-width: 0;
|
|
text-align: center;
|
|
border: none;
|
|
background: transparent;
|
|
padding: 10px 8px 12px;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
gap: 6px;
|
|
border-radius: 1px;
|
|
}
|
|
.fsc-card--now {
|
|
border: 1.5px solid #c8922a;
|
|
background: #fff9ee;
|
|
box-shadow: 0 2px 10px rgba(200,146,42,0.18);
|
|
position: relative;
|
|
z-index: 1;
|
|
}
|
|
|
|
.fsc-time {
|
|
font-family: JetBrains Mono, monospace;
|
|
font-size: 12px;
|
|
font-weight: 700;
|
|
color: #4a3218;
|
|
line-height: 1;
|
|
}
|
|
.fsc-card--now .fsc-time {
|
|
color: #c8922a;
|
|
}
|
|
|
|
.fsc-feel {
|
|
font-family: Manrope, sans-serif;
|
|
font-size: 10px;
|
|
font-weight: 700;
|
|
padding: 2px 6px;
|
|
border-radius: 2px;
|
|
line-height: 1.3;
|
|
max-width: 100%;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.fsc-scope-wrap {
|
|
position: relative;
|
|
width: 42px;
|
|
height: 42px;
|
|
flex-shrink: 0;
|
|
}
|
|
.fsc-wx-overlay {
|
|
position: absolute;
|
|
inset: 0;
|
|
top: 3px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
pointer-events: none;
|
|
}
|
|
|
|
.fsc-meta {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
gap: 2px;
|
|
width: 100%;
|
|
}
|
|
.fsc-meta-row {
|
|
font-family: Manrope, sans-serif;
|
|
font-size: 10px;
|
|
font-weight: 600;
|
|
line-height: 1.2;
|
|
color: #6b5230;
|
|
opacity: 0.8;
|
|
}
|
|
.fsc-card--now .fsc-meta-row { opacity: 1; color: #4a3218; }
|
|
.fsc-meta-rain { color: #2a6a90; }
|
|
.fsc-card--now .fsc-meta-rain { color: #1a4a70; }
|
|
|
|
.fsc-temp {
|
|
font-family: Fraunces, serif;
|
|
font-size: 22px;
|
|
font-weight: 700;
|
|
color: #1e1208;
|
|
line-height: 1;
|
|
}
|
|
|
|
.fsc-temp-curve {
|
|
display: block;
|
|
width: 100%;
|
|
flex: 1;
|
|
min-height: 60px;
|
|
}
|
|
|
|
.fsc-table-btn-wrap {
|
|
padding: 10px 16px 12px;
|
|
border-top: 1px solid #d4c0a0;
|
|
background: #fdf8ee;
|
|
flex-shrink: 0;
|
|
}
|
|
.fsc-table-btn {
|
|
display: block;
|
|
width: 100%;
|
|
padding: 10px 16px;
|
|
border: 1.5px solid #a87020;
|
|
border-radius: 6px;
|
|
background: linear-gradient(to bottom, #d4a030, #b8781a);
|
|
font-family: Manrope, sans-serif;
|
|
font-size: 14px;
|
|
font-weight: 700;
|
|
color: #fff;
|
|
letter-spacing: 0.03em;
|
|
cursor: pointer;
|
|
text-align: center;
|
|
box-shadow: 0 1px 4px rgba(160,100,20,0.22);
|
|
text-shadow: 0 1px 2px rgba(0,0,0,0.18);
|
|
}
|
|
.fsc-table-btn:hover {
|
|
background: linear-gradient(to bottom, #e8b848, #cc9030);
|
|
border-color: #c8922a;
|
|
box-shadow: 0 2px 8px rgba(200,146,42,0.28);
|
|
}
|
|
|
|
@media (max-width: 600px) {
|
|
.fsc-card {
|
|
min-width: 55px;
|
|
padding: 8px 4px 10px;
|
|
gap: 5px;
|
|
}
|
|
.fsc-temp {
|
|
font-size: 19px;
|
|
}
|
|
.fsc-feel {
|
|
font-size: 9px;
|
|
padding: 2px 4px;
|
|
}
|
|
.fsc-temp-curve {
|
|
min-height: 48px;
|
|
}
|
|
}
|