Files
fraxle 71860b9dd9 5.4.0
Restructure
New Journal entries
Colour tabs update with wind
2026-08-31 15:12:45 +01:00

2029 lines
52 KiB
CSS
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* ════════════════════════════════════════════════════════════════════════
ui.css — Status banners, legend, about block, footer, and responsive.
════════════════════════════════════════════════════════════════════════ */
/* Cell tag — event icon in the hour column */
.event-cell-tag {
font-size: 15px;
line-height: 1;
vertical-align: middle;
margin-left: 1px;
display: inline-block;
cursor: pointer;
border-radius: 3px;
transition: opacity 0.15s;
}
.event-cell-tag:hover {
opacity: 0.75;
}
/* ── ALMANAC PANEL ──────────────────────────────────────────────────── */
/* "What's Coming" upcoming cosmic events box below the forecast table. */
.almanac-panel {
margin: 20px 0 12px;
border: 1.5px solid #c9b08a;
border-radius: 4px;
background: #fdf8ee;
overflow: hidden;
}
.almanac-header {
display: flex;
align-items: baseline;
gap: 12px;
padding: 12px 18px 10px;
border-bottom: 1px solid #e8d8b8;
background: #faf2e2;
}
.almanac-title {
font-family: Fraunces, serif;
font-style: italic;
font-weight: 700;
font-size: 17px;
color: #2a1a08;
letter-spacing: 0;
}
.almanac-subtitle {
font-family: Manrope, sans-serif;
font-size: 10px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.07em;
color: #9a7d5a;
}
.almanac-list {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-auto-rows: 1fr;
gap: 0;
}
.almanac-entry {
display: flex;
align-items: flex-start;
gap: 13px;
padding: 13px 18px;
border-right: 1px solid #f0e4cc;
transition: background 0.15s;
}
/* Desktop: single row of 4 — vertical dividers only, none on the far edge. */
.almanac-entry:last-child {
border-right: none;
}
.almanac-entry:hover {
background: #fef8e8;
}
.almanac-entry-icon {
font-size: 22px;
line-height: 1;
flex-shrink: 0;
margin-top: 1px;
}
.almanac-entry-body {
flex: 1;
min-width: 0;
}
.almanac-entry-head {
display: flex;
align-items: baseline;
gap: 8px;
flex-wrap: wrap;
margin-bottom: 3px;
}
.almanac-entry-title {
font-family: Fraunces, serif;
font-style: italic;
font-weight: 700;
font-size: 14px;
color: #1e1208;
line-height: 1.2;
}
.almanac-entry-date {
font-family: Manrope, sans-serif;
font-size: 10px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.06em;
color: #c8922a;
white-space: nowrap;
}
.almanac-entry-countdown {
font-family: Manrope, sans-serif;
font-size: 10px;
font-weight: 700;
color: #9a7d5a;
white-space: nowrap;
}
.almanac-entry-desc {
font-family: Manrope, sans-serif;
font-size: 12px;
color: #4a3420;
line-height: 1.55;
}
.almanac-entry-visibility {
display: inline-block;
margin-top: 5px;
font-family: Manrope, sans-serif;
font-size: 10px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.06em;
color: #7a9a6a;
background: #eef4e8;
border: 1px solid #c0d8b0;
border-radius: 3px;
padding: 2px 7px;
}
.almanac-entry-accent {
width: 3px;
align-self: stretch;
border-radius: 2px;
flex-shrink: 0;
margin-top: 1px;
opacity: 0.7;
}
.almanac-empty {
padding: 22px 18px;
font-family: Manrope, sans-serif;
font-size: 13px;
color: #9a7d5a;
font-style: italic;
}
/* ≤900px: fall back to a 2×2 grid so cards stay readable. */
@media (max-width: 900px) {
.almanac-list {
grid-template-columns: repeat(2, 1fr);
}
.almanac-entry {
border-right: 1px solid #f0e4cc;
}
.almanac-entry:nth-child(2n) {
border-right: none; /* right edge of the grid */
}
.almanac-entry:nth-child(-n + 2) {
border-bottom: 1px solid #f0e4cc; /* divider between the two rows */
}
}
/* ≤600px: single column. */
@media (max-width: 600px) {
.almanac-list {
grid-template-columns: 1fr;
}
.almanac-entry,
.almanac-entry:nth-child(2n) {
border-right: none;
}
.almanac-entry {
border-bottom: 1px solid #f0e4cc;
}
.almanac-entry:last-child {
border-bottom: none;
}
}
/* ── CUSTOM SELECT DROPDOWN ─────────────────────────────────────────── */
/* Cross-platform replacement for native <select> on the col-toggles bar */
.cs-wrap {
position: relative;
display: inline-block;
}
/* The visible pill button */
.cs-btn {
display: inline-flex;
align-items: center;
gap: 5px;
padding: 5px 10px 5px 13px;
cursor: pointer;
border: 1.5px solid #c9b08a;
border-radius: 0;
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;
user-select: none;
white-space: nowrap;
}
.cs-btn:hover {
border-color: #c8922a;
color: #6b4f2a;
background: #fef3dc;
}
/* Active state — brass border + brass text, parchment background */
.cs-btn.on {
background: #c8922a;
border-color: #c8922a;
color: #fff;
font-weight: 600;
}
.cs-btn.on:hover {
background: #a06e18;
border-color: #a06e18;
color: #fff;
}
/* ── CUSTOM SELECT BUTTON - group colour tints ──────────────────────────
Mirrors the col-toggle group palette for dropdowns (Vehicle, Indoors,
Burn, Pollen). Same idle - hover - on - on-hover pattern. */
.cs-btn.grp-felt { background: rgba(223,243,236,0.50); color: #075c3a; border-color: rgba(7,92,58,0.35); }
.cs-btn.grp-surface { background: rgba(221,234,248,0.50); color: #0b3e72; border-color: rgba(11,62,114,0.30); }
.cs-btn.grp-pets { background: rgba(214,238,240,0.50); color: #0a5158; border-color: rgba(10,81,88,0.30); }
.cs-btn.grp-ambient { background: rgba(236,234,227,0.50); color: #3c3a35; border-color: rgba(60,58,53,0.30); }
.cs-btn.grp-precip { background: rgba(247,228,238,0.50); color: #6b1e3a; border-color: rgba(107,30,58,0.30); }
.cs-btn.grp-sky { background: rgba(234,232,252,0.50); color: #352e7a; border-color: rgba(53,46,122,0.30); }
.cs-btn.grp-wind { background: rgba(250,230,224,0.50); color: #6a2210; border-color: rgba(106,34,16,0.30); }
.cs-btn.grp-airqual { background: rgba(229,240,216,0.50); color: #244408; border-color: rgba(36,68,8,0.30); }
.cs-btn.grp-solar { background: rgba(250,234,204,0.50); color: #5a3004; border-color: rgba(90,48,4,0.30); }
.cs-btn.grp-felt:hover { background: rgba(213,233,226,0.80); color: #075c3a; border-color: rgba(7,92,58,0.55); }
.cs-btn.grp-surface:hover { background: rgba(211,224,238,0.80); color: #0b3e72; border-color: rgba(11,62,114,0.50); }
.cs-btn.grp-pets:hover { background: rgba(204,228,230,0.80); color: #0a5158; border-color: rgba(10,81,88,0.50); }
.cs-btn.grp-ambient:hover { background: rgba(226,224,217,0.80); color: #3c3a35; border-color: rgba(60,58,53,0.50); }
.cs-btn.grp-precip:hover { background: rgba(237,218,228,0.80); color: #6b1e3a; border-color: rgba(107,30,58,0.50); }
.cs-btn.grp-sky:hover { background: rgba(224,222,242,0.80); color: #352e7a; border-color: rgba(53,46,122,0.50); }
.cs-btn.grp-wind:hover { background: rgba(240,220,214,0.80); color: #6a2210; border-color: rgba(106,34,16,0.50); }
.cs-btn.grp-airqual:hover { background: rgba(219,230,206,0.80); color: #244408; border-color: rgba(36,68,8,0.50); }
.cs-btn.grp-solar:hover { background: rgba(240,224,194,0.80); color: #5a3004; border-color: rgba(90,48,4,0.50); }
/* Dropdown buttons - lighter palette to match toggle pills */
.cs-btn.grp-felt.on { background: #2ab578; border-color: #2ab578; color: #fff; }
.cs-btn.grp-surface.on { background: #4088d4; border-color: #4088d4; color: #fff; }
.cs-btn.grp-pets.on { background: #34a0a8; border-color: #34a0a8; color: #fff; }
.cs-btn.grp-ambient.on { background: #929088; border-color: #929088; color: #fff; }
.cs-btn.grp-precip.on { background: #c24e6c; border-color: #c24e6c; color: #fff; }
.cs-btn.grp-sky.on { background: #786ec8; border-color: #786ec8; color: #fff; }
.cs-btn.grp-wind.on { background: #c25646; border-color: #c25646; color: #fff; }
.cs-btn.grp-airqual.on { background: #5e9828; border-color: #5e9828; color: #fff; }
.cs-btn.grp-solar.on { background: #c08c34; border-color: #c08c34; color: #fff; }
.cs-btn.grp-felt.on:hover { background: #1e9e64; border-color: #1e9e64; color: #fff; }
.cs-btn.grp-surface.on:hover { background: #2e72bc; border-color: #2e72bc; color: #fff; }
.cs-btn.grp-pets.on:hover { background: #17868f; border-color: #17868f; color: #fff; }
.cs-btn.grp-ambient.on:hover { background: #7a7870; border-color: #7a7870; color: #fff; }
.cs-btn.grp-precip.on:hover { background: #a83c5a; border-color: #a83c5a; color: #fff; }
.cs-btn.grp-sky.on:hover { background: #6258b0; border-color: #6258b0; color: #fff; }
.cs-btn.grp-wind.on:hover { background: #a84436; border-color: #a84436; color: #fff; }
.cs-btn.grp-airqual.on:hover { background: #4c7e1a; border-color: #4c7e1a; color: #fff; }
.cs-btn.grp-solar.on:hover { background: #a87824; border-color: #a87824; color: #fff; }
/* Toggle pills - lighter palette */
.col-toggle.grp-felt.on { background: #2ab578; border-color: #2ab578; color: #fff; }
.col-toggle.grp-surface.on { background: #4088d4; border-color: #4088d4; color: #fff; }
.col-toggle.grp-pets.on { background: #34a0a8; border-color: #34a0a8; color: #fff; }
.col-toggle.grp-ambient.on { background: #929088; border-color: #929088; color: #fff; }
.col-toggle.grp-precip.on { background: #c24e6c; border-color: #c24e6c; color: #fff; }
.col-toggle.grp-sky.on { background: #786ec8; border-color: #786ec8; color: #fff; }
.col-toggle.grp-wind.on { background: #c25646; border-color: #c25646; color: #fff; }
.col-toggle.grp-airqual.on { background: #5e9828; border-color: #5e9828; color: #fff; }
.col-toggle.grp-solar.on { background: #c08c34; border-color: #c08c34; color: #fff; }
.col-toggle.grp-felt.on:hover { background: #1e9e64; border-color: #1e9e64; color: #fff; }
.col-toggle.grp-surface.on:hover { background: #2e72bc; border-color: #2e72bc; color: #fff; }
.col-toggle.grp-pets.on:hover { background: #17868f; border-color: #17868f; color: #fff; }
.col-toggle.grp-ambient.on:hover { background: #7a7870; border-color: #7a7870; color: #fff; }
.col-toggle.grp-precip.on:hover { background: #a83c5a; border-color: #a83c5a; color: #fff; }
.col-toggle.grp-sky.on:hover { background: #6258b0; border-color: #6258b0; color: #fff; }
.col-toggle.grp-wind.on:hover { background: #a84436; border-color: #a84436; color: #fff; }
.col-toggle.grp-airqual.on:hover { background: #4c7e1a; border-color: #4c7e1a; color: #fff; }
.col-toggle.grp-solar.on:hover { background: #a87824; border-color: #a87824; color: #fff; }
/* ── VENT PILL - group colour tints ─────────────────────────────────────
VentPill fuses with its sibling cs-btn so needs matching group tints.
Only felt and surface groups currently use VentPills. */
.cs-vent.grp-felt { background: rgba(223,243,236,0.50); color: #075c3a; border-color: rgba(7,92,58,0.35); }
.cs-vent.grp-surface { background: rgba(221,234,248,0.50); color: #0b3e72; border-color: rgba(11,62,114,0.30); }
.cs-vent.grp-felt:hover { background: rgba(213,233,226,0.80); color: #075c3a; border-color: rgba(7,92,58,0.55); }
.cs-vent.grp-surface:hover { background: rgba(211,224,238,0.80); color: #0b3e72; border-color: rgba(11,62,114,0.50); }
.cs-vent.grp-felt.on { border-color: #0f9e63; color: #0f9e63; }
.cs-vent.grp-surface.on { border-color: #2672c8; color: #2672c8; }
.cs-vent.grp-felt.on:hover { background: rgba(213,233,226,0.80); color: #0c7d4e; border-color: #0c7d4e; }
.cs-vent.grp-surface.on:hover { background: rgba(211,224,238,0.80); color: #1e5aa0; border-color: #1e5aa0; }
/* ── CUSTOM SELECT - profile card variant ────────────────────────────────
Square 80×80px card with scene image area + label strip at bottom.
Used for the Places / Activities / Work triggers in the profile bar. */
.profile-scroll .cs-wrap {
height: 100px;
}
.cs-btn.profile-card {
width: 100px;
height: 100px;
padding: 0;
position: relative;
flex-direction: column;
align-items: stretch;
overflow: hidden;
border-radius: 3px;
gap: 0;
white-space: normal;
}
.cs-btn.profile-card .cs-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;
}
.cs-btn.profile-card:hover .cs-btn-scene {
opacity: 0.7;
}
.cs-btn.profile-card.on .cs-btn-scene {
opacity: 1;
}
.cs-btn.profile-card .cs-btn-label {
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 24px;
/* Block (not flex) so text-overflow:ellipsis cuts cleanly on the trailing
edge — e.g. "Forest / Wo…" — instead of a flex item clipping both sides.
line-height vertically centres the single line; text-align centres short
labels while long ones ellipsise against the right pad that clears the
arrow. */
display: block;
line-height: 24px;
text-align: center;
font-size: 15px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.05em;
background: rgba(30,18,8,0.52);
color: #fff;
padding: 0 17px 0 6px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
/* When the label overflows it must read left-to-right so the ellipsis lands on
the end ("Forest / Wo…"); centred overflow would clip the start too. */
.cs-btn.profile-card.on .cs-btn-label {
text-align: left;
}
.cs-btn.profile-card .cs-arrow {
position: absolute;
right: 6px;
bottom: 9px;
margin: 0;
color: rgba(255,255,255,0.9);
}
.cs-btn.profile-card.on {
background: transparent;
border-color: #c8922a;
}
.cs-btn.profile-card.on .cs-btn-label {
background: rgba(200,146,42,0.82);
color: #fff;
}
.cs-btn.profile-card.on .cs-arrow {
color: #fff;
}
.cs-btn.profile-card:hover {
background: transparent;
color: inherit;
border-color: #c8922a;
box-shadow: 0 1px 4px rgba(200,146,42,0.25);
}
.cs-btn.profile-card.on:hover {
background: transparent;
}
@media (max-width: 640px) {
.profile-scroll .cs-wrap {
height: 80px;
}
.cs-btn.profile-card {
width: 80px;
height: 80px;
}
.cs-btn.profile-card .cs-arrow {
bottom: 7px;
right: 5px;
}
.cs-btn.profile-card .cs-btn-scene {
font-size: 18px;
}
.cs-btn.profile-card .cs-btn-label {
height: 20px;
line-height: 20px;
font-size: 9px;
}
}
/* Hover overlay — invisible by default, only activated in specific contexts */
.cs-btn-overlay {
display: none;
}
/* The chevron arrow inside the button */
.cs-arrow {
display: inline-block;
width: 6px;
height: 6px;
border-right: 2px solid currentColor;
border-bottom: 2px solid currentColor;
transform: rotate(45deg);
margin-left: 5px;
margin-bottom: 3px;
opacity: 1;
transition: transform 0.15s;
vertical-align: middle;
}
.cs-wrap.open .cs-arrow {
transform: rotate(225deg);
margin-bottom: -1px;
}
/* Grouped left (fused with checkbox pill) */
.cs-btn.grouped-left {
border-right: none;
border-radius: 0;
}
.cs-btn.grouped-left:only-child,
.cs-btn.grouped-left.last-child {
border-right: 1.5px solid #c9b08a;
border-radius: 0;
}
/* The floating dropdown panel. Centred under/over its button and clamped to
the nearest scrollable ancestor's edges via an inline `left` (px) set in
JS (see the useLayoutEffect in CustomSelect) — `left: 0` here is only the
pre-measurement fallback for the very first paint. */
.cs-panel {
position: absolute;
top: calc(100% + 4px);
left: 0;
z-index: 1000;
background: #fffcf2;
border: 1.5px solid #c9b08a;
border-radius: 4px;
box-shadow: 0 4px 16px rgba(30,18,8,0.13);
min-width: 100%;
white-space: nowrap;
/* Safety net only — long lists (SunSoak, Indoors, ...) lay out as two
columns instead (see .cs-panel--cols) so every option is visible at a
glance rather than relying on people to notice a cropped list needs
scrolling. This cap only bites in the rare case even that doesn't fit
the space available (see the JS-computed inline max-height). */
max-height: min(300px, 60vh);
overflow-y: auto;
overflow-x: hidden;
transform-origin: top center;
animation: cs-panel-in 0.15s ease-out;
}
/* Two-column layout for longer option lists (>5 items) — halves the height
needed so lists fit in the available space without scrolling. */
.cs-panel.cs-panel--cols {
column-count: 2;
column-gap: 0;
width: max-content;
max-width: 90vw;
}
.cs-panel.cs-panel--cols .cs-option {
break-inside: avoid;
}
@keyframes cs-panel-in {
from { opacity: 0; transform: translateY(-6px) scaleY(0.92); }
to { opacity: 1; transform: translateY(0) scaleY(1); }
}
/* Flip panel to open upward when it would overflow the bottom of the
viewport — e.g. these selectors sitting inside the profile/config bottom
sheet, which is anchored to the bottom of the screen. Animates in from
the opposite direction so it still reads as growing toward the button. */
.cs-panel.cs-panel--up {
top: auto;
bottom: calc(100% + 4px);
transform-origin: bottom center;
animation: cs-panel-in-up 0.15s ease-out;
}
@keyframes cs-panel-in-up {
from { opacity: 0; transform: translateY(6px) scaleY(0.92); }
to { opacity: 1; transform: translateY(0) scaleY(1); }
}
/* Card-grid panel — wrapping flex grid of scene cards */
.cs-panel.cs-panel--cards {
display: flex;
flex-wrap: wrap;
gap: 5px;
padding: 6px;
min-width: 0;
width: max-content;
max-width: min(320px, 90vw);
max-height: none;
white-space: normal;
overflow: visible;
}
/* Individual card option */
.cs-option.cs-option-card {
display: inline-flex;
flex-direction: column;
align-items: stretch;
width: 68px;
height: 68px;
padding: 0;
overflow: hidden;
border: 1.5px solid #c9b08a;
border-radius: 3px;
background: transparent;
transition: border-color 0.15s, box-shadow 0.15s;
}
.cs-option.cs-option-card:hover {
background: transparent;
color: inherit;
border-color: #c8922a;
box-shadow: 0 1px 5px rgba(200,146,42,0.3);
}
.cs-option.cs-option-card.selected {
border-color: #c8922a;
background: transparent;
color: inherit;
}
.cs-option.cs-option-card.disabled {
opacity: 0.55;
}
.cs-option.cs-option-card.disabled:hover {
border-color: #c9b08a;
box-shadow: none;
}
/* Scene area (gradient + emoji) */
.cs-option-scene {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
font-size: 18px;
line-height: 1;
background-size: cover;
background-position: center;
}
/* Label strip at the bottom */
.cs-option-label {
height: 20px;
display: flex;
align-items: center;
justify-content: center;
font-family: Manrope, sans-serif;
font-size: 15px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.04em;
background: rgba(245,237,214,0.92);
border-top: 1px solid rgba(201,176,138,0.4);
color: #6b4228;
padding: 0 2px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.cs-option.cs-option-card.selected .cs-option-label {
background: #c8922a;
color: #fff;
border-top-color: rgba(0,0,0,0.1);
}
/* Each option row */
.cs-option {
display: block;
padding: 8px 14px;
font-family: Manrope, sans-serif;
font-size: 12px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.05em;
color: #4a3420;
cursor: pointer;
transition: background 0.1s, color 0.1s;
user-select: none;
}
.cs-option:hover {
background: #fef3dc;
color: #1e1208;
}
.cs-option.selected {
color: #c8922a;
font-weight: 600;
background: #fdf8ee;
}
.cs-option.disabled {
opacity: 0.5;
cursor: default;
}
.cs-option.disabled:hover {
background: transparent;
color: #4a3420;
}
/* Hide option divider between show/hide */
.cs-divider {
height: 1px;
background: #e8d8c0;
margin: 2px 0;
}
/* ── CUSTOM CHECKBOX PILL (ventilation / managed) ───────────────────── */
.cs-vent {
display: inline-flex;
align-items: center;
gap: 6px;
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: none;
margin-left: -1px;
padding-left: 11px;
border-radius: 0;
background: #f5edd6;
color: #6b4228;
user-select: none;
transition: background 0.15s, color 0.15s, border-color 0.15s;
white-space: nowrap;
}
.cs-vent:hover {
border-color: #c8922a;
color: #6b4f2a;
background: #fef3dc;
}
.cs-vent.on {
border-color: #c8922a;
color: #c8922a;
background: #f5edd6;
font-weight: 600;
}
.cs-vent.on:hover {
background: #fef3dc;
color: #a06e18;
border-color: #a06e18;
}
/* The little square tick box inside the vent pill */
.cs-checkbox {
display: inline-flex;
align-items: center;
justify-content: center;
width: 13px;
height: 13px;
border: 1.5px solid currentColor;
border-radius: 2px;
flex-shrink: 0;
transition: background 0.12s;
}
.cs-checkbox.checked::after {
content: '';
display: block;
width: 7px;
height: 5px;
border-left: 2px solid currentColor;
border-bottom: 2px solid currentColor;
transform: rotate(-45deg) translateY(-1px);
}
/* ── 9. STATUS & ERROR BANNERS ("Acquiring forecast data…") ────────── */
.utci-status {
padding: 14px 18px;
background: #f0e4c4;
color: #7a5c2a;
font-family: Manrope, sans-serif;
font-size: 11px;
font-weight: 700;
text-align: center;
letter-spacing: 0.07em;
text-transform: uppercase;
border: 1.5px solid #c9b08a;
margin-bottom: 18px;
display: flex;
align-items: center;
justify-content: center;
flex-wrap: wrap;
gap: 10px 14px;
}
.utci-status-msg { text-align: center; }
.utci-status-retry {
flex: 0 0 auto;
padding: 6px 14px;
border: 1.5px solid currentColor;
border-radius: 999px;
background: #fffcf2;
color: inherit;
font-family: inherit;
font-size: 11px;
font-weight: 700;
letter-spacing: 0.07em;
text-transform: uppercase;
cursor: pointer;
transition: background 0.2s, box-shadow 0.2s;
}
.utci-status-retry:hover:not(:disabled) { background: #fef3dc; }
.utci-status-retry:focus-visible {
outline: none;
box-shadow: 0 0 0 3px currentColor;
}
.utci-status-retry:disabled { cursor: default; opacity: 0.55; }
/* acquiring-data popup overlay */
.acquiring-overlay {
position: fixed;
inset: 0;
background: rgba(0, 0, 0, 0.45);
display: flex;
align-items: center;
justify-content: center;
z-index: 9999;
}
.acquiring-popup {
background: #fdf8ee;
border: 1.5px solid #c9b08a;
border-radius: 10px;
padding: 32px 40px;
display: flex;
flex-direction: column;
align-items: center;
gap: 18px;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.22);
}
.acquiring-spinner {
width: 36px;
height: 36px;
border: 3px solid #c9b08a;
border-top-color: #7a5c2a;
border-radius: 50%;
animation: acquiring-spin 0.8s linear infinite;
}
@keyframes acquiring-spin {
to { transform: rotate(360deg); }
}
.acquiring-label {
font-family: Manrope, sans-serif;
font-size: 11px;
font-weight: 700;
letter-spacing: 0.07em;
text-transform: uppercase;
color: #7a5c2a;
}
/* ── Welcome / "How it works" popup ─────────────────────────────────── */
.welcome-overlay {
position: fixed;
inset: 0;
background: rgba(0, 0, 0, 0.45);
display: flex;
align-items: center;
justify-content: center;
z-index: 10000;
padding: 20px;
animation: welcome-fade 0.18s ease-out;
}
@keyframes welcome-fade {
from { opacity: 0; }
to { opacity: 1; }
}
.welcome-card {
position: relative;
background: #fdf8ee;
border: 1.5px solid #c9b08a;
border-radius: 12px;
padding: 30px 34px;
width: 100%;
max-width: 480px;
max-height: 90vh;
overflow-y: auto;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.22);
animation: welcome-pop 0.28s cubic-bezier(0.34, 1.4, 0.64, 1);
}
@keyframes welcome-pop {
from { opacity: 0; transform: scale(0.94) translateY(8px); }
to { opacity: 1; transform: scale(1) translateY(0); }
}
.welcome-close {
position: absolute;
top: 12px;
right: 14px;
background: none;
border: none;
font-size: 26px;
line-height: 1;
color: #b09870;
cursor: pointer;
padding: 2px 6px;
border-radius: 6px;
transition: color 0.15s, background 0.15s;
}
.welcome-close:hover {
color: #1e1208;
background: rgba(176, 152, 112, 0.16);
}
.welcome-head {
text-align: center;
margin-bottom: 22px;
}
.welcome-kicker {
font-family: Manrope, sans-serif;
font-size: 11px;
font-weight: 700;
letter-spacing: 0.1em;
text-transform: uppercase;
color: #c8922a;
margin-bottom: 6px;
}
.welcome-title {
font-family: Fraunces, serif;
font-size: 1.5rem;
font-weight: 600;
color: #1e1208;
margin: 0;
line-height: 1.2;
}
.welcome-intro {
font-family: Manrope, sans-serif;
font-size: 0.9rem;
line-height: 1.5;
color: #4a3420;
text-align: center;
margin: 0 0 22px;
}
.welcome-intro em {
font-style: italic;
color: #6b4f2a;
}
.welcome-intro strong {
color: #c8922a;
}
.welcome-remember {
font-family: Manrope, sans-serif;
font-size: 0.82rem;
line-height: 1.4;
color: #6b4f2a;
text-align: center;
background: #f0e4c4;
border-radius: 8px;
padding: 10px 14px;
margin: 0 0 10px;
}
.welcome-remember strong {
color: #c8922a;
}
.welcome-note {
font-family: Manrope, sans-serif;
font-size: 0.76rem;
line-height: 1.35;
color: #8a7250;
text-align: center;
margin: 0 0 14px;
}
/* Weekly free-tier nudge (WeeklyNudge.js) - reuses the .welcome-* card. */
.nudge-fact {
text-align: center;
margin: 0 0 18px;
}
.nudge-fact-icon {
display: block;
font-size: 2.2rem;
line-height: 1;
margin-bottom: 8px;
}
.nudge-fact .welcome-title {
font-size: 1.25rem;
margin-bottom: 8px;
}
.nudge-fact-body {
font-family: Manrope, sans-serif;
font-size: 0.88rem;
line-height: 1.5;
color: #4a3420;
margin: 0;
}
.nudge-links {
display: flex;
flex-direction: column;
align-items: center;
gap: 10px;
}
.nudge-links a,
.nudge-links button {
font-family: Manrope, sans-serif;
font-weight: 700;
font-size: 10px;
text-transform: uppercase;
letter-spacing: 0.07em;
text-decoration: none;
background: none;
border: none;
padding: 0 0 1px;
cursor: pointer;
color: #c8922a;
border-bottom: 1px solid rgba(200, 146, 42, 0.4);
}
.nudge-links .nudge-dismiss {
color: #b09870;
border-bottom-color: rgba(176, 152, 112, 0.4);
}
.welcome-steps {
list-style: none;
margin: 0 0 22px;
padding: 0;
display: flex;
flex-direction: column;
gap: 18px;
}
.welcome-step {
display: grid;
grid-template-columns: auto auto 1fr;
align-items: start;
gap: 12px;
}
.welcome-step-num {
font-family: Fraunces, serif;
font-size: 0.85rem;
font-weight: 700;
width: 24px;
height: 24px;
border-radius: 50%;
background: #c8922a;
color: #fffcf2;
display: flex;
align-items: center;
justify-content: center;
flex: 0 0 auto;
margin-top: 2px;
}
.welcome-step-icon {
font-size: 1.6rem;
line-height: 1;
margin-top: 1px;
}
.welcome-step-text {
display: flex;
flex-direction: column;
gap: 3px;
}
.welcome-step-title {
font-family: Manrope, sans-serif;
font-weight: 700;
font-size: 0.98rem;
color: #1e1208;
}
.welcome-step-body {
font-family: Manrope, sans-serif;
font-size: 0.88rem;
line-height: 1.45;
color: #4a3420;
}
.welcome-step-body strong {
color: #6b4f2a;
}
.welcome-cta {
display: block;
width: 100%;
font-family: Manrope, sans-serif;
font-weight: 700;
font-size: 0.95rem;
letter-spacing: 0.03em;
color: #fffcf2;
background: #c8922a;
border: none;
border-radius: 9px;
padding: 13px;
cursor: pointer;
transition: background 0.15s, transform 0.1s;
}
.welcome-cta:hover {
background: #b3801f;
}
.welcome-cta:active {
transform: translateY(1px);
}
@media (max-width: 800px) {
.welcome-card {
padding: 26px 20px;
margin-top: 80px; /* Ensure it sits below the fixed header */
}
.welcome-title {
font-size: 1.1rem;
}
.welcome-intro {
font-size: 0.85rem;
}
.welcome-step-text {
font-size: 0.85rem;
}
.welcome-step-title {
font-size: 0.9rem;
}
.welcome-step-body {
font-size: 0.8rem;
}
.welcome-cta {
font-size: 0.85rem;
}
.welcome-step-num {
font-size: 0.75rem;
}
.welcome-steps {
gap: 13px;
margin-bottom: 16px;
}
.welcome-intro {
margin-bottom: 16px;
}
.welcome-remember {
font-size: 0.78rem;
padding: 8px 12px;
}
.welcome-note {
font-size: 0.72rem;
margin-bottom: 12px;
}
.nudge-fact-icon {
font-size: 1.8rem;
}
.nudge-fact .welcome-title {
font-size: 1.05rem;
}
.nudge-fact-body {
font-size: 0.82rem;
}
}
.utci-fetch-time {
text-align: right;
font-size: 0.72rem;
opacity: 0.5;
margin: 0.3rem 0 0;
letter-spacing: 0.03em;
}
.utci-fetch-time.is-stale {
opacity: 0.75;
color: #a06e18;
}
.stale-dot {
font-size: 0.5rem;
color: #c8922a;
vertical-align: middle;
line-height: 1;
}
/* Recent locations — quick-click stacked list beneath the last-update line. */
.utci-recent-locs {
display: flex;
flex-direction: column;
align-items: flex-start;
gap: 3px;
/* Was 0.5rem — the recents now follow the tool row, so they need a clearer
break above them. */
margin-top: 1.25rem;
}
/* header.css sets align-items: center for the same tablet breakpoint, but
since ui.css is @imported after header.css in sunscope.css it wins at
equal specificity - so the tablet override has to live here instead. */
@media (max-width: 960px) {
.utci-recent-locs {
align-items: center;
}
}
.utci-recent-label {
font-family: Manrope, sans-serif;
font-size: 9px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.08em;
color: #b09870;
margin-bottom: 1px;
}
.utci-recent-chip {
display: flex;
align-items: center;
gap: 5px;
width: 100%;
max-width: 220px;
padding: 4px 10px 4px 8px;
font-family: Manrope, sans-serif;
font-size: 0.74rem;
font-weight: 600;
text-align: left;
color: #7a5e2a;
background: #fdf8ee;
border: 1.5px solid #d9c39b;
border-radius: 8px;
cursor: pointer;
transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}
.utci-recent-chip:hover {
background: #f6ecd6;
border-color: #c8922a;
color: #6a4f1e;
}
/* Keep long names on one line with an ellipsis rather than wrapping. */
.utci-recent-name {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.utci-recent-pin {
flex-shrink: 0;
color: #c8922a;
}
/* ── 10. LEGEND (thermal-stress band colours at the bottom) ────────── */
.utci-legend {
margin-top: 22px;
padding: 18px 20px;
background: #fdf8ee;
border: 1.5px solid #c9b08a;
}
.utci-legend-label {
font-family: Manrope, sans-serif;
font-size: 10px;
text-transform: uppercase;
letter-spacing: 0.08em;
color: #7a5c2a;
margin-bottom: 12px;
display: block;
font-weight: 600;
}
.utci-legend-label--secondary {
margin-top: 16px;
padding-top: 16px;
border-top: 1px solid #d4c0a0;
}
.utci-legend-row {
display: flex;
flex-wrap: wrap;
gap: 4px;
}
.utci-legend-item {
display: flex;
flex-direction: column;
align-items: center;
gap: 2px;
padding: 6px 12px;
font-family: Manrope, sans-serif;
flex: 1;
min-width: 110px;
text-align: center;
opacity: 0.9;
}
.utci-legend-item-label {
font-size: 12px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.04em;
}
.utci-legend-item-value {
font-size: 11px;
font-weight: 500;
letter-spacing: 0.02em;
opacity: 0.85;
}
/* ── 11. ABOUT + FOOTER ─────────────────────────────────────────────── */
.utci-bottom-grid {
display: flex;
gap: 24px;
margin-top: 28px;
align-items: stretch;
}
.utci-about {
flex: 2 1 0;
min-width: 0;
padding: 24px 28px;
background: #fdf8ee;
border: 1.5px solid #c9b08a;
}
.utci-reading-box {
flex: 1 1 0;
min-width: 0;
padding: 24px 28px;
background: #fdf8ee;
border: 1.5px solid #c9b08a;
}
.utci-reading-box .utci-about-text {
max-width: none;
margin-left: 0;
margin-right: 0;
}
.utci-about-heading {
font-family: Fraunces, serif;
font-size: 18px;
font-weight: 700;
color: #1e1208;
margin-bottom: 14px;
letter-spacing: -0.01em;
max-width: 860px;
margin-left: auto;
margin-right: auto;
}
.utci-about-text {
font-family: Manrope, sans-serif;
font-size: 14px;
line-height: 1.75;
color: #4a3420;
margin-bottom: 12px;
max-width: 860px;
margin-left: auto;
margin-right: auto;
}
.utci-about-text:last-child {
margin-bottom: 0;
}
.utci-about-text strong {
color: #1e1208;
font-weight: 600;
}
.utci-about-text em {
font-style: italic;
color: #6b4f2a;
}
.utci-about-link {
display: inline-block;
margin-left: 4px;
color: #c8922a;
font-weight: 600;
text-decoration: none;
white-space: nowrap;
}
.utci-about-link:hover {
text-decoration: underline;
}
.utci-footer {
margin-top: 36px;
padding: 10px 0;
font-family: Manrope, sans-serif;
font-size: 10px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.07em;
color: #9a7d5a;
display: flex;
flex-direction: column;
justify-content: center;
line-height: 1.2;
}
/* The "Reading the table." intro snippet */
.utci-footer em {
font-family: Fraunces, serif;
font-style: italic;
text-transform: none;
letter-spacing: 0;
font-size: 14px;
color: #7a5c2a;
}
/* Site-wide footer - matches about and faq pages */
.utci-site-footer {
text-align: center;
padding: 10px 1.5rem;
font-size: 0.82rem;
color: #b09870;
border-top: 1px solid #e0d0a8;
font-family: Manrope, sans-serif;
font-weight: 600;
text-transform: none;
letter-spacing: 0;
line-height: 1.7;
}
.utci-site-footer a {
color: #b09870;
text-decoration: none;
transition: color 0.2s;
}
.utci-site-footer a:hover {
color: #c8922a;
text-decoration: underline;
}
.display-opt {
display: flex;
align-items: center;
gap: 5px;
cursor: pointer;
user-select: none;
}
.display-opt input[type="checkbox"] {
accent-color: var(--c-accent, #e07b2a);
cursor: pointer;
}
/* ── 12. RESPONSIVE (mobile) ───────────────────────────────────────── */
/* On screens narrower than 800px, stack the header vertically and
shrink the dial. Add more rules in this block to tweak mobile
layout further. */
@media (max-width: 800px) {
.utci-bottom-grid {
flex-direction: column;
}
.utci-about {
flex: none;
}
.utci-app {
/* No top padding — the header is in the flow at the very top of the page.
Was 52px, reserving space for the nav back when it was absolutely
positioned over it. Narrowing --app-pad re-aims the header's and the
event note's full-bleed at the same time. */
--app-pad: 10px;
padding: 0 var(--app-pad) 32px;
}
.utci-header {
grid-template-columns: 1fr; /* stack the 3 header columns */
text-align: center;
}
.header-right {
align-items: center;
}
.utci-current-loc {
text-align: center;
}
.utci-recent-locs {
align-items: center;
}
.utci-recent-chip {
max-width: 260px;
}
.utci-search-wrap {
width: 100%;
}
.scope-ring {
width: 225px;
height: 225px;
margin: 0 auto;
}
.scope-env-row {
width: 225px; /* kept in step with the dial width above */
}
/* Halve the hourly-table cell padding on mobile so more columns fit
in the viewport before the horizontal scrollbar kicks in. */
.utci-table th {
padding: 7px 6px;
}
.utci-table td {
padding: 5px 6px;
}
/* Drop the compass-label text ("N", "NW"...) next to the wind vane on
mobile — the vane arrow alone is enough at small sizes. */
.wind-dir-label {
display: none;
}
}
/* At ≤640px the top nav becomes position:fixed (72px tall, see base.css),
so the app needs top padding to clear it. This must come AFTER the
max-width:800px rule above — which sets padding-top:52px for the tablet
range where the nav is NOT fixed — so it wins the cascade on true mobile. */
@media (max-width: 640px) {
.utci-app {
padding-top: 80px;
}
/* Hide the export panel on phones — no room for it, and the export
actions aren't useful at this size. */
.export-panel {
display: none;
}
}
/* -- CUSTOM SELECT BUTTON - mobile label clipping ----------------------
On narrow screens buttons are fixed ~33% width. The .cs-btn-label span
wraps the text node so ellipsis can work (text-overflow needs a block
context - bare text nodes inside flex containers cannot clip directly).
The cs-arrow is flex-shrink-0 so the chevron always stays visible.
DENSITY-BREAKPOINT - matches the table.css 480px breakpoint.
-------------------------------------------------------------------- */
@media (max-width: 480px) {
.cs-btn {
display: block !important;
position: relative !important;
overflow: hidden;
padding: 7px 6px !important;
white-space: nowrap;
}
.cs-btn-label {
display: block;
width: calc(100% - 15px);
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.cs-btn .cs-arrow {
position: absolute !important;
right: 6px;
top: 50%;
margin: 0;
transform: translateY(-50%) rotate(45deg);
}
/* Profile cards are full-bleed image tiles, not slim label pills — the
block/ellipsis treatment above collapses their flex scene to 0 height
and hides the thumbnail. Restore the column layout for them. */
.cs-btn.profile-card {
display: flex !important;
flex-direction: column;
padding: 0 !important;
}
.cs-btn.profile-card .cs-btn-label {
width: auto; /* span the full width via its left/right pins */
}
.cs-btn.profile-card .cs-arrow {
top: auto;
bottom: 7px;
transform: rotate(45deg); /* pinned bottom-right, not vertically centred */
}
.cs-wrap.open .cs-btn.profile-card .cs-arrow {
transform: rotate(225deg); /* keep the open-state flip */
}
}
/* ════════════════════════════════════════════════════════════════════════
INSIGHT PANELS - Why it feels like this + Today at a glance.
Sits between the header dial and the day tabs.
════════════════════════════════════════════════════════════════════════ */
/* "Why it feels like this" - sits in the header's right column, beside the dial */
.insight-panel--why {
width: 100%;
max-width: 300px;
}
/* "Last update" closes the panel out — a hairline above it keeps it apart
from the contribution rows it follows. */
.insight-panel--why .utci-fetch-time {
text-align: right;
margin-top: 8px;
padding-top: 6px;
border-top: 1px solid #ede4cc;
}
/* Solar model selector inside the Why it feels like panel */
.insight-env-footer {
display: flex;
flex-direction: column;
align-items: stretch;
border-bottom: 1px solid #ede4cc;
padding-bottom: 8px;
margin-bottom: 6px;
gap: 4px;
}
.insight-env-footer-label {
font-family: Manrope, sans-serif;
font-size: 13px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.1em;
color: #b09870;
text-align: center;
}
.insight-env-footer .scope-env-row {
width: 100%;
border-top: none;
padding: 0;
align-items: stretch;
}
.insight-env-footer .scope-env-label {
font-family: Manrope, sans-serif;
font-size: 15px;
color: #4a3420;
}
.insight-env-footer .cs-wrap,
.insight-env-footer .cs-btn {
width: 100%;
}
.insight-env-footer .cs-btn {
justify-content: center;
position: relative;
isolation: isolate;
border-radius: 4px;
}
.insight-env-footer .cs-btn .cs-btn-label { font-size: 15px; }
.insight-env-footer .cs-btn .cs-btn-overlay {
display: block;
position: absolute;
inset: 0;
border-radius: inherit;
background: #c8922a;
opacity: 0;
transition: opacity 0.35s ease;
pointer-events: none;
z-index: 0;
}
.insight-env-footer .cs-arrow {
position: absolute;
right: 12px;
z-index: 1;
}
/* Hourly table paired with the "Today at a glance" rail on its right */
.table-with-rail {
display: grid;
grid-template-columns: minmax(0, 1fr) auto;
gap: 16px;
align-items: start;
}
/* Left column: the columns-toggle bar stacked above the table, both
sharing the table's width so the rail can top-align with the toggles. */
.table-main {
min-width: 0;
}
.glance-rail {
width: 240px;
position: sticky;
top: 16px;
}
/* At ≥1024px the profile row + hourly table header both go sticky and pin
to the top of the viewport (see .active-profile-row / .utci-thead-sticky
in table.css, z-index 11 and 5). Left at top:16px the rail's sticky box
scrolls up underneath that stack and gets hidden behind it once it hits
the header height (~104px). Push the rail's stick point below both bars
instead so it settles under them rather than being covered. */
@media (min-width: 1024px) {
.glance-rail {
top: 63px;
}
}
.insight-panel--glance {
width: 100%;
}
/* "The Week Ahead" — sits under "At a glance" in the rail. Separate panel
because it describes the whole forecast range, not the selected day, and
putting a week-scoped line inside a day-scoped box reads as an error. */
.insight-panel--week {
width: 100%;
margin-top: 10px;
}
/* Week rows carry a score bar, so they are a two-line grid rather than the
single flex line the glance rows use: day and window on top, bar beneath.
Day and window read as one sentence - "Sun 30 : all day" - so they sit
together at the left rather than being pushed to opposite edges, where the
gap between them made two short phrases look like two columns of data. */
.insight-panel--week .insight-row {
display: grid;
grid-template-columns: 20px auto minmax(0, 1fr);
grid-template-areas:
"icon label value"
"icon score score";
column-gap: 8px;
row-gap: 4px;
align-items: center;
}
.insight-panel--week .insight-icon { grid-area: icon; }
.insight-panel--week .insight-label { grid-area: label; flex: none; }
.insight-panel--week .insight-value {
grid-area: value;
text-align: left;
flex-shrink: 1;
min-width: 0;
}
/* The separator is drawn, not written into the string, so the value stays a
plain window ("all day") everywhere else it is used. */
.insight-panel--week .insight-value::before {
content: ': ';
color: #8a8375;
font-weight: 400;
}
/* The washout row - no day qualified, so there is no day name and no score,
just a sentence. Forcing it through the day-and-window layout squeezed that
sentence into the narrow value column and stranded the colon on a line of
its own, so it gets the full width and drops the separator. Specificity is
raised past the rail rules below deliberately: this row stacks at every
width. */
.insight-panel--week .insight-row.insight-row--week-note {
grid-template-columns: 20px minmax(0, 1fr);
grid-template-areas:
"icon label"
"icon value";
align-items: start;
row-gap: 2px;
}
.insight-panel--week .insight-row--week-note .insight-icon { padding-top: 2px; }
.insight-panel--week .insight-row--week-note .insight-value {
font-family: Manrope, sans-serif;
font-weight: 500;
white-space: normal;
}
.insight-panel--week .insight-row--week-note .insight-value::before { content: none; }
/* How good the day is out of 100 — the bar does the comparing, the number
settles close calls. */
.week-score {
grid-area: score;
display: flex;
align-items: center;
gap: 7px;
}
.week-score__track {
flex: 1;
height: 5px;
border-radius: 3px;
background: #ede4cc;
overflow: hidden;
}
/* Colour is set inline per row - it tracks the score itself (red at 0 through
amber to green at 100), so it can't live in a static rule. */
.week-score__fill {
display: block;
height: 100%;
border-radius: 3px;
}
.week-score__pct {
font-family: JetBrains Mono, monospace;
font-size: 11px;
color: #8a8375;
flex-shrink: 0;
}
/* ── Pro: Export day data ──────────────────────────────────────────────── */
.export-panel {
margin-top: 10px;
background: #fffcf2;
border: 1px solid #c9b08a;
border-radius: 4px;
padding: 12px 14px;
}
.export-day-btn {
display: flex;
align-items: center;
gap: 7px;
width: 100%;
padding: 8px 12px;
background: linear-gradient(135deg, #c8922a 0%, #a06e18 100%);
color: #fffcf2;
border: none;
border-radius: 4px;
font-family: Manrope, sans-serif;
font-size: 13px;
font-weight: 600;
cursor: pointer;
letter-spacing: 0.02em;
transition: opacity 0.15s;
}
.export-day-btn:hover {
opacity: 0.88;
}
.export-day-btn:active {
opacity: 0.75;
}
.export-day-btn--locked {
background: linear-gradient(135deg, #c0b090 0%, #9a8060 100%);
cursor: pointer;
opacity: 0.75;
}
.export-day-btn--locked:hover {
opacity: 0.90;
}
.export-day-btn__icon {
font-size: 15px;
line-height: 1;
}
.export-day-hint {
margin-top: 7px;
font-family: Manrope, sans-serif;
font-size: 10px;
color: #9a7d5a;
text-align: center;
letter-spacing: 0.03em;
}
.insight-panel {
background: #fffcf2;
border: 1px solid #c9b08a;
border-radius: 4px;
padding: 12px 16px;
}
/* Section heading - "WHY IT FEELS" */
.insight-panel-title {
font-family: Manrope, sans-serif;
font-size: 13px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.1em;
color: #b09870;
margin-bottom: 10px;
display: flex;
align-items: center;
justify-content: center;
gap: 7px;
}
/* Sits under the panel title to say what the listed days are being judged on
- the rows themselves are just dates and windows. */
.insight-panel-sub {
font-family: Manrope, sans-serif;
font-size: 12px;
color: #8a8375;
text-align: center;
margin: -6px 0 10px;
}
.insight-thermal-cat {
display: inline-block;
padding: 2px 7px;
border-radius: 3px;
font-size: 13px;
font-weight: 700;
letter-spacing: 0.06em;
text-transform: uppercase;
line-height: 1.5;
}
/* Each factor row */
.insight-row {
display: flex;
align-items: center;
gap: 8px;
padding: 5px 0;
border-bottom: 1px solid #ede4cc;
font-family: Manrope, sans-serif;
font-size: 15px;
}
.insight-row:last-child {
border-bottom: none;
padding-bottom: 0;
}
/* Group-tinted rows remove the divider border since the background pill
provides the visual separation. */
.insight-row--felt,
.insight-row--surface,
.insight-row--ambient,
.insight-row--precip,
.insight-row--sky,
.insight-row--wind,
.insight-row--airqual,
.insight-row--solar {
border-bottom: none;
}
.insight-icon {
width: 20px;
text-align: center;
flex-shrink: 0;
font-size: 14px;
line-height: 1;
}
.insight-label {
flex: 1;
color: #4a3420;
font-size: 15px;
display: flex;
flex-direction: column;
gap: 3px;
}
.insight-bar-track {
height: 4px;
background: rgba(0, 0, 0, 0.08);
border-radius: 2px;
overflow: hidden;
}
.insight-bar {
display: block;
height: 100%;
border-radius: 2px;
transition: width 0.35s ease;
}
.bar-pos { background: #c8522a; }
.bar-neg { background: #3a78a8; }
/* Delta values for "Why it feels like this" */
.insight-delta {
font-family: JetBrains Mono, monospace;
font-size: 15px;
font-weight: 600;
min-width: 44px;
text-align: right;
flex-shrink: 0;
}
.delta-pos {
color: #c8522a; /* warm orange-red - heat contribution */
}
.delta-neg {
color: #3a78a8; /* cool blue - cooling contribution */
}
.delta-base {
color: #4a3420; /* neutral — absolute air temperature, not a delta */
}
.insight-row--base {
opacity: 0.75;
border-bottom: 1px dashed rgba(74,52,32,0.2);
margin-bottom: 2px;
}
/* Values for "Today at a glance" */
.insight-value {
font-family: JetBrains Mono, monospace;
font-size: 15px;
font-weight: 600;
color: #4a3420;
text-align: right;
flex-shrink: 0;
white-space: pre-line; /* honour \n so multi-range windows stack one per line */
}
/* Secondary figure inside a value — currently the day's peak alongside the
climate anomaly. Inline where there is width; on its own line in the 240px
desktop rail, so the two numbers break deliberately rather than wherever
the text happens to run out of room. Nested inside .insight-value rather
than given its own grid area so rows without a sub keep their layout. */
.insight-sub {
font-weight: 500;
opacity: 0.72;
}
.insight-sub::before { content: ' '; }
/* Alert state - draws attention without being aggressive */
.insight-row--alert .insight-value {
color: #b84020;
}
.insight-row--alert .insight-label {
color: #1e1208;
font-weight: 700;
}
/* Group-tinted backgrounds for insight rows — very light shade matching
the column group colour so items feel categorised at a glance. */
.insight-row--felt { background: rgba(223,243,236,0.50); margin: 0 -10px; padding: 5px 10px; border-radius: 6px; }
.insight-row--surface { background: rgba(221,234,248,0.50); margin: 0 -10px; padding: 5px 10px; border-radius: 6px; }
.insight-row--ambient { background: rgba(236,234,227,0.50); margin: 0 -10px; padding: 5px 10px; border-radius: 6px; }
.insight-row--precip { background: rgba(247,228,238,0.50); margin: 0 -10px; padding: 5px 10px; border-radius: 6px; }
.insight-row--sky { background: rgba(234,232,252,0.50); margin: 0 -10px; padding: 5px 10px; border-radius: 6px; }
.insight-row--wind { background: rgba(250,230,224,0.50); margin: 0 -10px; padding: 5px 10px; border-radius: 6px; }
.insight-row--airqual { background: rgba(229,240,216,0.50); margin: 0 -10px; padding: 5px 10px; border-radius: 6px; }
.insight-row--solar { background: rgba(250,234,204,0.50); margin: 0 -10px; padding: 5px 10px; border-radius: 6px; }
/* ── Wide screens - the rail is narrow (240px), so stack each value
beneath its label instead of letting long values overflow sideways.
Mobile keeps the inline label/value layout (plenty of width there). */
@media (min-width: 901px) {
/* Glance rail on the left, hourly table on the right */
.table-with-rail {
grid-template-columns: auto minmax(0, 1fr);
}
.glance-rail { grid-column: 1; grid-row: 1; }
.table-main { grid-column: 2; grid-row: 1; }
.insight-panel--glance .insight-row,
.insight-panel--week .insight-row {
display: grid;
grid-template-columns: 20px 1fr;
grid-template-areas:
"icon label"
"icon value";
column-gap: 8px;
row-gap: 1px;
align-items: start;
}
/* The rail is only 240px wide, but "Sun 30 : all day" still fits on one
line, so the week rows keep day and window together and give the score
bar the second line - unlike the glance rows, which stack. */
.insight-panel--week .insight-row {
grid-template-columns: 20px auto minmax(0, 1fr);
grid-template-areas:
"icon label value"
"icon score score";
row-gap: 3px;
align-items: center;
}
.insight-panel--week .insight-label,
.insight-panel--week .insight-value {
font-size: 14px;
}
.insight-panel--glance .insight-icon,
.insight-panel--week .insight-icon {
grid-area: icon;
padding-top: 1px;
}
.insight-panel--glance .insight-label,
.insight-panel--week .insight-label {
grid-area: label;
}
.insight-panel--glance .insight-value,
.insight-panel--week .insight-value {
grid-area: value;
text-align: left; /* value sits left-aligned under its label */
}
/* Rail is only 240px — the secondary figure takes its own line. */
.insight-panel--glance .insight-sub {
display: block;
}
.insight-panel--glance .insight-sub::before { content: none; }
}
/* ── Narrow screens - drop the rail below the table ─────────────────── */
@media (max-width: 900px) {
.table-with-rail {
grid-template-columns: 1fr;
}
.glance-rail {
width: 100%;
position: static;
order: -1; /* show the summary above the filters + table */
}
}