/* Palette lifted from the monthly calendar (../calendar/public/calendar.css)
   so the two read as one family. Freetime is a lighter tint of the primary —
   same shape, same column as a scheduled event, just a different shade. */

@font-face {
	font-family: 'Josefin Sans';
	font-style: normal;
	font-weight: 400;
	font-display: swap;
	src: url('fonts/josefin-sans.woff2') format('woff2');
}

:root {
	--ink: #0c2754;			/* darkest navy: borders, header text */
	--primary: #1a3e7c;		/* scheduled events, buttons */
	--today: #0e2751;
	--rule: #c7d3e7;		/* grid lines */
	--rule-soft: #e3eaf5;
	--freetime: #8ba3ca;	/* lighter tint of --primary */
	--freetime-ink: #12305f;
	/* Peeked calendars (family) share one blue so they read as a single group.
	   Cooler and greener than the navy/periwinkle pair, so it's distinct from
	   both scheduled and freetime at a glance. */
	--family: #3f7f9e;
	--muted: #6b82a8;

	--gutter: 54px;
	--tzgutter: 0px;		/* widens when a second timezone is chosen */
	--daymin: 96px;			/* below this, days stop shrinking and you scroll */
	--hour: 46px;			/* px per hour; JS reads this */
	--head: 74px;
	--allday: 30px;
	--bar: 34px;
	--lane: 9px;			/* left strip in each column reserved for rain marks */
}

/* Only when a second timezone is picked does its gutter take up room. */
#calWrap.has-tz { --tzgutter: 46px; }

* { box-sizing: border-box; }

html, body {
	height: 100%;
	margin: 0;
}

body {
	color: var(--ink);
	font: 15px 'Josefin Sans', sans-serif;
	background: #fff;
	overflow: hidden;
}

/* ============ top bar ============ */

#topbar {
	height: var(--bar);
	line-height: var(--bar);
	border-bottom: 0.5px solid var(--ink);
	padding: 0 10px;
	display: flex;
	align-items: center;
	gap: 8px;
	white-space: nowrap;
	overflow-x: auto;
	overflow-y: hidden;
}

#range {
	font-size: 17px;
	color: var(--ink);
	padding-right: 6px;
}

#spacer { flex: 1; }

#status {
	font-size: 13px;
	color: var(--muted);
}

#status.offline { color: #a8442a; }

a.button, button.button {
	display: inline-block;
	color: var(--primary);
	font: 14px 'Josefin Sans', sans-serif;
	text-decoration: none;
	padding: 4px 12px;
	border: 1px solid var(--rule);
	border-radius: 4px;
	background: #fff;
	cursor: pointer;
	line-height: 18px;
}

a.button:active, button.button:active { background: #d7d7d7; }
button.primary { background: var(--primary); color: #fff; border-color: var(--primary); }
a.danger { color: #a8442a; border-color: #e3cdc6; }

/* ---- calendar chips ----
   Two controls in one pill: the name toggles visibility, the dot on the right
   makes that calendar the target for new events. */

.chip {
	display: inline-flex;
	align-items: center;
	font-size: 13px;
	margin-right: 4px;
	border: 1px solid var(--rule);
	border-radius: 11px;
	user-select: none;
	color: var(--muted);
	background: #fff;
	line-height: 18px;
	overflow: hidden;
}

.chip .name {
	padding: 2px 8px 2px 10px;
	cursor: pointer;
}

.chip.on {
	background: var(--primary);
	border-color: var(--primary);
	color: #fff;
}

.chip.freetime.on {
	background: var(--freetime);
	border-color: var(--freetime);
	color: var(--freetime-ink);
}

.chip.add {
	padding: 2px 10px;
	cursor: pointer;
	border-style: dashed;
	color: var(--muted);
}

.chip.add:hover { color: var(--primary); border-color: var(--primary); }

/* Hold-to-peek marker. A peeked calendar is hidden until F is held, so its chip
   sits in the family blue and dashed, to say "not currently on screen". */
.chip.peek {
	background: #fff;
	border-color: var(--family);
	border-style: dashed;
	color: var(--family);
}

body.peeking .chip.peek {
	background: var(--family);
	color: #fff;
	border-style: solid;
}

.chip .peekToggle {
	cursor: pointer;
	padding: 2px 6px 2px 4px;
	font-size: 11px;
	font-style: italic;
	opacity: 0.45;
}

.chip .peekToggle:hover { opacity: 0.95; }
.chip.peek .peekToggle { opacity: 1; }

.chip .target {
	cursor: pointer;
	padding: 2px 8px 2px 4px;
	font-size: 11px;
	opacity: 0.45;
}

.chip .target:hover { opacity: 0.9; }

/* The default target for new events is the filled one. */
.chip.is-target .target { opacity: 1; }

#tzPick {
	font-size: 12px;
	color: var(--muted);
	display: inline-flex;
	align-items: center;
	gap: 4px;
}

#tzSelect {
	font: 12px 'Josefin Sans', sans-serif;
	color: var(--ink);
	border: 1px solid var(--rule);
	border-radius: 4px;
	padding: 2px 4px;
	background: #fff;
	max-width: 150px;
}

.nav { display: inline-flex; gap: 3px; }
a.button.step { padding: 4px 8px; }

#jumpDate {
	font: 12px 'Josefin Sans', sans-serif;
	color: var(--muted);
	border: 1px solid var(--rule);
	border-radius: 4px;
	padding: 3px 5px;
	background: #fff;
}

/* ============ calendar frame ============ */

/* One scroll container for both axes. Days narrower than --daymin push the grid
   wider than the viewport and you scroll sideways to reach them, rather than
   the columns being clipped off the edge. Headers stay pinned to the top and
   the time gutters to the left, so neither is lost while scrolling. */
#calWrap {
	height: calc(100% - var(--bar));
	overflow: auto;
}

#calHead, #allDayRow, #calBody {
	display: grid;
	grid-template-columns: var(--tzgutter) var(--gutter) repeat(8, minmax(var(--daymin), 1fr));
	min-width: calc(var(--tzgutter) + var(--gutter) + 8 * var(--daymin));
}

#calHead {
	height: var(--head);
	border-bottom: 1px solid var(--rule);
	position: sticky;
	top: 0;
	z-index: 6;
	background: #fff;
}

#allDayRow {
	min-height: var(--allday);
	border-bottom: 1px solid var(--ink);
	position: sticky;
	top: var(--head);
	z-index: 6;
	background: #fff;
}

#calBody {
	align-items: start;
}

/* Left-pinned columns: the secondary-zone gutter, then the local one. */
.stickyL0, .stickyL1 {
	position: sticky;
	z-index: 5;
	background: #fff;
}

.stickyL0 { left: 0; }
.stickyL1 { left: var(--tzgutter); }

/* Inside the pinned header rows these must also outrank the day cells. */
#calHead .stickyL0, #calHead .stickyL1,
#allDayRow .stickyL0, #allDayRow .stickyL1 { z-index: 7; }

/* ---- day headers ---- */

.dayhead {
	border-left: 1px solid var(--rule);
	padding: 4px 6px 0 6px;
	text-align: center;
	overflow: hidden;
}

.dayhead.is-today { background: #f2f6fc; }
.dayhead.is-past .dname, .dayhead.is-past .dnum { color: var(--muted); }

.dname {
	font-size: 12px;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--muted);
	line-height: 14px;
}

.dnum {
	font-size: 19px;
	line-height: 21px;
	color: var(--ink);
}

.dayhead.is-today .dnum {
	display: inline-block;
	min-width: 26px;
	border-bottom: 2px solid var(--today);
}

/* ---- weather ---- */

.wx {
	font-size: 12px;
	line-height: 15px;
	color: var(--muted);
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}

.wx .icon { font-size: 13px; color: var(--primary); }
.wx .hi { color: var(--ink); }
.wx .pp { color: var(--freetime); }
.wx.stale { opacity: 0.55; font-style: italic; }

.wind {
	font-size: 11px;
	line-height: 13px;
	color: var(--muted);
	white-space: nowrap;
	overflow: hidden;
}

.wind .arrow { display: inline-block; color: var(--freetime); }

/* ---- all-day band ---- */

.adcol {
	border-left: 1px solid var(--rule);
	padding: 2px;
	min-height: var(--allday);
	display: flex;
	flex-direction: column;
	gap: 2px;
}

.adevent {
	font-size: 12px;
	line-height: 15px;
	padding: 1px 5px;
	border-radius: 3px;
	background: var(--primary);
	color: #fff;
	cursor: pointer;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.adevent.freetime { background: var(--freetime); color: var(--freetime-ink); }
.adevent { position: relative; }

.gutlabel {
	font-size: 11px;
	color: var(--muted);
	text-align: right;
	padding: 3px 5px 0 0;
	line-height: 13px;
}

/* ---- time gutters ---- */

/* Position comes from .stickyL0/.stickyL1 — sticky also anchors the absolutely
   positioned hour labels, so no `position: relative` here (it would win on
   specificity and un-stick the gutter). */
#times, #tzTimes {
	border-right: 1px solid var(--rule);
}

#tzTimes { border-right-color: var(--rule-soft); }

.hourlabel {
	position: absolute;
	right: 5px;
	font-size: 11px;
	color: var(--muted);
	line-height: 11px;
	transform: translateY(-5px);
}

/* The secondary zone reads as an aside, not a peer of local time. */
#tzTimes .hourlabel {
	color: var(--freetime);
	font-style: italic;
}

.tzhead {
	font-size: 10px;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--freetime);
	text-align: right;
	padding: 6px 5px 0 2px;
	line-height: 12px;
	overflow: hidden;
}

/* ---- day columns ---- */

.col {
	position: relative;
	border-left: 1px solid var(--rule);
	/* hour lines: solid on the hour, faint on the half hour */
	background-image:
		linear-gradient(to bottom, var(--rule) 1px, transparent 1px),
		linear-gradient(to bottom, var(--rule-soft) 1px, transparent 1px);
	background-size: 100% var(--hour), 100% calc(var(--hour) / 2);
}

.col.is-today { background-color: #f8fafd; }
.col.is-past { background-color: #fbfbfc; }

.nowline {
	position: absolute;
	left: 0;
	right: 0;
	height: 0;
	border-top: 1.5px solid #a8442a;
	z-index: 5;
	pointer-events: none;
}

/* ---- rain marks ----
   A teardrop drawn in CSS rather than a glyph, so it doesn't depend on emoji
   coverage and stays the same navy as everything else. Filled = rain starts,
   hollow = rain stops. They live in the --lane strip down the left of each
   column, which events are inset past, so the two never collide. */

.drop {
	position: absolute;
	left: 1px;
	width: 7px;
	height: 7px;
	background: var(--primary);
	border: 1px solid var(--primary);
	border-radius: 50% 50% 50% 0;
	transform: rotate(-45deg) translate(-1px, -1px);
	z-index: 3;
	pointer-events: none;
}

.drop.end {
	background: transparent;
}

/* ---- events ---- */

.ev {
	position: absolute;
	overflow: hidden;
	border-radius: 3px;
	padding: 2px 5px;
	font-size: 12px;
	line-height: 14px;
	cursor: pointer;
	background: var(--primary);
	color: #fff;
	border: 1px solid #fff;
	z-index: 2;
}

/* Same column, same shape as a scheduled event — only the shade differs. */
.ev.freetime {
	background: var(--freetime);
	color: var(--freetime-ink);
	z-index: 1;
}

/* Only on screen while F is held, so they read as a temporary overlay. */
.ev.family, .adevent.family {
	background: var(--family);
	color: #fff;
}

.ev.family { z-index: 3; }

/* An edit that hasn't reached Google yet. It stays fully coloured and fully
   clickable — dimming it read as "disabled" when the only thing that's true is
   "not synced yet". The hollow dot is the whole hint; it disappears by itself
   once the outbox drains. */
.ev.pending::after,
.adevent.pending::after {
	content: '';
	position: absolute;
	top: 3px;
	right: 3px;
	width: 5px;
	height: 5px;
	border: 1px solid currentColor;
	border-radius: 50%;
	opacity: 0.85;
}

.ev .t {
	font-size: 11px;
	opacity: 0.85;
	display: block;
}

/* No pin glyph — italic and dimmed is enough to separate location from title,
   and avoids depending on symbol coverage in the font. */
.ev .loc {
	font-size: 11px;
	font-style: italic;
	opacity: 0.75;
	display: block;
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}

.ev .grip {
	position: absolute;
	left: 0;
	right: 0;
	bottom: 0;
	height: 6px;
	cursor: ns-resize;
}

/* While dragging, the real event stays put and faded; the ghost shows where it
   will land. */
.ev.dragging { opacity: 0.25; }

.ghost {
	position: absolute;
	border-radius: 3px;
	padding: 2px 5px;
	font-size: 12px;
	line-height: 14px;
	background: rgba(26, 62, 124, 0.22);
	border: 1px dashed var(--primary);
	color: var(--ink);
	z-index: 7;
	pointer-events: none;
	overflow: hidden;
}

.ghost.freetime {
	background: rgba(139, 163, 202, 0.28);
	border-color: var(--freetime);
}

.ghost .t { font-size: 11px; display: block; }

/* ============ editor ============ */

#editor {
	display: none;
	position: fixed;
	inset: 0;
	background: rgba(12, 39, 84, 0.35);
	z-index: 10;
}

#editor.open { display: block; }

#editorBox {
	width: 360px;
	margin: 90px auto 0 auto;
	background: #fff;
	padding: 18px;
	border-radius: 5px;
	box-shadow: 0 5px 20px rgba(0, 0, 0, 0.35);
}

#fSummary {
	width: 100%;
	font: 19px 'Josefin Sans', sans-serif;
	color: var(--ink);
	border: none;
	border-bottom: 1px solid var(--rule);
	padding: 4px 0 6px 0;
	margin-bottom: 14px;
}

#editorBox .row {
	display: flex;
	align-items: center;
	gap: 8px;
	margin-bottom: 9px;
}

#editorBox .lbl {
	width: 66px;
	font-size: 13px;
	color: var(--muted);
	flex: none;
}

#editorBox input[type=text],
#editorBox input[type=date],
#editorBox input[type=time],
#editorBox select {
	font: 14px 'Josefin Sans', sans-serif;
	color: var(--ink);
	border: 1px solid var(--rule);
	border-radius: 3px;
	padding: 4px 6px;
	background: #fff;
	flex: 1;
	min-width: 0;
}

#editorBox .check { font-size: 13px; color: var(--muted); }
#editorBox .check input { margin: 0 4px 0 0; }

input:focus, select:focus, textarea:focus { outline: 1px solid var(--primary); }

#editorError {
	color: #a8442a;
	font-size: 13px;
	margin: 0 0 8px 0;
	min-height: 16px;
}

#editorNote {
	color: var(--muted);
	font-size: 13px;
	font-style: italic;
	margin: 0;
}

#editorNote:empty { display: none; }

#editorBox input:disabled, #editorBox select:disabled {
	background: #f6f8fb;
	color: var(--muted);
	cursor: default;
}

.actions { display: flex; align-items: center; gap: 6px; }
.actions .grow { flex: 1; }

/* ============ sign-in ============ */

#signin {
	display: none;
	position: fixed;
	inset: 0;
	background: #fff;
	z-index: 20;
}

#signin.open { display: block; }

#signin div {
	text-align: center;
	margin: 150px auto 0 auto;
	width: 400px;
	padding: 20px;
	color: var(--ink);
	font: 30px 'Josefin Sans', sans-serif;
}

#signin .button { font-size: 20px; padding: 10px 20px; margin-top: 20px; }
#signinError { font-size: 15px; color: var(--primary); }
