mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-10-19 05:26:47 +00:00
85b5756e89
Ride minutes and late marks follow an edited timetable instead of the routing that fetched them; a landing day's join band reads as the ride it is rather than a nine hour drive of no length; the refuel offer is there on the road out of a terminal or a pick-up desk; the phone's stage map draws the ride; the share page numbers its stops the way the planner does; the PDF lists a day the way the day plan lists it, from both shells; a poster-less clip draws its play badge everywhere, not only in the editor; the hero title has room for its descenders and the list card keeps its badge clear; the release notice keeps its close control in reach when it stacks; a link chip's actions are thumb-sized and its delete asks first; the Google retry line and the Google-only switch appear only where Google answers.
823 lines
22 KiB
CSS
823 lines
22 KiB
CSS
/*
|
|
* The release notice modal: a two-column panel, the release on the left and a
|
|
* note from the maintainer on the right.
|
|
*
|
|
* The measurements are the design's own, at full size, kept in one stylesheet
|
|
* rather than spread across inline styles (the same arrangement mobile.css uses
|
|
* for the mobile shell). The panel is 1420px wide wherever the screen has room
|
|
* and gives up width, never size, where it has not.
|
|
*
|
|
* The left column is deliberately dark in both themes: it is a brand panel, not
|
|
* a surface, so it does not read the surface tokens. Everything on the right
|
|
* does. theme-lint-disable: the brand panel's colours are fixed by design.
|
|
*/
|
|
|
|
.rn-overlay {
|
|
position: fixed;
|
|
inset: 0;
|
|
/* Above the navbar, the page-bound sticky bars and the page-owned
|
|
overlays: the notice is app-wide, so nothing a page draws may cover it. */
|
|
z-index: var(--z-notice, 99998);
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
padding: 34px;
|
|
background: oklch(0.12 0.01 60 / 0.52);
|
|
backdrop-filter: blur(14px) saturate(1.1);
|
|
-webkit-backdrop-filter: blur(14px) saturate(1.1);
|
|
animation: rn-fade 0.35s ease both;
|
|
}
|
|
|
|
@keyframes rn-fade {
|
|
from { opacity: 0; }
|
|
to { opacity: 1; }
|
|
}
|
|
|
|
@keyframes rn-rise {
|
|
from { opacity: 0; transform: translateY(16px) scale(0.985); }
|
|
to { opacity: 1; transform: none; }
|
|
}
|
|
|
|
/*
|
|
* The design draws these boxes with their border outside the stated size, the
|
|
* browser default. TREK sets border-box globally, which would take 2px off each.
|
|
*/
|
|
.rn-panel,
|
|
.rn-mark,
|
|
.rn-feature,
|
|
.rn-feature-visual,
|
|
.rn-notes,
|
|
.rn-close { box-sizing: content-box; }
|
|
|
|
.rn-panel {
|
|
position: relative;
|
|
width: min(1420px, calc(100% - 2px));
|
|
max-height: 100%;
|
|
display: grid;
|
|
grid-template-columns: 1.2fr 1fr;
|
|
/* One row, never taller than the panel: otherwise the row takes the height of
|
|
the taller column and the panel clips both, the support buttons first. */
|
|
grid-template-rows: minmax(0, 1fr);
|
|
border-radius: 30px;
|
|
overflow: hidden;
|
|
box-shadow: 0 4px 12px oklch(0 0 0 / 0.2), 0 60px 130px -40px oklch(0 0 0 / 0.7);
|
|
border: 1px solid oklch(1 0 0 / 0.1);
|
|
animation: rn-rise 0.5s cubic-bezier(0.22, 1, 0.36, 1) both;
|
|
font-family: var(--font-system);
|
|
/* The design sets no base line height; the app's 1.5 would add 3px to every label. */
|
|
line-height: normal;
|
|
}
|
|
|
|
/* The panel's, not the note's: in the stacked layout below it has to outlast the
|
|
release half, which scrolls by first. */
|
|
.rn-close {
|
|
position: absolute;
|
|
top: 22px;
|
|
/* Logical, so the X sits at the reading end in Arabic too. With the physical
|
|
right it stayed over the release half there, which the note's palette below
|
|
is not made for, and the stacked layout put it at the other end anyway. */
|
|
inset-inline-end: 22px;
|
|
width: 36px;
|
|
height: 36px;
|
|
border-radius: 50%;
|
|
background: var(--bg-hover);
|
|
border: 1px solid var(--border-faint);
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
color: var(--text-secondary);
|
|
z-index: 2;
|
|
cursor: pointer;
|
|
transition: background-color 0.15s ease, color 0.15s ease;
|
|
}
|
|
|
|
.rn-close:hover { background: var(--bg-selected); color: var(--text-primary); }
|
|
|
|
/* Below the two-column breakpoint the halves stack and the panel scrolls. The
|
|
rows must go back to auto: with the single minmax row from above, the note took
|
|
the whole panel and the release half was left with nothing but its padding. */
|
|
@media (max-width: 1080px) {
|
|
.rn-panel { grid-template-columns: 1fr; grid-template-rows: auto auto; overflow-y: auto; }
|
|
.rn-release { grid-area: 1 / 1; }
|
|
.rn-note { grid-area: 2 / 1; }
|
|
.rn-release, .rn-release-inner, .rn-note-body { overflow: visible; }
|
|
/* The X used to sit in the note, a whole release half below the top edge, and
|
|
at a tablet's width the backdrop is gone too. As a grid item over both rows
|
|
it sticks 22px under the top edge for the entire scroll, over either half. */
|
|
.rn-close {
|
|
position: sticky;
|
|
grid-row: 1 / -1;
|
|
grid-column: 1;
|
|
justify-self: end;
|
|
align-self: start;
|
|
margin: 22px;
|
|
/* At the top of the scroll it hangs over the release half, which is dark in
|
|
both themes. The note's palette is a near-transparent fill and secondary
|
|
ink: in the light theme that is a slate glyph on near black, roughly 1.8:1,
|
|
so the only way to dismiss the notice on a tablet was invisible. An opaque
|
|
chip with primary ink carries over either half, the way .rn-support below
|
|
gets a solid band once it sticks. */
|
|
background: color-mix(in srgb, var(--bg-card) 92%, var(--text-primary));
|
|
border-color: var(--border-primary);
|
|
color: var(--text-primary);
|
|
box-shadow: 0 2px 8px oklch(0 0 0 / 0.25);
|
|
}
|
|
/* Once the note has scrolled into view, the ask stays at the bottom edge. The
|
|
band's usual tint is translucent, so it gets a solid one here. */
|
|
.rn-support {
|
|
position: sticky;
|
|
bottom: 0;
|
|
z-index: 1;
|
|
background: color-mix(in srgb, var(--bg-card) 95%, var(--text-primary));
|
|
}
|
|
}
|
|
|
|
[data-reduce-motion='true'] .rn-overlay,
|
|
[data-reduce-motion='true'] .rn-panel {
|
|
animation-duration: 0.01ms;
|
|
}
|
|
|
|
@media (prefers-reduced-motion: reduce) {
|
|
.rn-overlay, .rn-panel { animation-duration: 0.01ms; }
|
|
}
|
|
|
|
/* ── Left: the release ─────────────────────────────────────────────────── */
|
|
|
|
.rn-release {
|
|
position: relative;
|
|
background: radial-gradient(120% 95% at 18% 0%, #1b1b22 0%, #0e0e12 52%, #08080a 100%);
|
|
color: #f5f5f7;
|
|
padding: 44px 46px 34px;
|
|
display: flex;
|
|
flex-direction: column;
|
|
overflow: hidden;
|
|
min-height: 0;
|
|
}
|
|
|
|
/* The dot field, faded out towards the lower right. */
|
|
.rn-release-grain {
|
|
position: absolute;
|
|
inset: 0;
|
|
background-image: radial-gradient(circle, oklch(1 0 0 / 0.1) 1px, transparent 1.3px);
|
|
background-size: 24px 24px;
|
|
-webkit-mask-image: radial-gradient(90% 70% at 25% 12%, #000 0%, transparent 78%);
|
|
mask-image: radial-gradient(90% 70% at 25% 12%, #000 0%, transparent 78%);
|
|
pointer-events: none;
|
|
}
|
|
|
|
.rn-release-inner {
|
|
position: relative;
|
|
display: flex;
|
|
flex-direction: column;
|
|
flex: 1;
|
|
min-height: 0;
|
|
overflow-y: auto;
|
|
scrollbar-width: none;
|
|
}
|
|
|
|
.rn-release-inner::-webkit-scrollbar { display: none; }
|
|
|
|
.rn-eyebrow-row { display: flex; align-items: center; gap: 11px; }
|
|
|
|
.rn-mark {
|
|
width: 30px;
|
|
height: 30px;
|
|
border-radius: 10px;
|
|
background: oklch(1 0 0 / 0.1);
|
|
border: 1px solid oklch(1 0 0 / 0.16);
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
flex: none;
|
|
}
|
|
|
|
.rn-mark img { width: 18px; height: 18px; display: block; }
|
|
|
|
.rn-eyebrow,
|
|
.rn-features-label {
|
|
font-family: var(--font-subtext);
|
|
font-size: 11px;
|
|
line-height: 14px;
|
|
font-weight: 600;
|
|
letter-spacing: 0.2em;
|
|
text-transform: uppercase;
|
|
color: oklch(1 0 0 / 0.5);
|
|
}
|
|
|
|
.rn-version {
|
|
margin-top: 22px;
|
|
font-family: var(--font-subtext);
|
|
font-size: 74px;
|
|
font-weight: 600;
|
|
line-height: 0.84;
|
|
letter-spacing: -0.055em;
|
|
color: #fbfbfd;
|
|
}
|
|
|
|
.rn-headline {
|
|
/* CJK breaks anywhere by default; break at phrase boundaries where supported. */
|
|
word-break: auto-phrase;
|
|
margin: 20px 0 0;
|
|
font-size: 26px;
|
|
font-weight: 600;
|
|
line-height: 1.24;
|
|
letter-spacing: -0.03em;
|
|
max-width: 560px;
|
|
text-wrap: pretty;
|
|
}
|
|
|
|
.rn-intro {
|
|
margin: 11px 0 0;
|
|
max-width: 640px;
|
|
font-size: 16.5px;
|
|
line-height: 1.6;
|
|
color: oklch(1 0 0 / 0.62);
|
|
text-wrap: pretty;
|
|
}
|
|
|
|
.rn-features-head {
|
|
margin-top: 28px;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 14px;
|
|
}
|
|
|
|
.rn-features-label { white-space: nowrap; }
|
|
|
|
.rn-features-rule { flex: 1; height: 1px; background: oklch(1 0 0 / 0.12); }
|
|
|
|
.rn-features-aside {
|
|
font-size: 13px;
|
|
font-weight: 500;
|
|
color: oklch(1 0 0 / 0.4);
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.rn-features {
|
|
margin-top: 14px;
|
|
/* Keeps the foot clear of the cards when the column has no height to spare. */
|
|
margin-bottom: 18px;
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
|
|
gap: 14px;
|
|
}
|
|
|
|
/* A headliner laid across the row: the picture beside the text, not above it.
|
|
Doubled class so it wins over the .rn-feature block below, which sets the column. */
|
|
.rn-feature.rn-feature-wide {
|
|
grid-column: 1 / -1;
|
|
flex-direction: row;
|
|
align-items: center;
|
|
gap: 18px;
|
|
padding: 12px 18px 12px 12px;
|
|
}
|
|
|
|
.rn-feature.rn-feature-wide .rn-feature-visual {
|
|
flex: 0 0 236px;
|
|
width: 236px;
|
|
height: 88px;
|
|
}
|
|
|
|
.rn-feature.rn-feature-wide .rn-feature-body { margin-top: 4px; }
|
|
|
|
.rn-feature {
|
|
position: relative;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 18px;
|
|
min-height: 0;
|
|
padding: 14px 14px 18px;
|
|
border-radius: 20px;
|
|
background: linear-gradient(160deg, oklch(1 0 0 / 0.1) 0%, oklch(1 0 0 / 0.045) 62%);
|
|
border: 1px solid oklch(1 0 0 / 0.13);
|
|
backdrop-filter: blur(16px) saturate(1.2);
|
|
-webkit-backdrop-filter: blur(16px) saturate(1.2);
|
|
box-shadow: inset 0 1px 0 oklch(1 0 0 / 0.16), 0 12px 28px -16px oklch(0 0 0 / 0.7);
|
|
overflow: hidden;
|
|
}
|
|
|
|
.rn-feature-shine {
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
right: 0;
|
|
height: 1px;
|
|
background: linear-gradient(90deg, transparent, oklch(1 0 0 / 0.4), transparent);
|
|
}
|
|
|
|
.rn-feature-visual {
|
|
position: relative;
|
|
height: 112px;
|
|
border-radius: 14px;
|
|
overflow: hidden;
|
|
background: oklch(1 0 0 / 0.06);
|
|
border: 1px solid oklch(1 0 0 / 0.12);
|
|
}
|
|
|
|
.rn-feature-title {
|
|
font-size: 17px;
|
|
font-weight: 600;
|
|
line-height: 1.25;
|
|
letter-spacing: -0.015em;
|
|
text-wrap: pretty;
|
|
}
|
|
|
|
.rn-feature-body {
|
|
margin-top: 7px;
|
|
font-size: 13.5px;
|
|
line-height: 1.55;
|
|
color: oklch(1 0 0 / 0.6);
|
|
text-wrap: pretty;
|
|
}
|
|
|
|
.rn-release-foot {
|
|
margin-top: auto;
|
|
padding-top: 26px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
gap: 20px;
|
|
border-top: 1px solid oklch(1 0 0 / 0.09);
|
|
}
|
|
|
|
.rn-footnote {
|
|
font-size: 14.5px;
|
|
line-height: 1.55;
|
|
color: oklch(1 0 0 / 0.46);
|
|
max-width: 360px;
|
|
text-wrap: pretty;
|
|
}
|
|
|
|
.rn-notes {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 11px;
|
|
height: 44px;
|
|
padding: 0 7px 0 18px;
|
|
border-radius: 999px;
|
|
background: oklch(1 0 0 / 0.07);
|
|
border: 1px solid oklch(1 0 0 / 0.14);
|
|
color: #f5f5f7;
|
|
font-size: 15px;
|
|
font-weight: 600;
|
|
white-space: nowrap;
|
|
box-shadow: inset 0 1px 0 oklch(1 0 0 / 0.1);
|
|
cursor: pointer;
|
|
text-decoration: none;
|
|
transition: background-color 0.15s ease;
|
|
}
|
|
|
|
.rn-notes:hover { background: oklch(1 0 0 / 0.12); color: #f5f5f7; }
|
|
|
|
.rn-notes-arrow {
|
|
width: 30px;
|
|
height: 30px;
|
|
border-radius: 50%;
|
|
background: #f5f5f7;
|
|
color: #101013;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
flex: none;
|
|
}
|
|
|
|
/* ── The card pictures ─────────────────────────────────────────────────── */
|
|
|
|
.rn-vis {
|
|
position: absolute;
|
|
inset: 0;
|
|
color: #f5f5f7;
|
|
font-family: var(--font-system);
|
|
}
|
|
|
|
.rn-vis-road > svg,
|
|
.rn-vis-trail > svg { position: absolute; inset: 0; width: 100%; height: 100%; }
|
|
|
|
.rn-vis-icon {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
color: oklch(1 0 0 / 0.55);
|
|
}
|
|
|
|
/* Places API: the index answering a search while it is typed. */
|
|
.rn-vis-places {
|
|
padding: 9px 12px;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 6px;
|
|
}
|
|
|
|
/* The same wordmark the API keys card leads with, centred; its pill text inverts against the tile. */
|
|
.rn-vis-trekbadge { align-self: center; display: flex; align-items: center; height: 24px; }
|
|
|
|
.rn-vis-trekmark { display: block; height: 20px; width: auto; color: #f5f5f7; }
|
|
|
|
.rn-vis-places .trek-mark .pill-fg { fill: #101013; }
|
|
|
|
.rn-vis-search {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 6px;
|
|
height: 22px;
|
|
padding: 0 9px;
|
|
border-radius: 8px;
|
|
background: oklch(1 0 0 / 0.08);
|
|
border: 1px solid oklch(1 0 0 / 0.16);
|
|
font-size: 10px;
|
|
font-weight: 500;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.rn-vis-search svg { width: 11px; height: 11px; flex: none; color: oklch(1 0 0 / 0.55); }
|
|
|
|
/* The query types itself out once, then the answer arrives under it. */
|
|
.rn-vis-typed {
|
|
display: inline-block;
|
|
max-width: 90px;
|
|
overflow: hidden;
|
|
white-space: nowrap;
|
|
animation: rn-type 1.3s steps(13, end) 0.7s both;
|
|
}
|
|
|
|
@keyframes rn-type { from { max-width: 0; } to { max-width: 90px; } }
|
|
|
|
.rn-vis-caret {
|
|
width: 1px;
|
|
height: 12px;
|
|
margin-left: -4px;
|
|
background: #f5f5f7;
|
|
animation: rn-caret 1s steps(1) infinite;
|
|
}
|
|
|
|
@keyframes rn-caret { 50% { opacity: 0; } }
|
|
|
|
.rn-vis-result {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 7px;
|
|
padding: 5px 8px;
|
|
border-radius: 8px;
|
|
background: oklch(1 0 0 / 0.07);
|
|
animation: rn-answer 0.3s ease 2.1s both;
|
|
}
|
|
|
|
@keyframes rn-answer { from { opacity: 0; transform: translateY(-3px); } to { opacity: 1; transform: none; } }
|
|
|
|
.rn-vis-cat {
|
|
width: 18px;
|
|
height: 18px;
|
|
border-radius: 50%;
|
|
border: 1.5px solid #ffffff;
|
|
color: #ffffff;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
flex: none;
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
.rn-vis-place { display: flex; flex-direction: column; min-width: 0; line-height: 1.2; }
|
|
|
|
.rn-vis-place span {
|
|
font-size: 10px;
|
|
font-weight: 600;
|
|
white-space: nowrap;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
}
|
|
|
|
.rn-vis-place small { font-size: 8.5px; color: oklch(1 0 0 / 0.5); }
|
|
|
|
@media (prefers-reduced-motion: reduce) {
|
|
.rn-vis-typed, .rn-vis-caret, .rn-vis-result { animation: none; }
|
|
}
|
|
|
|
[data-reduce-motion='true'] .rn-vis-typed,
|
|
[data-reduce-motion='true'] .rn-vis-caret,
|
|
[data-reduce-motion='true'] .rn-vis-result { animation: none; }
|
|
|
|
/* Road trip: the drive on the map, in the planner's route blue and marker style. */
|
|
.rn-vis-road-casing { fill: none; stroke: #0a5cc2; stroke-width: 5; stroke-linecap: round; stroke-linejoin: round; }
|
|
|
|
.rn-vis-road-line { fill: none; stroke: #0a84ff; stroke-width: 3; stroke-linecap: round; stroke-linejoin: round; }
|
|
|
|
.rn-vis-marker {
|
|
position: absolute;
|
|
width: 18px;
|
|
height: 18px;
|
|
margin: -9px 0 0 -9px;
|
|
border-radius: 50%;
|
|
border: 2px solid #ffffff;
|
|
box-sizing: border-box;
|
|
box-shadow: 0 1px 4px oklch(0 0 0 / 0.35);
|
|
color: #ffffff;
|
|
font-size: 8.5px;
|
|
font-weight: 700;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
font-variant-numeric: tabular-nums;
|
|
}
|
|
|
|
.rn-vis-distance {
|
|
position: absolute;
|
|
right: 9px;
|
|
bottom: 8px;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 4px;
|
|
padding: 2px 7px;
|
|
border-radius: 99px;
|
|
background: #f5f5f7;
|
|
color: #101013;
|
|
font-size: 9px;
|
|
font-weight: 600;
|
|
white-space: nowrap;
|
|
font-variant-numeric: tabular-nums;
|
|
}
|
|
|
|
/* Dawarich: a recorded day, in the trail colour the map draws it with. */
|
|
.rn-vis-trail-line { fill: none; stroke: #2563eb; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }
|
|
|
|
.rn-vis-trail-stay { fill: #ffffff; stroke: #2563eb; stroke-width: 2; }
|
|
|
|
/* Document sync: the wordmark, the two-way arrow under it, and the five stores in a row. */
|
|
.rn-vis-docs {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
gap: 4px;
|
|
padding: 8px 12px;
|
|
}
|
|
|
|
.rn-vis-docs .rn-vis-trekbadge { height: 22px; }
|
|
.rn-vis-docs .rn-vis-trekmark { height: 19px; }
|
|
|
|
.rn-vis-docs-flow { display: flex; color: oklch(1 0 0 / 0.55); transform: rotate(90deg); }
|
|
|
|
.rn-vis-docs-stores {
|
|
display: flex;
|
|
gap: 8px;
|
|
}
|
|
|
|
.rn-vis-docs-store {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
width: 34px;
|
|
height: 34px;
|
|
border-radius: 10px;
|
|
background: oklch(1 0 0 / 0.1);
|
|
box-shadow: inset 0 1px 0 oklch(1 0 0 / 0.18), inset 0 0 0 1px oklch(1 0 0 / 0.1);
|
|
}
|
|
|
|
/* The mark itself, unframed, with its corners rounded like an app icon. */
|
|
.rn-vis-brand {
|
|
position: absolute;
|
|
top: 12px;
|
|
left: 12px;
|
|
width: 58px;
|
|
height: 58px;
|
|
border-radius: 15px;
|
|
overflow: hidden;
|
|
box-shadow: 0 4px 14px oklch(0 0 0 / 0.45), 0 0 0 1px oklch(1 0 0 / 0.14);
|
|
}
|
|
|
|
/* A glass sheen over the mark: a soft light from the top and a bright inner edge. */
|
|
.rn-vis-brand::after {
|
|
content: '';
|
|
position: absolute;
|
|
inset: 0;
|
|
border-radius: inherit;
|
|
background: linear-gradient(160deg, oklch(1 0 0 / 0.42) 0%, oklch(1 0 0 / 0.08) 38%, transparent 55%, oklch(0 0 0 / 0.12) 100%);
|
|
box-shadow: inset 0 1px 0 oklch(1 0 0 / 0.55), inset 0 0 0 1px oklch(1 0 0 / 0.22);
|
|
pointer-events: none;
|
|
}
|
|
|
|
.rn-vis-brand img { display: block; width: 100%; height: 100%; }
|
|
|
|
/* ── Right: the note ───────────────────────────────────────────────────── */
|
|
|
|
.rn-note {
|
|
position: relative;
|
|
background: var(--bg-card);
|
|
color: var(--text-primary);
|
|
display: flex;
|
|
flex-direction: column;
|
|
min-height: 0;
|
|
}
|
|
|
|
.rn-note-body {
|
|
flex: 1;
|
|
min-height: 0;
|
|
padding: 44px 44px 26px;
|
|
display: flex;
|
|
flex-direction: column;
|
|
overflow-y: auto;
|
|
scrollbar-width: none;
|
|
}
|
|
|
|
.rn-note-body::-webkit-scrollbar { display: none; }
|
|
|
|
/*
|
|
* The two columns scroll; what is inside them must not give way instead. A flex
|
|
* item may shrink below its content, and one with overflow hidden may shrink to
|
|
* nothing, so on a 1080p screen at 100% the promise box was pressed down to its
|
|
* label while the paragraphs around it kept their height and the column scrolled.
|
|
*/
|
|
.rn-release-inner > *,
|
|
.rn-note-body > * { flex-shrink: 0; }
|
|
|
|
.rn-note-eyebrow {
|
|
font-family: var(--font-subtext);
|
|
font-size: 11px;
|
|
line-height: 14px;
|
|
font-weight: 600;
|
|
letter-spacing: 0.2em;
|
|
text-transform: uppercase;
|
|
color: var(--text-muted);
|
|
}
|
|
|
|
.rn-note-title {
|
|
word-break: auto-phrase;
|
|
margin: 14px 0 0;
|
|
font-size: 29px;
|
|
font-weight: 600;
|
|
line-height: 1.2;
|
|
letter-spacing: -0.03em;
|
|
max-width: 420px;
|
|
text-wrap: pretty;
|
|
}
|
|
|
|
.rn-note p {
|
|
margin: 20px 0 0;
|
|
font-size: 16px;
|
|
line-height: 1.66;
|
|
color: var(--text-secondary);
|
|
text-wrap: pretty;
|
|
}
|
|
|
|
.rn-note p + p { margin-top: 14px; }
|
|
|
|
/*
|
|
* The promise is a pane of glass in the inverse of the note: dark on a light note,
|
|
* light on a dark one, with the same sheen and edge light as the release cards.
|
|
*/
|
|
.rn-promise {
|
|
position: relative;
|
|
isolation: isolate;
|
|
overflow: hidden;
|
|
margin-top: 24px;
|
|
padding: 18px 20px;
|
|
border-radius: 18px;
|
|
background: linear-gradient(
|
|
160deg,
|
|
color-mix(in oklch, var(--text-primary) 94%, transparent) 0%,
|
|
color-mix(in oklch, var(--text-primary) 80%, transparent) 100%
|
|
);
|
|
border: 1px solid color-mix(in oklch, var(--text-primary) 55%, transparent);
|
|
backdrop-filter: blur(16px) saturate(1.3);
|
|
-webkit-backdrop-filter: blur(16px) saturate(1.3);
|
|
box-shadow: inset 0 1px 0 oklch(1 0 0 / 0.2), 0 16px 34px -20px oklch(0 0 0 / 0.6);
|
|
color: var(--bg-primary);
|
|
}
|
|
|
|
/* The edge light along the top, as on the cards. */
|
|
.rn-promise::before {
|
|
content: '';
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
right: 0;
|
|
height: 1px;
|
|
background: linear-gradient(90deg, transparent, oklch(1 0 0 / 0.5), transparent);
|
|
z-index: 1;
|
|
}
|
|
|
|
/* A soft light falling in from the top left, and a faint glow where it leaves. */
|
|
.rn-promise::after {
|
|
content: '';
|
|
position: absolute;
|
|
inset: 0;
|
|
background:
|
|
radial-gradient(120% 110% at 0% 0%, oklch(1 0 0 / 0.16) 0%, transparent 55%),
|
|
radial-gradient(80% 90% at 100% 100%, oklch(0.84 0.18 85 / 0.12) 0%, transparent 60%);
|
|
pointer-events: none;
|
|
z-index: -1;
|
|
}
|
|
|
|
.rn-promise-label {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 9px;
|
|
font-family: var(--font-subtext);
|
|
font-size: 10.5px;
|
|
font-weight: 600;
|
|
letter-spacing: 0.16em;
|
|
text-transform: uppercase;
|
|
color: color-mix(in oklch, var(--bg-primary) 55%, transparent);
|
|
}
|
|
|
|
.rn-promise-text {
|
|
margin-top: 9px;
|
|
font-size: 16.5px;
|
|
line-height: 1.5;
|
|
letter-spacing: -0.01em;
|
|
text-wrap: pretty;
|
|
}
|
|
|
|
.rn-promise-text b { font-weight: 600; }
|
|
|
|
.rn-promise-text span { font-weight: 400; color: color-mix(in oklch, var(--bg-primary) 68%, transparent); }
|
|
|
|
.rn-closing {
|
|
margin-top: auto;
|
|
padding-top: 24px;
|
|
font-size: 16.5px;
|
|
font-weight: 600;
|
|
letter-spacing: -0.02em;
|
|
color: var(--text-primary);
|
|
}
|
|
|
|
.rn-support {
|
|
padding: 22px 44px 26px;
|
|
border-top: 1px solid var(--border-primary);
|
|
background: var(--bg-hover);
|
|
}
|
|
|
|
.rn-support-text {
|
|
font-size: 15.5px;
|
|
line-height: 1.62;
|
|
color: var(--text-secondary);
|
|
text-wrap: pretty;
|
|
}
|
|
|
|
.rn-support-text b { font-weight: 600; color: var(--text-primary); }
|
|
|
|
.rn-support-buttons {
|
|
margin-top: 14px;
|
|
display: grid;
|
|
grid-template-columns: 1fr 1fr;
|
|
gap: 10px;
|
|
}
|
|
|
|
.rn-support-btn {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
gap: 9px;
|
|
height: 50px;
|
|
border-radius: 15px;
|
|
font-size: 15.5px;
|
|
font-weight: 600;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.04em;
|
|
box-shadow: 0 2px 6px oklch(0 0 0 / 0.1);
|
|
cursor: pointer;
|
|
border: 0;
|
|
transition: filter 0.15s ease;
|
|
}
|
|
|
|
.rn-support-btn:hover { filter: brightness(0.96); }
|
|
|
|
/* The steam lifts off the cup in turn, and the heart beats. */
|
|
.rn-coffee { overflow: visible; }
|
|
.rn-steam { stroke-width: 1.8; animation: rn-steam 3s ease-in-out infinite; }
|
|
.rn-steam:nth-of-type(4) { animation-delay: 0.5s; }
|
|
.rn-steam:nth-of-type(5) { animation-delay: 1s; }
|
|
|
|
@keyframes rn-steam {
|
|
0% { opacity: 0; transform: translate(0, 3px); }
|
|
25% { opacity: 1; transform: translate(-0.7px, -1px); }
|
|
55% { opacity: 0.85; transform: translate(0.7px, -5px); }
|
|
100% { opacity: 0; transform: translate(-0.4px, -10px); }
|
|
}
|
|
|
|
.rn-heart { transform-origin: 50% 55%; animation: rn-beat 1.3s ease-in-out infinite; }
|
|
|
|
@keyframes rn-beat {
|
|
0%, 60%, 100% { transform: scale(1); }
|
|
15% { transform: scale(1.2); }
|
|
30% { transform: scale(1); }
|
|
45% { transform: scale(1.12); }
|
|
}
|
|
|
|
@media (prefers-reduced-motion: reduce) {
|
|
.rn-steam, .rn-heart { animation: none; }
|
|
}
|
|
|
|
[data-reduce-motion='true'] .rn-steam,
|
|
[data-reduce-motion='true'] .rn-heart { animation: none; }
|
|
|
|
/* Brand colours: Buy Me a Coffee and Ko-fi own these. */
|
|
.rn-support-bmc { background: #ffdd00; color: #101013; } /* theme-lint-disable */
|
|
.rn-support-kofi { background: #ff5e5b; color: #ffffff; } /* theme-lint-disable */
|
|
|
|
/* Narrow viewports: keep the proportions, drop the outer padding. */
|
|
@media (max-width: 900px) {
|
|
.rn-overlay { padding: 0; }
|
|
.rn-panel { border-radius: 0; border: 0; max-height: 100%; }
|
|
}
|