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

741 lines
21 KiB
CSS

/* ════════════════════════════════════════════════════════════════════════
header.css — Page header: title wordmark, UTCI dial, and search box.
════════════════════════════════════════════════════════════════════════ */
/* ── 4. HEADER (title + dial + search, three-column grid) ──────────── */
.utci-header {
display: grid;
grid-template-columns: 1fr auto 1fr; /* left | dial | why */
grid-template-areas: "hleft dial hright";
column-gap: 32px;
align-items: stretch;
padding-bottom: 6px;
margin-bottom: 6px;
}
.header-left { grid-area: hleft; }
.scope-col { grid-area: dial; }
.header-right { grid-area: hright; }
/* Left column — the location line and its search overlay. The wordmark and
tagline that used to head this stack now live in the site header, so what is
left hangs from the top of the row, level with the top of the dial. */
.header-left {
display: flex;
flex-direction: column;
align-items: flex-start;
justify-content: flex-start;
}
/* Wraps the location line + the reveal-on-demand search overlay so the
search can position itself directly over the location to save space. */
.utci-loc-search {
position: relative;
/* Was 18px, clearing the tagline above it. It leads the column now. */
margin-top: 0;
width: 380px;
max-width: 100%;
}
/* Right column — now hosts the "Why it feels like this" panel,
sitting close to the dial it explains. */
.header-right {
display: flex;
flex-direction: column;
align-items: flex-start;
justify-content: flex-start; /* level with the top of the dial */
}
/* The wordmark and tagline that used to head this column now live in the
site header (.nav-logo in base.css) — see the header there. */
/* "↳ Location, Somewhere" + the magnifier that reveals the search */
.utci-current-loc {
font-family: Fraunces, serif;
font-style: italic;
font-weight: 800;
font-size: 18px;
margin-top: 0;
margin-bottom: 0;
color: #1e1208;
text-align: left;
display: flex;
align-items: center;
gap: 8px;
flex-wrap: wrap;
}
/* The location name doubles as a search trigger — styled to read as plain
text but with a subtle hover cue so it's discoverable. */
.utci-loc-name {
flex: 0 1 auto;
font: inherit;
color: inherit;
padding: 0;
border: none;
background: none;
cursor: pointer;
text-align: left;
display: inline-flex;
align-items: baseline;
gap: 5px;
border-bottom: 1px dashed transparent;
transition: color 0.2s, border-color 0.2s;
}
/* Map pin sits just ahead of the location name; nudge it onto the text
baseline and tint it brass so it reads as a location marker. */
.utci-loc-pin {
flex: 0 0 auto;
align-self: center;
position: relative;
top: 1px;
color: #c8922a;
}
.utci-loc-name:hover {
color: #c8922a;
border-bottom-color: #c8922a80;
}
.utci-loc-name:focus-visible {
outline: none;
color: #c8922a;
border-bottom-color: #c8922a;
}
/* Small brass magnifying-glass button sitting beside the location name */
.utci-search-toggle {
flex: 0 0 auto;
display: inline-flex;
align-items: center;
justify-content: center;
width: 28px;
height: 28px;
padding: 0;
border: 1.5px solid #c9b08a;
border-radius: 999px;
background: #fffcf2;
color: #9a7a3a;
cursor: pointer;
transition: color 0.2s, border-color 0.2s, background 0.2s, box-shadow 0.2s;
}
.utci-search-toggle:hover {
color: #c8922a;
border-color: #c8922a;
background: #fef3dc;
}
.utci-search-toggle:focus-visible {
outline: none;
border-color: #c8922a;
box-shadow: 0 0 0 3px #c8922a24;
}
.utci-search-toggle[aria-expanded="true"] {
color: #c8922a;
background: #fef3dc;
border-color: #c8922a;
}
/* "Use my location" and "Share" - same brass pill as the magnifier beside them */
.utci-loc-action {
flex: 0 0 auto;
display: inline-flex;
align-items: center;
justify-content: center;
width: 28px;
height: 28px;
padding: 0;
border: 1.5px solid #c9b08a;
border-radius: 999px;
background: #fffcf2;
color: #9a7a3a;
cursor: pointer;
text-decoration: none;
transition: color 0.2s, border-color 0.2s, background 0.2s, box-shadow 0.2s;
}
.utci-loc-action:hover:not(:disabled) {
color: #c8922a;
border-color: #c8922a;
background: #fef3dc;
}
.utci-loc-action:focus-visible {
outline: none;
border-color: #c8922a;
box-shadow: 0 0 0 3px #c8922a24;
}
.utci-loc-action:disabled { cursor: default; opacity: 0.6; }
/* Slow pulse while the browser is resolving the fix */
.utci-loc-action.is-busy svg { animation: loc-seek 1.1s ease-in-out infinite; }
@keyframes loc-seek {
0%, 100% { opacity: 1; }
50% { opacity: 0.35; }
}
@media (prefers-reduced-motion: reduce) {
.utci-loc-action.is-busy svg { animation: none; opacity: 0.55; }
}
/* Tool row under the location line — the magnifier, locate, share and journal
buttons sit on their own row now that the header has the space, each with a
small caption so the icons don't have to carry the meaning alone. */
.utci-loc-tools {
display: flex;
flex-wrap: wrap;
align-items: flex-start;
gap: 16px;
margin-top: 10px;
}
.utci-loc-tool {
display: flex;
flex-direction: column;
align-items: center;
gap: 4px;
}
.utci-loc-tool-label {
font-family: Manrope, sans-serif;
font-style: normal;
font-weight: 600;
font-size: 9.5px;
letter-spacing: 0.08em;
text-transform: uppercase;
color: #a08c62;
white-space: nowrap;
transition: color 0.2s;
}
/* Light the caption up with its button so the pair reads as one control */
.utci-loc-tool:hover .utci-loc-tool-label { color: #c8922a; }
/* Transient note under the location row: "Link copied", permission errors */
.utci-loc-note {
display: flex;
align-items: center;
gap: 6px;
margin-top: 6px;
font-family: Manrope, sans-serif;
font-size: 11px;
letter-spacing: 0.04em;
color: #7a6a46;
}
.utci-loc-note.is-warn { color: #a8603a; }
.utci-loc-note-x {
border: 0;
background: none;
padding: 0 2px;
font-size: 14px;
line-height: 1;
color: inherit;
cursor: pointer;
opacity: 0.7;
}
.utci-loc-note-x:hover { opacity: 1; }
/* The big UTCI dial in the middle of the header.
Change width/height to resize it. */
.scope-ring {
width: 270px;
height: 270px;
display: block;
}
/* Wraps the dial SVG + the precip FX canvas so the canvas can overlay the
lens. Sizes itself to the SVG (220px, or 250px on mobile). */
.scope-wrap {
position: relative;
display: inline-block;
line-height: 0;
}
/* Animated rain/snow/lightning layer, clipped to the lens circle and sitting
on top of the glass. Inset to 95% to match the lens radius (r=95 of 100). */
.scope-fx {
position: absolute;
top: 50%;
left: 50%;
width: 95%;
height: 95%;
transform: translate(-50%, -50%);
border-radius: 50%;
pointer-events: none;
}
/* Cloud sprite strips drift horizontally inside the lens; sprites are
duplicated +200 user-units so the wrap is seamless. */
@keyframes scopeCloudDrift {
from { transform: translateX(0); }
to { transform: translateX(var(--drift, -200px)); }
}
.scope-cloud-layer {
animation: scopeCloudDrift linear infinite;
will-change: transform;
}
@media (prefers-reduced-motion: reduce) {
.scope-cloud-layer { animation: none; }
}
.scope-col {
display: flex;
flex-direction: column;
align-items: center;
/* Top-anchored so the dial defines the row's top edge and the location and
Solar model columns beside it start on the same line. */
justify-content: flex-start;
gap: 8px;
}
/* Outer wrapper — matches scope dial width at every breakpoint */
.scope-daycycle-wrap {
display: flex;
flex-direction: column;
gap: 4px;
width: 100%;
max-width: 270px; /* matches .scope-ring desktop size */
padding-bottom: 32px; /* compensates for the extra Air temp row in the Why It Feels panel */
}
/* Unified pill: icon on left, bar fills the right */
.scope-daycycle-pill {
display: flex;
align-items: center;
gap: 8px;
padding: 4px 7px 4px 10px;
background: rgba(40, 28, 10, 0.55);
border: 1px solid rgba(200, 146, 42, 0.5);
border-radius: 999px;
box-sizing: border-box;
width: 100%;
}
/* Play/stop button — text + icon, no own background (pill provides it) */
.scope-play {
flex-shrink: 0;
background: none;
border: none;
color: rgba(220, 195, 145, 0.8);
font-family: 'Manrope', sans-serif;
font-size: 11px;
font-weight: 700;
letter-spacing: 0.4px;
cursor: pointer;
padding: 0;
line-height: 1;
white-space: nowrap;
display: flex;
align-items: center;
gap: 5px;
transition: color 0.15s;
}
.scope-play:hover { color: #f5edd6; }
.scope-play.is-playing { color: #ffd98a; }
.scope-play.is-playing:hover { color: #ffe6b0; }
.scope-play-icon { font-size: 9px; line-height: 1; }
/* Fixed-width label prevents the bar from shifting when text swaps */
.scope-play-label {
display: inline-block;
min-width: 64px;
font-family: 'JetBrains Mono', ui-monospace, monospace;
font-variant-numeric: tabular-nums;
}
/* Kill all transitions while the user is scrubbing the timeline */
body.tl-scrubbing * { transition: none !important; }
/* Timeline — fills the row beside the play icon, ticks sit below the track */
.day-timeline {
flex: 1;
min-width: 0;
display: flex;
flex-direction: column;
gap: 4px;
user-select: none;
-webkit-user-select: none;
}
.day-timeline-track {
position: relative;
height: 16px;
border-radius: 999px;
border: 1px solid rgba(0, 0, 0, 0.35);
box-shadow: inset 0 1px 4px rgba(0, 0, 0, 0.6);
cursor: pointer;
overflow: visible;
}
.day-timeline-thumb {
position: absolute;
top: -5px;
width: 3px;
height: 26px;
background: #fff8e8;
border-radius: 2px;
transform: translateX(-50%);
pointer-events: none;
box-shadow: 0 0 6px rgba(255, 230, 150, 0.8), 0 0 0 1px rgba(0,0,0,0.3);
}
.day-timeline-label {
position: absolute;
bottom: calc(100% + 5px);
left: 50%;
transform: translateX(-50%);
font-family: 'JetBrains Mono', ui-monospace, monospace;
font-size: 9px;
font-weight: 700;
font-variant-numeric: tabular-nums;
color: #ffd98a;
white-space: nowrap;
pointer-events: none;
background: rgba(20, 12, 4, 0.75);
padding: 2px 5px;
border-radius: 4px;
border: 1px solid rgba(200, 146, 42, 0.4);
}
.day-timeline-sun-marker {
position: absolute;
top: -13px;
font-size: 9px;
color: #ffd98a;
transform: translateX(-50%);
pointer-events: none;
line-height: 1;
text-shadow: 0 0 4px rgba(0,0,0,0.8);
}
.day-timeline-ticks {
display: flex;
justify-content: space-between;
/* indent to align with bar start (icon ≈ 10px + gap 8px + pill padding 7px) */
padding: 0 8px 0 27px;
}
.day-timeline-tick {
font-family: 'JetBrains Mono', ui-monospace, monospace;
font-size: 9px;
color: rgba(220, 200, 160, 0.65);
font-variant-numeric: tabular-nums;
line-height: 1;
}
/* The environment selector sits just below the dial, centred under it.
Kept out of .scope-col so the dial alone defines that column's height
and stays vertically centred against the side columns. */
.scope-env-bar {
display: flex;
justify-content: center;
margin-top: 2px;
margin-bottom: 4px;
}
.scope-env-row {
display: flex;
flex-direction: column;
align-items: center;
gap: 2px;
border-top: 1px solid #c9b08a;
width: 270px; /* match desktop/tablet dial width */
}
.scope-env-label {
font-family: Manrope, sans-serif;
font-size: 15px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.1em;
color: #b09870;
}
.scope-env-row .cs-wrap,
.scope-env-row .cs-btn {
width: 100%;
}
.scope-env-row .cs-btn {
justify-content: center;
position: relative;
isolation: isolate;
border-radius: 999px;
box-shadow: inset 0 1px 3px rgba(255,255,255,0.30), 0 2px 8px rgba(0,0,0,0.18);
transition: color 0.35s ease;
}
.scope-env-row .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;
}
.scope-env-row .cs-btn.on:hover .cs-btn-overlay {
opacity: 1;
}
/* Label stays above the overlay */
.scope-env-row .cs-btn .cs-btn-label {
position: relative;
z-index: 1;
font-family: Manrope, sans-serif;
font-size: 15px;
font-weight: 600;
}
/* Arrow pinned right, above the overlay */
.scope-env-row .cs-arrow {
position: absolute;
right: 12px;
z-index: 1;
}
.scope-env-row .cs-panel,
.scope-env-row .cs-option,
.insight-env-footer .cs-panel,
.insight-env-footer .cs-option {
text-align: center;
}
.insight-env-footer .cs-btn.on:hover .cs-btn-overlay { opacity: 1; }
.insight-env-footer .cs-btn .cs-btn-label { position: relative; z-index: 1; }
/* Per-environment gradient themes — !important keeps the gradient fixed
under the brass hover overlay (ui.css :hover rules load later). */
.scope-env-row[data-env="open"] .cs-btn.on { background: linear-gradient(135deg, #5a8a28 0%, #b8d860 100%) !important; border-color: #4a7818 !important; color: #fff; }
.scope-env-row[data-env="forest"] .cs-btn.on { background: linear-gradient(135deg, #1b5e3b 0%, #57bf8a 100%) !important; border-color: #1b5e3b !important; color: #fff; }
.scope-env-row[data-env="alpine"] .cs-btn.on { background: linear-gradient(135deg, #a8cfe8 0%, #dff0fa 100%) !important; border-color: #6aaedd !important; color: #1a3a58; }
.scope-env-row[data-env="beach"] .cs-btn.on { background: linear-gradient(135deg, #2a8fc8 0%, #e8d87a 100%) !important; border-color: #1e78b0 !important; color: #fff; }
.scope-env-row[data-env="river"] .cs-btn.on { background: linear-gradient(135deg, #2e6e5e 0%, #78c4a8 100%) !important; border-color: #2e6e5e !important; color: #fff; }
.scope-env-row[data-env="desert"] .cs-btn.on { background: linear-gradient(135deg, #b86820 0%, #e8c458 100%) !important; border-color: #a05818 !important; color: #fff; }
.scope-env-row[data-env="openwater"] .cs-btn.on { background: linear-gradient(135deg, #0c4878 0%, #2898d8 100%) !important; border-color: #0c4878 !important; color: #fff; }
.scope-env-row[data-env="urban"] .cs-btn.on { background: linear-gradient(135deg, #4a5568 0%, #a89880 100%) !important; border-color: #3a4455 !important; color: #fff; }
/* Duplicate gradient rules for the Solar model button inside the insight panel */
.insight-env-footer[data-env="open"] .cs-btn.on { background: linear-gradient(135deg, #5a8a28 0%, #b8d860 100%) !important; border-color: #4a7818 !important; color: #fff; }
.insight-env-footer[data-env="forest"] .cs-btn.on { background: linear-gradient(135deg, #1b5e3b 0%, #57bf8a 100%) !important; border-color: #1b5e3b !important; color: #fff; }
.insight-env-footer[data-env="alpine"] .cs-btn.on { background: linear-gradient(135deg, #a8cfe8 0%, #dff0fa 100%) !important; border-color: #6aaedd !important; color: #1a3a58; }
.insight-env-footer[data-env="beach"] .cs-btn.on { background: linear-gradient(135deg, #2a8fc8 0%, #e8d87a 100%) !important; border-color: #1e78b0 !important; color: #fff; }
.insight-env-footer[data-env="river"] .cs-btn.on { background: linear-gradient(135deg, #2e6e5e 0%, #78c4a8 100%) !important; border-color: #2e6e5e !important; color: #fff; }
.insight-env-footer[data-env="desert"] .cs-btn.on { background: linear-gradient(135deg, #b86820 0%, #e8c458 100%) !important; border-color: #a05818 !important; color: #fff; }
.insight-env-footer[data-env="openwater"] .cs-btn.on { background: linear-gradient(135deg, #0c4878 0%, #2898d8 100%) !important; border-color: #0c4878 !important; color: #fff; }
.insight-env-footer[data-env="urban"] .cs-btn.on { background: linear-gradient(135deg, #4a5568 0%, #a89880 100%) !important; border-color: #3a4455 !important; color: #fff; }
/* On hover the brass overlay covers the interior — force white text for contrast */
.scope-env-row .cs-btn.on:hover { color: #fff; }
.insight-env-footer .cs-btn.on:hover { color: #fff; }
/* The search box on the right of the header */
.utci-search-wrap {
position: relative;
width: 300px;
}
/* When revealed, the search floats over the location line rather than
occupying its own vertical slot — keeps the header compact. */
.utci-search-overlay {
position: absolute;
top: -9px;
left: 0;
width: 100%;
z-index: 60;
/* "Eyes opening": unfurl from the top edge while fading in, so the drop
shadow grows with the box instead of flashing in fully-formed. */
transform-origin: center center;
animation: utci-search-open 0.26s cubic-bezier(0.22, 1, 0.36, 1);
}
@keyframes utci-search-open {
from {
opacity: 0;
transform: scaleY(0.05);
}
to {
opacity: 1;
transform: scaleY(1);
}
}
/* Reverse the reveal when dismissing — close from the vertical middle and
fade out rather than vanishing instantly. */
.utci-search-overlay.is-closing {
animation: utci-search-close 0.2s cubic-bezier(0.4, 0, 1, 1) forwards;
}
@keyframes utci-search-close {
from {
opacity: 1;
transform: scaleY(1);
}
to {
opacity: 0;
transform: scaleY(0.05);
}
}
.utci-search-overlay .utci-search {
box-shadow: 0 6px 20px #64461426; /* lift it off the location underneath */
}
.utci-search-label {
font-family: Manrope, sans-serif;
font-size: 10px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.08em;
color: #b09870;
display: block;
margin-bottom: 7px;
}
.utci-search {
width: 100%;
padding: 12px 16px;
border: 1.5px solid #c9b08a;
background: #fffcf2;
font-family: Manrope, sans-serif;
font-size: 14px;
color: #1e1208;
outline: none;
transition: border-color 0.2s, box-shadow 0.2s;
}
.utci-search::placeholder {
color: #c0a880;
}
.utci-search:focus {
border-color: #c8922a;
box-shadow: 0 0 0 3px #c8922a24; /* brass glow when focused */
}
/* The dropdown list of city results */
.utci-results {
position: absolute;
top: 100%;
left: 0;
right: 0;
background: #fffcf2;
border: 1.5px solid #c9b08a;
border-top: none;
max-height: 260px;
overflow-y: auto;
z-index: 50;
box-shadow: 0 8px 24px #6446141f;
}
.utci-result {
padding: 11px 16px;
cursor: pointer;
border-bottom: 1px solid #ede4cc;
font-size: 14px;
transition: background 0.12s;
border-left: 3px solid transparent;
}
.utci-result:hover {
background: #fef3dc;
border-left-color: #c8922a; /* brass marker on hover */
}
/* The "GB · 51.48°, -1.07°" line under each city */
.utci-result-meta {
font-size: 11px;
color: #b09870;
font-family: JetBrains Mono, monospace;
margin-top: 3px;
letter-spacing: 0.06em;
}
.utci-searching {
margin-top: 6px;
padding: 5px 10px;
font-size: 10px;
color: #5a3e1b;
background: #f5edd6;
border-radius: 6px;
font-family: Manrope, sans-serif;
font-weight: 700;
letter-spacing: 0.08em;
text-transform: uppercase;
display: inline-block;
}
/* ── Stacked header layout (mobile + tablet) ─────────────────────────────
The desktop 3-column grid (left | dial | why-panel) needs ~960px of
viewport to fit: the location/search box is 300px, the "Why it feels like"
panel ~300px, plus the 220px dial and gaps. Below that the rigid columns
can't shrink and the why-panel overflows off the right edge, so we stack
everything into one centred column — matching where the glance rail also
drops below the table. */
@media (max-width: 960px) {
.utci-header {
grid-template-columns: 1fr; /* single column — stack title, dial, search */
grid-template-areas: none; /* flow in DOM order: left, dial, selector, why */
gap: 20px;
padding-bottom: 15px;
margin-bottom: 0px;
}
/* Clear the desktop area placement so children stack in DOM order */
.header-left,
.scope-col,
.scope-env-bar,
.header-right {
grid-area: auto;
}
.header-left {
align-items: center; /* centre the wordmark along with everything else */
}
.header-right {
align-items: center; /* centre the "Why it feels like" panel under the dial */
}
}
@media (max-width: 960px) {
.scope-ring {
width: 250px;
height: 250px;
margin: 0 auto;
}
.scope-daycycle-wrap {
max-width: 250px;
}
.scope-env-row {
width: 250px;
}
.utci-loc-search {
width: 100%;
margin-top: 4px; /* tighten gap above location on mobile */
}
.utci-current-loc {
justify-content: center; /* centre name + magnifier on mobile */
text-align: center;
}
.utci-loc-tools {
justify-content: center; /* centre the tool row on mobile */
}
.utci-search-wrap {
width: 100%; /* full-width search box */
}
}