: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); } }