New big and small scope sunset and sunrise simulation New calculations for the day tabs Added missing icons to simple view New record popups Week ahead description popups Camping profile Tweak to some of the indoor tems
848 lines
28 KiB
CSS
848 lines
28 KiB
CSS
/* ── SELF-HOSTED FONTS ───────────────────────────────────────────────── */
|
||
@font-face { font-family: 'Manrope'; font-style: normal; font-weight: 200 800; font-display: swap; src: url('../fonts/manrope-variable.woff2') format('woff2'); }
|
||
@font-face { font-family: 'Fraunces'; font-style: normal; font-weight: 700; font-display: swap; src: url('../fonts/fraunces-700-normal.woff2') format('woff2'); }
|
||
@font-face { font-family: 'Fraunces'; font-style: normal; font-weight: 900; font-display: swap; src: url('../fonts/fraunces-900-normal.woff2') format('woff2'); }
|
||
@font-face { font-family: 'Fraunces'; font-style: italic; font-weight: 300; font-display: swap; src: url('../fonts/fraunces-300-italic.woff2') format('woff2'); }
|
||
@font-face { font-family: 'Fraunces'; font-style: italic; font-weight: 700; font-display: swap; src: url('../fonts/fraunces-700-italic.woff2') format('woff2'); }
|
||
@font-face { font-family: 'JetBrains Mono'; font-style: normal; font-weight: 400; font-display: swap; src: url('../fonts/jetbrains-mono-400.woff2') format('woff2'); }
|
||
@font-face { font-family: 'JetBrains Mono'; font-style: normal; font-weight: 600; font-display: swap; src: url('../fonts/jetbrains-mono-600.woff2') format('woff2'); }
|
||
|
||
/* ════════════════════════════════════════════════════════════════════════
|
||
base.css — Fonts, reset, page shell, and top navigation.
|
||
════════════════════════════════════════════════════════════════════════
|
||
|
||
COLOUR PALETTE (the "warm parchment & brass" theme)
|
||
──────────────────────────────────────────────────────────────────────
|
||
#f5edd6 parchment page background
|
||
#fffcf2 soft cream cards, search box, table
|
||
#fdf8ee warm cream toolbars, legend, about block
|
||
#f0e4c4 pale honey table heading row, priority banner
|
||
#ebdcb4 deep honey site header bar, footer bar, nav drawer
|
||
#fef3dc warm hover buttons on hover
|
||
#fef8ea row hover table row on hover
|
||
#fff8e4 "now" row the currently-active hour
|
||
#1e1208 espresso headings + emphasis
|
||
#4a3420 warm dark body text in the table
|
||
#6b4f2a muted bronze subtle emphasis
|
||
#7a5c2a tagline brown italic intro line
|
||
#9a7d5a soft brown column toggle text
|
||
#b09870 warm grey muted labels
|
||
#c0a880 pale dust night-row text, footer
|
||
#c8922a BRASS brand accent (links, dial, focus)
|
||
#a06e18 deep brass hover state for some links
|
||
#c9b08a warm border panel borders
|
||
#d4c0a0 soft border toolbar/legend borders
|
||
#ede4cc line table row dividers
|
||
|
||
FONTS
|
||
──────────────────────────────────────────────────────────────────────
|
||
Fraunces serif display titles, day labels, hour cell
|
||
Manrope body sans-serif paragraphs, small labels
|
||
JetBrains Mono numeric monospace table data
|
||
════════════════════════════════════════════════════════════════════════ */
|
||
|
||
/* ── 1. FONTS + RESET ───────────────────────────────────────────────── */
|
||
|
||
/* Font loading is handled in index.html via a non-blocking <link rel="preload">
|
||
to avoid render-blocking. The @import has been intentionally removed. */
|
||
|
||
*,
|
||
*:before,
|
||
*:after {
|
||
box-sizing: border-box;
|
||
margin: 0;
|
||
padding: 0;
|
||
}
|
||
|
||
|
||
/* ── 2. PAGE BACKGROUND & SHELL ─────────────────────────────────────── */
|
||
|
||
body {
|
||
background: #f5edd6; /* parchment */
|
||
}
|
||
|
||
.utci-app {
|
||
font-family: Manrope, sans-serif;
|
||
color: #1e1208;
|
||
background: #f5edd6;
|
||
min-height: 100vh;
|
||
/* The side padding, as a variable: the header and the event note both
|
||
full-bleed by cancelling it, and would otherwise each need the number
|
||
restating at every breakpoint that changes it. */
|
||
--app-pad: 36px;
|
||
/* No top padding: .utci-topnav is a real header at the very top of the flow
|
||
now, and supplies its own. Was 52px, reserved for the nav when it was
|
||
absolutely positioned over this space. */
|
||
padding: 0 var(--app-pad) 32px;
|
||
position: relative;
|
||
/* overflow-x: clip (not hidden) — `clip` clips horizontal overflow
|
||
WITHOUT making this a scroll container, so `position: sticky` on
|
||
descendants (table <th>) can still stick relative to the viewport.
|
||
`hidden` would create a containing block that breaks sticky. */
|
||
overflow-x: clip;
|
||
}
|
||
|
||
|
||
/* The centred container that holds everything. */
|
||
.utci-shell {
|
||
position: relative;
|
||
z-index: 1;
|
||
margin: 0 auto;
|
||
}
|
||
|
||
|
||
/* ── 3. SITE HEADER (wordmark left, nav links right) ───────────────── */
|
||
|
||
/* Rendered as <header id="site-nav"> — the same element the static pages
|
||
(about.html et al) use — and it now carries the wordmark and tagline that
|
||
used to be repeated inside .utci-header. It sits FIRST in the flow, at the
|
||
very top of the page, with the event banner beneath it.
|
||
Full-bleed: .utci-app pads its content in by --app-pad a side, so the header
|
||
cancels that with a matching negative margin and pads itself instead — the
|
||
bar's rule reaches both page edges while its contents still line up with
|
||
the content below. */
|
||
.utci-topnav {
|
||
position: relative; /* keeps z-index working without leaving the flow */
|
||
z-index: 100;
|
||
margin: 0 calc(var(--app-pad) * -1) 18px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: flex-end; /* .nav-logo's margin-right:auto splits the row */
|
||
padding: 18px var(--app-pad);
|
||
gap: 28px;
|
||
/* Two shades deeper than the parchment page beneath, so the bar reads as
|
||
chrome rather than as more page — it is the topmost surface, so it sits a
|
||
step below the table heading row (#f0e4c4) rather than matching it.
|
||
The shadow is espresso at low alpha, not black, to stay in the warm family.
|
||
The mobile bar and drawer below repeat these three values. */
|
||
background: #ebdcb4;
|
||
border-bottom: 1px solid #c9b08a;
|
||
box-shadow: 0 3px 8px rgba(30, 18, 8, 0.10);
|
||
}
|
||
|
||
.utci-topnav a {
|
||
font-family: Manrope, sans-serif;
|
||
font-size: 16px;
|
||
font-weight: 700;
|
||
letter-spacing: 0.06em;
|
||
text-transform: uppercase;
|
||
color: #b09870;
|
||
text-decoration: none;
|
||
border-bottom: 1px solid transparent;
|
||
padding-bottom: 2px;
|
||
transition: color 0.2s, border-color 0.2s;
|
||
}
|
||
|
||
.utci-topnav a:hover {
|
||
color: #1e1208;
|
||
border-bottom-color: #1e1208;
|
||
}
|
||
|
||
/* Desktop: nav-links renders inline as part of the header's flex row */
|
||
.utci-topnav .nav-links {
|
||
display: contents; /* participates in the header's flex layout transparently */
|
||
}
|
||
|
||
/* ── About dropdown ─────────────────────────────────────────────────── */
|
||
.utci-topnav .nav-dropdown {
|
||
position: relative;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
}
|
||
/* Invisible bridge so hover doesn't break between toggle and menu */
|
||
.utci-topnav .nav-dropdown::after {
|
||
content: '';
|
||
position: absolute;
|
||
left: 0;
|
||
right: 0;
|
||
top: 100%;
|
||
height: 4px;
|
||
}
|
||
.utci-topnav .nav-dropdown-toggle .caret {
|
||
display: inline-block;
|
||
margin-left: 4px;
|
||
font-size: 0.7em;
|
||
transition: transform 0.2s;
|
||
}
|
||
.utci-topnav .nav-dropdown:hover .nav-dropdown-toggle .caret,
|
||
.utci-topnav .nav-dropdown:focus-within .nav-dropdown-toggle .caret {
|
||
transform: rotate(180deg);
|
||
}
|
||
.utci-topnav .nav-dropdown-menu {
|
||
position: absolute;
|
||
top: calc(100% - 1px);
|
||
left: 50%;
|
||
margin-top: 0;
|
||
background: #fffcf2;
|
||
border: 1px solid #d4c0a0;
|
||
border-radius: 8px;
|
||
box-shadow: 0 8px 24px rgba(100, 70, 20, 0.12);
|
||
display: flex;
|
||
flex-direction: column;
|
||
min-width: 210px;
|
||
padding: 6px;
|
||
opacity: 0;
|
||
visibility: hidden;
|
||
transform: translateX(-50%) translateY(-4px);
|
||
transition: opacity 0.18s ease, transform 0.18s ease, visibility 0.18s ease;
|
||
z-index: 110;
|
||
}
|
||
.utci-topnav .nav-dropdown:hover .nav-dropdown-menu,
|
||
.utci-topnav .nav-dropdown:focus-within .nav-dropdown-menu {
|
||
opacity: 1;
|
||
visibility: visible;
|
||
transform: translateX(-50%) translateY(0);
|
||
}
|
||
/* The Account dropdown sits at the far right of the nav row, so a menu
|
||
centred under it (like About's) would spill past the viewport edge on
|
||
most screen widths. Right-align it to the toggle instead, growing left. */
|
||
.utci-topnav .nav-dropdown--right .nav-dropdown-menu {
|
||
left: auto;
|
||
right: 0;
|
||
transform: translateY(-4px);
|
||
}
|
||
.utci-topnav .nav-dropdown--right.nav-dropdown:hover .nav-dropdown-menu,
|
||
.utci-topnav .nav-dropdown--right.nav-dropdown:focus-within .nav-dropdown-menu {
|
||
transform: translateY(0);
|
||
}
|
||
/* Labels align to the same right edge the menu itself hangs from. */
|
||
.utci-topnav .nav-dropdown--right .nav-dropdown-menu a {
|
||
text-align: right;
|
||
}
|
||
.utci-topnav .nav-dropdown-menu a {
|
||
text-transform: none;
|
||
letter-spacing: normal;
|
||
font-size: 14px;
|
||
font-weight: 600;
|
||
color: #5a3e1a;
|
||
padding: 8px 12px;
|
||
border-radius: 6px;
|
||
border-bottom: none;
|
||
white-space: nowrap;
|
||
}
|
||
.utci-topnav .nav-dropdown-menu a:hover {
|
||
background: #ede4cc;
|
||
color: #1e1208;
|
||
border-bottom: none;
|
||
}
|
||
|
||
/* ── Event note ─────────────────────────────────────────────────────── */
|
||
/* Active cosmic/weather events shown as a strip across the content width,
|
||
directly under the site header. It is IN FLOW — it pushes the page down
|
||
instead of covering anything, which is the whole point of it not being a
|
||
flyout. One event at a time with its full message, cycling with a fade.
|
||
|
||
It used to render ABOVE the nav, which meant repositioning the nav out of
|
||
its absolute placement whenever a note was present. The header owns the top
|
||
of the page now, so the note is simply the first thing under it — on desktop
|
||
and on mobile (where the header is fixed and .utci-app pads clear of it)
|
||
alike, with no override either way. */
|
||
.event-note {
|
||
display: flex;
|
||
align-items: baseline;
|
||
gap: 11px;
|
||
padding: 10px 15px;
|
||
margin-bottom: 14px;
|
||
background: #fdf8ee;
|
||
border: 1.5px solid #c9b08a;
|
||
border-radius: 4px;
|
||
position: relative;
|
||
overflow: hidden;
|
||
animation: event-note-in 0.35s cubic-bezier(0.34, 1.25, 0.64, 1) both;
|
||
}
|
||
|
||
@keyframes event-note-in {
|
||
from { opacity: 0; transform: translateY(-5px); }
|
||
to { opacity: 1; transform: translateY(0); }
|
||
}
|
||
|
||
/* Per-event colour, kept to a hairline so the strip stays parchment —
|
||
same device as .almanac-entry-accent. */
|
||
.event-note-accent {
|
||
position: absolute;
|
||
inset: 0;
|
||
opacity: 0.75;
|
||
pointer-events: none;
|
||
/* One element, drawn as an L: a 1px strip down the left that turns and runs
|
||
along the bottom. The note's own overflow: hidden rounds the corner off
|
||
with the rest of the box. */
|
||
clip-path: polygon(
|
||
0 0,
|
||
1px 0,
|
||
1px calc(100% - 1px),
|
||
100% calc(100% - 1px),
|
||
100% 100%,
|
||
0 100%
|
||
);
|
||
}
|
||
|
||
/* Safety-relevant weather (heat, frost, storm, wind, wet) — brass emphasis.
|
||
This is the fallback: when the event carries a weather tint, app.js
|
||
overrides background/border inline with the matching day-tab colour and
|
||
adds .is-tinted (below). */
|
||
.event-note.is-priority {
|
||
background: #f0e4c4;
|
||
border-color: #c8922a;
|
||
}
|
||
|
||
/* Tinted warning banner — the hue now carries the "this is a warning" signal,
|
||
so the copy drops the brass accents for neutral dark tones that stay
|
||
readable on any of the palette's hues (orange, blue, grey). */
|
||
.event-note.is-tinted .event-note-msg {
|
||
color: #3f3222;
|
||
}
|
||
.event-note.is-tinted.is-priority .event-note-dates {
|
||
color: #56452c;
|
||
}
|
||
.event-note.is-tinted .event-note-dot {
|
||
background: rgba(0, 0, 0, 0.18);
|
||
}
|
||
.event-note.is-tinted .event-note-dot:hover {
|
||
background: rgba(0, 0, 0, 0.34);
|
||
}
|
||
.event-note.is-tinted .event-note-dot.active {
|
||
background: rgba(0, 0, 0, 0.55);
|
||
}
|
||
|
||
/* Slide stack. Every active event is rendered and every slide is placed in the
|
||
same single grid cell, so the strip's height is set by the TALLEST slide and
|
||
stays put as the rotation cycles — a one-line event followed by a message
|
||
that wraps to two lines no longer grows the banner and shunts the page. */
|
||
.event-note-stack {
|
||
display: grid;
|
||
grid-template-columns: minmax(0, 1fr);
|
||
align-items: start;
|
||
flex: 1;
|
||
min-width: 0;
|
||
}
|
||
|
||
.event-note-slide {
|
||
grid-area: 1 / 1; /* stack all slides on top of each other */
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 2px;
|
||
min-width: 0;
|
||
opacity: 0; /* only .is-active is visible */
|
||
pointer-events: none;
|
||
user-select: none; /* keeps hidden copy out of a drag-selection */
|
||
transition: opacity 0.35s ease;
|
||
}
|
||
|
||
.event-note-header {
|
||
display: flex;
|
||
align-items: baseline;
|
||
gap: 6px;
|
||
}
|
||
|
||
.event-note-body {
|
||
display: flex;
|
||
align-items: baseline;
|
||
gap: 10px;
|
||
min-width: 0;
|
||
}
|
||
.event-note-slide.is-active {
|
||
opacity: 1;
|
||
pointer-events: auto;
|
||
user-select: auto;
|
||
}
|
||
|
||
.event-note-emoji {
|
||
font-size: 16px;
|
||
line-height: 1;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.event-note-title {
|
||
font-family: Fraunces, serif;
|
||
font-style: italic;
|
||
font-weight: 700;
|
||
font-size: 14px;
|
||
color: #2a1a08;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.event-note-msg {
|
||
font-family: Manrope, sans-serif;
|
||
font-size: 12.5px;
|
||
font-weight: 500;
|
||
line-height: 1.45;
|
||
color: #6b4f2a;
|
||
min-width: 0;
|
||
}
|
||
|
||
.event-note-dates {
|
||
font-family: Manrope, sans-serif;
|
||
font-size: 10px;
|
||
font-weight: 700;
|
||
letter-spacing: 0.06em;
|
||
text-transform: uppercase;
|
||
color: #9a7d5a;
|
||
white-space: nowrap;
|
||
margin-left: auto; /* push the dates to the right-hand end */
|
||
flex-shrink: 0;
|
||
}
|
||
.event-note.is-priority .event-note-dates {
|
||
color: #a06e18;
|
||
}
|
||
|
||
.event-note-dots {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 6px;
|
||
flex-shrink: 0;
|
||
align-self: center;
|
||
}
|
||
.event-note-dot {
|
||
width: 6px;
|
||
height: 6px;
|
||
padding: 0;
|
||
border: none;
|
||
border-radius: 50%;
|
||
background: #d9c39b;
|
||
cursor: pointer;
|
||
transition: background 0.2s, transform 0.2s;
|
||
}
|
||
.event-note-dot:hover {
|
||
background: #c0a880;
|
||
}
|
||
.event-note-dot.active {
|
||
background: #c8922a;
|
||
transform: scale(1.3);
|
||
}
|
||
|
||
/* Close + Quick Record stack in the strip's top-right corner, Close above
|
||
Quick Record, rather than running side by side in the row. */
|
||
.event-note-actions {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: flex-end;
|
||
gap: 4px;
|
||
flex-shrink: 0;
|
||
align-self: flex-start;
|
||
margin: -2px -6px 0 10px;
|
||
}
|
||
|
||
/* Quick Record — the banner's one action: sends the event showing to the
|
||
journal (see quickRecord in app.js). Reads as an affordance rather than
|
||
chrome, so unlike the close pill above it it carries its brass tint
|
||
standing still. */
|
||
.event-note-record {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 5px;
|
||
flex-shrink: 0;
|
||
padding: 4px 9px;
|
||
border: 1px solid rgba(200, 146, 42, 0.45);
|
||
border-radius: 999px;
|
||
background: rgba(200, 146, 42, 0.13);
|
||
font-family: Manrope, sans-serif;
|
||
font-size: 10px;
|
||
font-weight: 700;
|
||
letter-spacing: 0.06em;
|
||
text-transform: uppercase;
|
||
color: #8a6414;
|
||
line-height: 1;
|
||
cursor: pointer;
|
||
transition: background 0.2s, color 0.2s, border-color 0.2s;
|
||
}
|
||
.event-note-record:hover {
|
||
background: rgba(200, 146, 42, 0.28);
|
||
border-color: rgba(200, 146, 42, 0.75);
|
||
color: #6b4a0c;
|
||
}
|
||
.event-note-record:focus-visible {
|
||
outline: 2px solid #c8922a;
|
||
outline-offset: 1px;
|
||
}
|
||
/* On a tinted warning the brass disappears into the hue, so the pill drops
|
||
to the same neutral darks the rest of the tinted copy uses. */
|
||
.event-note.is-tinted .event-note-record {
|
||
background: rgba(0, 0, 0, 0.08);
|
||
border-color: rgba(0, 0, 0, 0.24);
|
||
color: #3f3222;
|
||
}
|
||
.event-note.is-tinted .event-note-record:hover {
|
||
background: rgba(0, 0, 0, 0.16);
|
||
border-color: rgba(0, 0, 0, 0.4);
|
||
color: #2a1a08;
|
||
}
|
||
|
||
/* Close control — a small brass "Close ×" pill in the top-right corner. It
|
||
sits at the end of the strip's flex row rather than being absolutely
|
||
positioned, so the dates line can never run underneath it. */
|
||
.event-note-close {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 4px;
|
||
flex-shrink: 0;
|
||
padding: 3px 7px;
|
||
border: 1px solid transparent;
|
||
border-radius: 999px;
|
||
background: transparent;
|
||
font-family: Manrope, sans-serif;
|
||
font-size: 10px;
|
||
font-weight: 700;
|
||
letter-spacing: 0.06em;
|
||
text-transform: uppercase;
|
||
color: #9a7d5a;
|
||
line-height: 1;
|
||
cursor: pointer;
|
||
transition: background 0.2s, color 0.2s, border-color 0.2s;
|
||
}
|
||
.event-note-close:hover {
|
||
background: rgba(200, 146, 42, 0.14);
|
||
border-color: rgba(200, 146, 42, 0.45);
|
||
color: #7a5a1e;
|
||
}
|
||
.event-note-close:focus-visible {
|
||
outline: 2px solid #c8922a;
|
||
outline-offset: 1px;
|
||
}
|
||
.event-note.is-priority .event-note-close {
|
||
color: #a06e18;
|
||
}
|
||
.event-note.is-tinted .event-note-close {
|
||
color: #56452c;
|
||
}
|
||
.event-note.is-tinted .event-note-close:hover {
|
||
background: rgba(0, 0, 0, 0.09);
|
||
border-color: rgba(0, 0, 0, 0.22);
|
||
color: #2a1a08;
|
||
}
|
||
|
||
/* Closing: the slot's height runs down to zero (measured and driven inline by
|
||
noteClose in app.js) and the note is anchored to its BOTTOM edge, so the
|
||
banner rides up behind the header's seam while everything below it rises by
|
||
the same amount at the same rate. One animated property for both movements —
|
||
a transform on the note would slide it independently of the page, and a
|
||
transform on the content below would break the fixed-position controls
|
||
living inside it. */
|
||
.event-note-slot {
|
||
/* The gap under the banner lives here rather than on the note, and is
|
||
deliberately equal to what the header gets back when .has-event-note is
|
||
dropped at the end of the close: the header's own margin-bottom (18px,
|
||
zeroed while a note is attached) plus, on a phone, the 8px .utci-app
|
||
stops padding once the note is gone. Without that, the space swapped in
|
||
at unmount showed up as a jump. */
|
||
margin-bottom: 18px;
|
||
display: grid;
|
||
grid-template-rows: 1fr; /* the row fills the slot, whatever its height */
|
||
align-items: end; /* ...and the note hangs from its bottom edge */
|
||
overflow: hidden;
|
||
}
|
||
.event-note-slot > .event-note {
|
||
min-height: 0; /* grid items floor at min-content without this */
|
||
}
|
||
/* The entry animation is fill-mode: both, so its final transform would stay
|
||
applied — cleared so it cannot offset the note against the slot. */
|
||
.event-note.is-closing {
|
||
animation: none;
|
||
pointer-events: none;
|
||
}
|
||
|
||
/* The note follows the header in the flow now, so it needs no special
|
||
positioning — only the gap the header's own margin-bottom would otherwise
|
||
have given the content it sits in front of. */
|
||
|
||
@media (max-width: 640px) {
|
||
.event-note {
|
||
align-items: flex-start;
|
||
gap: 9px;
|
||
padding: 10px 12px;
|
||
}
|
||
.event-note-dates {
|
||
margin-left: 0; /* no room to right-align on a phone */
|
||
}
|
||
/* Phone: both pills shrink to their icon alone, on a ~26px touch target
|
||
each, and the stack is pushed to the right-hand end of the row. */
|
||
.event-note-actions {
|
||
margin: -4px -6px 0 auto;
|
||
gap: 2px;
|
||
}
|
||
.event-note-close {
|
||
padding: 8px;
|
||
}
|
||
.event-note-close-label {
|
||
display: none;
|
||
}
|
||
/* Same treatment for Quick Record — the notebook glyph alone. It keeps its
|
||
tint, so it still reads as the button of the two. */
|
||
.event-note-record {
|
||
padding: 7px;
|
||
}
|
||
.event-note-record-label {
|
||
display: none;
|
||
}
|
||
}
|
||
|
||
/* ── Note attached to the header ─────────────────────────────────────
|
||
When a note is present it hangs off the header's bottom edge rather than
|
||
floating below it as a separate panel: the header drops the gap it would
|
||
otherwise leave, and the note keeps a square top with no top border, inset
|
||
to the content edge so there is a gap either side. The header's own bottom
|
||
rule becomes the seam the strip hangs from.
|
||
|
||
Placed after the ≤640px block above deliberately — these override the
|
||
note's base padding and border at every width, mobile included. */
|
||
.has-event-note .utci-topnav {
|
||
margin-bottom: 0;
|
||
}
|
||
.has-event-note .event-note {
|
||
/* Inset to the content edge rather than full-bleed, so the strip keeps a
|
||
gap either side of it. The gap below is the slot's — see .event-note-slot. */
|
||
margin: 0;
|
||
padding: 10px 15px;
|
||
/* No top border and square top corners: the header's own bottom rule is the
|
||
seam it hangs from. A tinted note's inline borderColor still tints what is
|
||
left, since that sets the colour only and this sets style and width. */
|
||
border: 1.5px solid #c9b08a;
|
||
border-top: none;
|
||
border-radius: 0 0 4px 4px;
|
||
}
|
||
@media (max-width: 640px) {
|
||
/* Matches the two-class specificity above so the phone's tighter padding
|
||
survives the override. */
|
||
.has-event-note .event-note {
|
||
padding: 10px 12px;
|
||
}
|
||
|
||
/* 18px + the 8px of .utci-app padding-top below — see .event-note-slot. */
|
||
.event-note-slot {
|
||
margin-bottom: 26px;
|
||
}
|
||
|
||
/* The bar is position:fixed and 72px tall on a phone, and .utci-app pads 80px
|
||
clear of it — the spare 8px would show as a gap above the note. Two classes
|
||
so it outranks the single-class padding-top in ui.css whatever the order. */
|
||
.utci-app.has-event-note {
|
||
padding-top: 72px;
|
||
}
|
||
}
|
||
|
||
/* The site identity, in the header on every viewport. Was display:none here
|
||
and unhidden only on mobile, back when the big .utci-title wordmark carried
|
||
the desktop identity instead. */
|
||
.nav-logo {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: flex-start;
|
||
justify-content: center;
|
||
flex-shrink: 0;
|
||
/* Same device about.css uses on .nav-logo: one auto margin pushes everything
|
||
after it to the right-hand end, which works with .nav-links staying
|
||
display:contents. */
|
||
margin-right: auto;
|
||
}
|
||
.nav-logo-wordmark {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 0.05em;
|
||
/* It is the page's <h1> now, so the browser's own h1 margin and 2em size are
|
||
cleared here — the wordmark's size and weight come from .nav-logo-sun and
|
||
.nav-logo-scope, and the icon is sized in rem. */
|
||
margin: 0;
|
||
font-size: 1rem;
|
||
font-weight: inherit;
|
||
}
|
||
.nav-logo-sun,
|
||
.nav-logo-scope {
|
||
font-family: Manrope, sans-serif;
|
||
font-weight: 250;
|
||
/* 1.6rem matches .nav-logo-sun in about.css, so the wordmark is the same size on the
|
||
forecast and on every static page. The phone bar scales it back up (see the
|
||
≤640px block) where it is the centred focal point rather than a corner mark. */
|
||
font-size: 1.6rem;
|
||
color: #1e1208;
|
||
letter-spacing: -0.01em;
|
||
}
|
||
.nav-logo-icon {
|
||
width: 1.26rem; /* same 0.79 ratio to the wordmark as .nav-logo-icon */
|
||
height: 1.26rem;
|
||
color: #1e1208;
|
||
flex-shrink: 0;
|
||
}
|
||
.nav-logo-tag {
|
||
display: block;
|
||
font-family: Manrope, sans-serif;
|
||
font-style: normal;
|
||
font-weight: 600;
|
||
font-size: 10px;
|
||
letter-spacing: 0.12em;
|
||
text-transform: uppercase;
|
||
color: #7a5c2a;
|
||
margin-top: 3px;
|
||
}
|
||
|
||
/* Desktop: overlay hidden */
|
||
.utci-topnav .nav-overlay {
|
||
display: none;
|
||
}
|
||
|
||
/* ── Burger button (hidden on desktop) ─────────────────────────────── */
|
||
.utci-burger {
|
||
display: none;
|
||
flex-direction: column;
|
||
justify-content: center;
|
||
align-items: center;
|
||
gap: 5px;
|
||
width: 36px;
|
||
height: 36px;
|
||
background: none;
|
||
border: none;
|
||
cursor: pointer;
|
||
padding: 4px;
|
||
z-index: 110;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.utci-burger span {
|
||
display: block;
|
||
width: 22px;
|
||
height: 2px;
|
||
background: #7a5c2a;
|
||
border-radius: 2px;
|
||
transition: transform 0.25s ease, opacity 0.2s ease;
|
||
transform-origin: center;
|
||
}
|
||
|
||
/* ── Mobile nav drawer ──────────────────────────────────────────────── */
|
||
@media (max-width: 640px) {
|
||
.utci-app {
|
||
padding: 96px 16px 24px; /* 96px = 72px nav height + 24px breathing room */
|
||
}
|
||
|
||
/* Show wordmark in nav bar, hide it from main content */
|
||
.nav-logo {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
justify-content: center;
|
||
position: absolute;
|
||
left: 0;
|
||
right: 0;
|
||
top: 50%;
|
||
transform: translateY(-50%);
|
||
text-align: center;
|
||
pointer-events: none;
|
||
}
|
||
|
||
.nav-logo-wordmark {
|
||
display: block;
|
||
line-height: 1;
|
||
}
|
||
.nav-logo-sun,
|
||
.nav-logo-scope {
|
||
font-size: 2.1rem;
|
||
}
|
||
.nav-logo-icon {
|
||
width: 1.65rem;
|
||
height: 1.65rem;
|
||
}
|
||
|
||
/* Phone keeps the bar pinned to the viewport, with the wordmark centred in
|
||
it and the links behind the burger. The offsets are set here rather than
|
||
inherited: the desktop rule is in-flow now and carries no top/left/right,
|
||
and its full-bleed negative margin has nothing to cancel once the bar is
|
||
fixed and already edge-to-edge. */
|
||
.utci-topnav {
|
||
position: fixed;
|
||
top: 0;
|
||
left: 0;
|
||
right: 0;
|
||
margin: 0;
|
||
padding: 10px 20px;
|
||
height: 72px;
|
||
background: #ebdcb4;
|
||
border-bottom: 1px solid #c9b08a;
|
||
box-shadow: 0 3px 8px rgba(30, 18, 8, 0.10);
|
||
}
|
||
|
||
.utci-burger {
|
||
display: flex;
|
||
}
|
||
|
||
/* Hide the links by default on mobile — shown in drawer */
|
||
.utci-topnav .nav-links {
|
||
position: fixed;
|
||
top: 0;
|
||
right: -100%;
|
||
width: 220px;
|
||
height: 100vh;
|
||
background: #ebdcb4;
|
||
border-left: 1px solid #c9b08a;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: flex-start;
|
||
justify-content: flex-start;
|
||
padding: 80px 32px 32px;
|
||
gap: 28px;
|
||
transition: right 0.28s cubic-bezier(0.4, 0, 0.2, 1);
|
||
box-shadow: -8px 0 24px rgba(100,70,20,0.08);
|
||
z-index: 105;
|
||
}
|
||
|
||
.utci-topnav .nav-links.is-open {
|
||
right: 0;
|
||
}
|
||
|
||
.utci-topnav .nav-links a {
|
||
font-size: 15px;
|
||
}
|
||
|
||
/* Dropdown collapses to an indented static list inside the drawer */
|
||
.utci-topnav .nav-dropdown {
|
||
flex-direction: column;
|
||
align-items: flex-start;
|
||
width: 100%;
|
||
gap: 18px;
|
||
}
|
||
.utci-topnav .nav-dropdown-toggle .caret { display: none; }
|
||
.utci-topnav .nav-dropdown-menu {
|
||
position: static;
|
||
opacity: 1;
|
||
visibility: visible;
|
||
transform: none;
|
||
box-shadow: none;
|
||
border: none;
|
||
background: none;
|
||
padding: 0 0 0 14px;
|
||
margin-top: 0;
|
||
min-width: 0;
|
||
gap: 18px;
|
||
}
|
||
.utci-topnav .nav-dropdown-menu a { padding: 0; font-size: 14px; }
|
||
/* Right-aligned text is a desktop-popup touch (see the --right rule
|
||
above) - on mobile everything is one left-indented list, so match
|
||
About's list instead of standing out. */
|
||
.utci-topnav .nav-dropdown--right .nav-dropdown-menu a { text-align: left; }
|
||
|
||
/* Burger → X animation */
|
||
.utci-topnav.nav-open .utci-burger span:nth-child(1) {
|
||
transform: translateY(7px) rotate(45deg);
|
||
}
|
||
.utci-topnav.nav-open .utci-burger span:nth-child(2) {
|
||
opacity: 0;
|
||
transform: scaleX(0);
|
||
}
|
||
.utci-topnav.nav-open .utci-burger span:nth-child(3) {
|
||
transform: translateY(-7px) rotate(-45deg);
|
||
}
|
||
|
||
/* Overlay behind drawer */
|
||
.utci-topnav .nav-overlay {
|
||
display: block;
|
||
position: fixed;
|
||
inset: 0;
|
||
background: rgba(30,18,8,0.35);
|
||
opacity: 0;
|
||
pointer-events: none;
|
||
transition: opacity 0.25s ease;
|
||
z-index: 104;
|
||
}
|
||
|
||
.utci-topnav.nav-open .nav-overlay {
|
||
opacity: 1;
|
||
pointer-events: auto;
|
||
}
|
||
}
|