411 lines
14 KiB
CSS
411 lines
14 KiB
CSS
:root {
|
|
color-scheme: light dark;
|
|
--bg: #faf6f4;
|
|
--surface: #ffffff;
|
|
--surface-2: #f4eeec;
|
|
--ink: #2b2330;
|
|
--ink-2: #5d5463;
|
|
--muted: #847a89;
|
|
--line: #e9e1df;
|
|
--period: #cf3f66;
|
|
--period-soft: #f9dde5;
|
|
--period-ink: #ffffff;
|
|
--fertile: #1f8f8a;
|
|
--fertile-soft: #d6efed;
|
|
--focus: #6d4fc4;
|
|
--danger: #b3261e;
|
|
--shadow: 0 1px 2px rgb(43 35 48 / 6%), 0 4px 16px rgb(43 35 48 / 5%);
|
|
--radius: 18px;
|
|
--tabs-height: 64px;
|
|
font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text", system-ui, "Segoe UI", Roboto, sans-serif;
|
|
}
|
|
|
|
@media (prefers-color-scheme: dark) {
|
|
:root {
|
|
--bg: #18141b;
|
|
--surface: #221d26;
|
|
--surface-2: #2c2631;
|
|
--ink: #f2ecf3;
|
|
--ink-2: #c3b9c7;
|
|
--muted: #9a8f9f;
|
|
--line: #3a3340;
|
|
--period: #ee6b8d;
|
|
--period-soft: #4b2534;
|
|
--period-ink: #1e0b12;
|
|
--fertile: #4cc4bd;
|
|
--fertile-soft: #183937;
|
|
--focus: #a991f0;
|
|
--danger: #ff8a80;
|
|
--shadow: none;
|
|
}
|
|
}
|
|
|
|
* { box-sizing: border-box; }
|
|
|
|
html { -webkit-text-size-adjust: 100%; }
|
|
|
|
body {
|
|
margin: 0;
|
|
min-height: 100vh;
|
|
background: var(--bg);
|
|
color: var(--ink);
|
|
font-size: 16px;
|
|
line-height: 1.45;
|
|
-webkit-tap-highlight-color: transparent;
|
|
}
|
|
|
|
button, input, select { font: inherit; color: inherit; }
|
|
|
|
:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
|
|
|
|
h1, h2 { margin: 0; line-height: 1.2; }
|
|
h2 { font-size: 1.05rem; font-weight: 600; }
|
|
|
|
.topbar {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 10px;
|
|
max-width: 560px;
|
|
margin: 0 auto;
|
|
padding: calc(env(safe-area-inset-top) + 14px) 16px 6px;
|
|
}
|
|
.topbar h1 { font-size: 1.35rem; font-weight: 700; letter-spacing: -0.01em; }
|
|
|
|
.badge {
|
|
padding: 2px 10px;
|
|
border-radius: 999px;
|
|
background: var(--surface-2);
|
|
color: var(--ink-2);
|
|
font-size: 0.8rem;
|
|
font-weight: 600;
|
|
}
|
|
|
|
main {
|
|
max-width: 560px;
|
|
margin: 0 auto;
|
|
padding: 8px 16px calc(var(--tabs-height) + env(safe-area-inset-bottom) + 24px);
|
|
}
|
|
|
|
.view { display: grid; gap: 14px; }
|
|
.view[hidden] { display: none; }
|
|
|
|
.card {
|
|
background: var(--surface);
|
|
border-radius: var(--radius);
|
|
padding: 18px;
|
|
box-shadow: var(--shadow);
|
|
}
|
|
.card > h2 + .subtitle { margin-top: 4px; }
|
|
|
|
.subtitle { margin: 0 0 14px; color: var(--muted); font-size: 0.9rem; }
|
|
.footnote { margin: 0; padding: 0 4px; color: var(--muted); font-size: 0.8rem; text-align: center; }
|
|
|
|
.banner {
|
|
margin: 0 0 12px;
|
|
padding: 10px 14px;
|
|
border-radius: 12px;
|
|
background: var(--surface-2);
|
|
color: var(--ink);
|
|
font-size: 0.9rem;
|
|
}
|
|
.banner.error { color: var(--danger); }
|
|
|
|
/* Today */
|
|
|
|
.hero { text-align: center; padding: 26px 18px 22px; }
|
|
.hero .eyebrow { margin: 0; color: var(--muted); font-size: 0.85rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.06em; }
|
|
.hero .figure { margin: 4px 0 2px; font-size: 3.4rem; font-weight: 700; letter-spacing: -0.03em; line-height: 1.05; font-variant-numeric: tabular-nums; }
|
|
.hero .figure small { font-size: 1.1rem; font-weight: 600; color: var(--ink-2); letter-spacing: 0; }
|
|
.hero .lead { margin: 6px 0 0; font-size: 1.05rem; font-weight: 600; }
|
|
.hero .detail { margin: 2px 0 0; color: var(--ink-2); font-size: 0.92rem; }
|
|
.hero .note { margin: 14px auto 0; max-width: 34ch; color: var(--muted); font-size: 0.85rem; }
|
|
.hero.on-period .figure { color: var(--period); }
|
|
|
|
.facts { display: grid; gap: 10px; margin: 18px 0 0; padding: 16px 0 0; border-top: 1px solid var(--line); text-align: left; }
|
|
.fact { display: flex; align-items: center; gap: 12px; }
|
|
.fact .key { flex: none; }
|
|
.fact div { display: grid; }
|
|
.fact strong { font-size: 0.95rem; font-weight: 600; }
|
|
.fact span { color: var(--ink-2); font-size: 0.88rem; }
|
|
|
|
.log-section + .log-section { margin-top: 18px; }
|
|
.log-section h3 { margin: 0 0 10px; color: var(--ink-2); font-size: 0.85rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; }
|
|
|
|
.chips { display: flex; flex-wrap: wrap; gap: 8px; }
|
|
.chip {
|
|
min-height: 40px;
|
|
padding: 8px 14px;
|
|
border: 1.5px solid var(--line);
|
|
border-radius: 999px;
|
|
background: var(--surface);
|
|
font-size: 0.92rem;
|
|
font-weight: 500;
|
|
cursor: pointer;
|
|
touch-action: manipulation;
|
|
}
|
|
.chip[aria-pressed="true"] { border-color: var(--period); background: var(--period); color: var(--period-ink); }
|
|
.chip.symptom[aria-pressed="true"] { border-color: var(--ink); background: var(--ink); color: var(--surface); }
|
|
.chip:disabled { cursor: default; }
|
|
.chip:disabled:not([aria-pressed="true"]) { opacity: 0.55; }
|
|
|
|
.empty-log { margin: 0; color: var(--muted); font-size: 0.92rem; }
|
|
|
|
/* Buttons */
|
|
|
|
.button {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
min-height: 44px;
|
|
padding: 10px 18px;
|
|
border: 0;
|
|
border-radius: 12px;
|
|
background: var(--period);
|
|
color: var(--period-ink);
|
|
font-weight: 600;
|
|
text-decoration: none;
|
|
cursor: pointer;
|
|
}
|
|
.button.secondary { background: var(--surface-2); color: var(--ink); }
|
|
.button:disabled { opacity: 0.6; cursor: default; }
|
|
.button-row { display: flex; flex-wrap: wrap; gap: 10px; }
|
|
|
|
.icon-button {
|
|
display: grid;
|
|
place-items: center;
|
|
width: 40px;
|
|
height: 40px;
|
|
border: 0;
|
|
border-radius: 999px;
|
|
background: var(--surface-2);
|
|
font-size: 1.4rem;
|
|
line-height: 1;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.link-button {
|
|
display: block;
|
|
margin: 12px auto 0;
|
|
padding: 6px 10px;
|
|
border: 0;
|
|
background: none;
|
|
color: var(--ink-2);
|
|
font-size: 0.9rem;
|
|
font-weight: 600;
|
|
cursor: pointer;
|
|
}
|
|
|
|
/* Calendar */
|
|
|
|
.month-nav { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; }
|
|
.month-nav h2 { font-size: 1.1rem; }
|
|
|
|
.weekdays, .month-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 4px; }
|
|
.weekdays span { color: var(--muted); font-size: 0.75rem; font-weight: 600; text-align: center; }
|
|
.month-grid { margin-top: 6px; }
|
|
|
|
.day {
|
|
position: relative;
|
|
display: grid;
|
|
place-items: center;
|
|
aspect-ratio: 1;
|
|
min-width: 0;
|
|
border: 0;
|
|
border-radius: 999px;
|
|
background: transparent;
|
|
font-size: 0.95rem;
|
|
font-variant-numeric: tabular-nums;
|
|
cursor: pointer;
|
|
touch-action: manipulation;
|
|
}
|
|
.day.outside { visibility: hidden; }
|
|
.day.future { cursor: default; }
|
|
.day.fertile { background: var(--fertile-soft); }
|
|
.day.predicted { box-shadow: inset 0 0 0 2px var(--period); background: var(--period-soft); }
|
|
.day.period { background: var(--period); color: var(--period-ink); font-weight: 600; }
|
|
/* More than six weeks out: same marks, washed out. */
|
|
.day.fertile.faded { background: color-mix(in srgb, var(--fertile-soft) 45%, transparent); }
|
|
.day.predicted.faded {
|
|
background: color-mix(in srgb, var(--period-soft) 45%, transparent);
|
|
box-shadow: inset 0 0 0 1.5px color-mix(in srgb, var(--period) 40%, transparent);
|
|
}
|
|
.day.faded .flow, .day.faded .mark.ovulation { opacity: 0.45; }
|
|
.day.today::after {
|
|
content: "";
|
|
position: absolute;
|
|
inset: -3px;
|
|
border: 2px solid var(--ink);
|
|
border-radius: 999px;
|
|
}
|
|
.day .marks { position: absolute; bottom: 12%; display: flex; align-items: flex-end; gap: 3px; }
|
|
/* Flow strength as 1-3 rising bars, like signal strength. */
|
|
.flow { display: inline-flex; align-items: flex-end; gap: 1.5px; height: 8px; color: var(--period); }
|
|
.flow i { width: 3px; border-radius: 1px; background: currentColor; opacity: 0.3; }
|
|
.flow i:nth-child(1) { height: 4px; }
|
|
.flow i:nth-child(2) { height: 6px; }
|
|
.flow i:nth-child(3) { height: 8px; }
|
|
.flow i.on { opacity: 1; }
|
|
.day.period .flow { color: var(--period-ink); }
|
|
.legend .flow { width: 16px; justify-content: center; }
|
|
.day .mark { width: 5px; height: 5px; border-radius: 999px; }
|
|
.mark.ovulation { background: var(--fertile); }
|
|
.mark.spotting { background: var(--period); }
|
|
.mark.symptoms { background: var(--muted); }
|
|
.day.period .mark.symptoms { background: var(--period-ink); }
|
|
|
|
.legend { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 10px 16px; margin: 0; list-style: none; font-size: 0.9rem; color: var(--ink-2); }
|
|
.legend li { display: flex; align-items: center; gap: 10px; }
|
|
|
|
.key { display: inline-block; width: 16px; height: 16px; border-radius: 999px; }
|
|
.key-period { background: var(--period); }
|
|
.key-predicted { background: var(--period-soft); box-shadow: inset 0 0 0 2px var(--period); }
|
|
.key-fertile { background: var(--fertile-soft); }
|
|
.key-predicted.faded {
|
|
background: color-mix(in srgb, var(--period-soft) 45%, transparent);
|
|
box-shadow: inset 0 0 0 1.5px color-mix(in srgb, var(--period) 40%, transparent);
|
|
}
|
|
.key-ovulation { position: relative; background: var(--fertile-soft); }
|
|
.key-ovulation::after { content: ""; position: absolute; inset: 5px; border-radius: 999px; background: var(--fertile); }
|
|
.key-spotting, .key-symptoms { position: relative; }
|
|
.key-spotting::after, .key-symptoms::after { content: ""; position: absolute; inset: 5px; border-radius: 999px; }
|
|
.key-spotting::after { background: var(--period); }
|
|
.key-symptoms::after { background: var(--muted); }
|
|
|
|
/* Stats */
|
|
|
|
.tiles { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; }
|
|
.tile { background: var(--surface); border-radius: var(--radius); padding: 14px 16px; box-shadow: var(--shadow); }
|
|
.tile .label { margin: 0; color: var(--ink-2); font-size: 0.85rem; }
|
|
.tile .value { margin: 2px 0 0; font-size: 1.6rem; font-weight: 650; letter-spacing: -0.01em; font-variant-numeric: tabular-nums; }
|
|
.tile .value small { font-size: 0.95rem; font-weight: 500; color: var(--ink-2); }
|
|
|
|
.chart { position: relative; }
|
|
.chart svg { display: block; width: 100%; height: auto; overflow: visible; }
|
|
.chart .grid { stroke: var(--line); stroke-width: 1; }
|
|
.chart .axis-label { fill: var(--muted); font-size: 11px; }
|
|
.chart .bar { fill: var(--period); }
|
|
.chart .bar.dim { opacity: 0.35; }
|
|
.chart .avg { stroke: var(--ink-2); stroke-width: 1; stroke-dasharray: 3 3; }
|
|
.chart .avg-label { fill: var(--ink-2); font-size: 11px; font-weight: 600; }
|
|
.chart .hit { fill: transparent; cursor: pointer; }
|
|
.chart-empty { margin: 0; color: var(--muted); font-size: 0.92rem; }
|
|
.tooltip {
|
|
position: absolute;
|
|
z-index: 2;
|
|
padding: 6px 10px;
|
|
border-radius: 10px;
|
|
background: var(--ink);
|
|
color: var(--surface);
|
|
font-size: 0.82rem;
|
|
white-space: nowrap;
|
|
pointer-events: none;
|
|
transform: translate(-50%, calc(-100% - 8px));
|
|
}
|
|
.tooltip[hidden] { display: none; }
|
|
|
|
.upcoming { display: grid; margin: 0; padding: 0; list-style: none; font-size: 0.92rem; font-variant-numeric: tabular-nums; }
|
|
.upcoming li { display: flex; justify-content: space-between; gap: 12px; padding: 9px 0; border-top: 1px solid var(--line); }
|
|
.upcoming li:first-child { border-top: 0; padding-top: 0; }
|
|
.upcoming .when { font-weight: 600; }
|
|
.upcoming .likely { color: var(--ink-2); text-align: right; }
|
|
.upcoming .likely small { display: block; color: var(--muted); font-size: 0.78rem; }
|
|
.upcoming li.faded .when { color: var(--ink-2); font-weight: 500; }
|
|
|
|
.table-wrap { margin-top: 12px; overflow-x: auto; }
|
|
.history { width: 100%; border-collapse: collapse; font-size: 0.92rem; font-variant-numeric: tabular-nums; }
|
|
.history th { padding: 0 0 8px; color: var(--muted); font-size: 0.8rem; font-weight: 600; text-align: left; }
|
|
.history td { padding: 9px 0; border-top: 1px solid var(--line); }
|
|
.history th:not(:first-child), .history td:not(:first-child) { text-align: right; }
|
|
.history .excluded { color: var(--muted); }
|
|
.history .excluded small { display: block; font-size: 0.78rem; }
|
|
|
|
/* Settings */
|
|
|
|
.switch-row { display: flex; align-items: center; justify-content: space-between; gap: 16px; cursor: pointer; }
|
|
.switch-row span { display: grid; gap: 2px; }
|
|
.switch-row small { color: var(--muted); font-size: 0.85rem; }
|
|
.switch-row input { flex: none; width: 24px; height: 24px; accent-color: var(--period); }
|
|
|
|
.notify-body { display: grid; gap: 14px; justify-items: start; }
|
|
.notify-note { margin: 0; color: var(--ink-2); font-size: 0.92rem; }
|
|
.notify-status { display: flex; align-items: center; gap: 8px; margin: 0; font-weight: 600; }
|
|
.status-dot { width: 10px; height: 10px; border-radius: 999px; background: var(--fertile); }
|
|
.remind-row { display: flex; align-items: center; gap: 8px; color: var(--ink-2); font-size: 0.92rem; }
|
|
.remind-row select {
|
|
min-height: 40px;
|
|
padding: 6px 10px;
|
|
border: 1.5px solid var(--line);
|
|
border-radius: 10px;
|
|
background: var(--surface);
|
|
}
|
|
|
|
.seed-form { display: grid; gap: 12px; }
|
|
.seed-form label { display: grid; gap: 4px; color: var(--ink-2); font-size: 0.88rem; font-weight: 600; }
|
|
.seed-form input {
|
|
min-height: 44px;
|
|
padding: 8px 12px;
|
|
border: 1.5px solid var(--line);
|
|
border-radius: 12px;
|
|
background: var(--surface);
|
|
font-weight: 400;
|
|
}
|
|
.seed-rows { display: grid; gap: 10px; }
|
|
.seed-row { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
|
|
.seed-row input { width: 100%; min-width: 0; }
|
|
.seed-hint { margin: 0; color: var(--muted); font-size: 0.85rem; }
|
|
|
|
/* Tabs */
|
|
|
|
.tabs {
|
|
position: fixed;
|
|
inset: auto 0 0;
|
|
z-index: 5;
|
|
display: grid;
|
|
grid-template-columns: repeat(4, 1fr);
|
|
padding: 6px max(8px, env(safe-area-inset-left)) calc(6px + env(safe-area-inset-bottom));
|
|
border-top: 1px solid var(--line);
|
|
background: color-mix(in srgb, var(--surface) 92%, transparent);
|
|
-webkit-backdrop-filter: blur(16px);
|
|
backdrop-filter: blur(16px);
|
|
}
|
|
.tabs.three { grid-template-columns: repeat(3, 1fr); }
|
|
.tabs button {
|
|
display: grid;
|
|
justify-items: center;
|
|
gap: 2px;
|
|
min-height: 52px;
|
|
padding: 4px;
|
|
border: 0;
|
|
background: none;
|
|
color: var(--muted);
|
|
font-size: 0.72rem;
|
|
font-weight: 600;
|
|
cursor: pointer;
|
|
}
|
|
.tabs button[hidden] { display: none; }
|
|
.tabs svg { width: 24px; height: 24px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
|
|
.tabs button[aria-selected="true"] { color: var(--period); }
|
|
|
|
/* Day sheet */
|
|
|
|
.sheet {
|
|
width: min(560px, 100%);
|
|
max-width: 100%;
|
|
max-height: 90vh;
|
|
margin: auto auto 0;
|
|
padding: 0;
|
|
border: 0;
|
|
border-radius: 22px 22px 0 0;
|
|
background: var(--surface);
|
|
color: var(--ink);
|
|
}
|
|
.sheet::backdrop { background: rgb(0 0 0 / 35%); }
|
|
.sheet-inner { padding: 18px 18px calc(22px + env(safe-area-inset-bottom)); }
|
|
.sheet-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 16px; }
|
|
.sheet-head h2 { font-size: 1.15rem; }
|
|
.sheet .prediction-note { margin: 0 0 16px; color: var(--ink-2); font-size: 0.9rem; }
|
|
|
|
@media (min-width: 600px) {
|
|
.sheet { margin: auto; border-radius: 22px; }
|
|
.tiles { grid-template-columns: repeat(4, 1fr); }
|
|
}
|