/* ════════════════════════════════════════════════════════════════════════ 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-bottom: 18px; } /* 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; border-bottom: 2px solid #d4c0a0; 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-shrink: 0; 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: none; color: #b09870; border-bottom: 2px solid transparent; margin-bottom: -2px; transition: color 0.2s, border-color 0.2s; } .utci-day-tab:hover { color: #6b4f2a; } .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-wrap: wrap; gap: 6px; align-items: center; margin-bottom: 0; padding: 10px 14px; background: #fdf8ee; border: 1.5px solid #d4c0a0; border-bottom: none; /* merges visually with the col-toggles bar below */ } .filter-profiles-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; } /* Vertical rule separating general-use profiles from technical ones */ .profile-divider { display: inline-block; width: 1px; align-self: stretch; background: #c9b08a; margin: 2px 6px; opacity: 0.6; } .profile-btn { padding: 5px 13px; cursor: pointer; border: 1.5px solid #c9b08a; background: #f5edd6; color: #6b4228; font-family: Manrope, sans-serif; font-size: 13px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em; transition: all 0.15s; -webkit-user-select: none; user-select: none; } .profile-btn:hover { border-color: #c8922a; color: #6b4f2a; background: #fef3dc; } .profile-btn.active { background: #c8922a; border-color: #c8922a; 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: 10px; padding: 10px 14px; background: #fdf8ee; border: 1.5px solid #d4c0a0; } .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; } /* Burn select — unlike regular col-toggle buttons, the select never goes full-brass background so the native dropdown list stays readable. Active state = brass border + brass text on parchment. Inactive state = same as a regular col-toggle pill. */ .burn-select { cursor: pointer; outline: none; } /* Override the inherited .col-toggle.on brass background */ .col-toggle.burn-select.on { background: #f5edd6; color: #c8922a; border-color: #c8922a; font-weight: 600; } .col-toggle.burn-select.on:hover { background: #fef3dc; color: #c8922a; border-color: #c8922a; } .burn-select:focus { border-color: #c8922a; outline: none; } /* ── 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: 20px 0 0 20px !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: 20px !important; } /* The checkbox pill — same height/padding as a col-toggle but styled as a label */ .col-toggle-vent { display: inline-flex; align-items: center; gap: 5px; padding: 5px 12px 5px 10px; font-size: 12px; font-family: Manrope, sans-serif; font-weight: 700; letter-spacing: 0.05em; text-transform: uppercase; cursor: pointer; border: 1.5px solid #c9b08a; border-left: 1px solid #d4c0a0; /* softer join line */ border-radius: 0 20px 20px 0; background: #fef8ee; color: #6b4228; user-select: none; transition: background 0.15s, color 0.15s, border-color 0.15s; white-space: nowrap; } .col-toggle-vent:hover { border-color: #c8922a; color: #6b4f2a; background: #fef3dc; } .col-toggle-vent.on { background: #c8922a; border-color: #c8922a; color: #fff; } /* Custom checkbox square inside the vent label */ .vent-checkbox { display: inline-block; width: 12px; height: 12px; border: 1.5px solid currentColor; border-radius: 3px; background: transparent; flex-shrink: 0; position: relative; transition: background 0.12s; } .vent-checkbox.checked::after { content: ''; position: absolute; left: 2px; top: -1px; width: 5px; height: 8px; border: 2px solid currentColor; border-top: none; border-left: none; transform: rotate(45deg); } /* ── 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); } /* 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