flowtrack/static/styles.css
rope 94372c6abc Flowtrack: private period tracker with cycle predictions
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 08:37:13 +01:00

368 lines
12 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; }
.day.today::after {
content: "";
position: absolute;
inset: -3px;
border: 2px solid var(--ink);
border-radius: 999px;
}
.day .marks { position: absolute; bottom: 12%; display: flex; gap: 3px; }
.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-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; }
.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); }
.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-dates { display: grid; gap: 8px; }
.seed-form .seed-length { max-width: 120px; }
/* 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); }
}