/* 75 — a daily log for one person, opened on a phone. The look is municipal pool tile: a pale aqua ground, grout lines, deep navy-teal ink, chlorine blue for anything that fills, and the orange of backstroke flags for the day you are standing on. */ :root { --tile: #E6EEEF; --grout: #C6D6DA; --chalk: #FBFDFD; --ink: #0E3140; --ink-soft: #557987; --lane: #0F7391; --lane-wash: rgba(15, 115, 145, 0.16); --flag: #D8471C; --flag-wash: rgba(216, 71, 28, 0.14); --display: "Avenir Next Condensed", "Arial Narrow", Impact, sans-serif; --body: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace; --gap: 0.5rem; --radius: 3px; } @media (prefers-color-scheme: dark) { :root { --tile: #0B1E27; --grout: #1F3F4D; --chalk: #102A35; --ink: #DCEAED; --ink-soft: #7E9EA9; --lane: #3FA9CC; --lane-wash: rgba(63, 169, 204, 0.20); --flag: #FF7043; --flag-wash: rgba(255, 112, 67, 0.18); } } *, *::before, *::after { box-sizing: border-box; } html { -webkit-text-size-adjust: 100%; } body { margin: 0; background: var(--tile); color: var(--ink); font-family: var(--body); font-size: 16px; line-height: 1.45; -webkit-font-smoothing: antialiased; } a { color: var(--lane); } .sr-only { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap; } :focus-visible { outline: 2px solid var(--flag); outline-offset: 2px; } .page { max-width: 34rem; margin: 0 auto; padding: 1.25rem 1rem calc(2rem + env(safe-area-inset-bottom)); } .page-narrow { max-width: 26rem; } /* ----------------------------------------------------------- masthead */ .masthead { margin-bottom: 1.5rem; } .masthead-nav { display: grid; grid-template-columns: 3rem 1fr 3rem; align-items: center; } .step { display: block; font-family: var(--display); font-size: 2.5rem; line-height: 1; text-align: center; text-decoration: none; color: var(--ink-soft); border-radius: var(--radius); padding: 0.25rem 0; } .step.is-spent { opacity: 0.2; } .masthead-day { text-align: center; } .eyebrow { margin: 0; font-family: var(--mono); font-size: 0.7rem; letter-spacing: 0.24em; text-transform: uppercase; color: var(--ink-soft); } .masthead-count { margin: 0; font-family: var(--display); font-size: clamp(4.5rem, 22vw, 6.5rem); font-weight: 600; line-height: 0.82; letter-spacing: -0.01em; font-variant-numeric: tabular-nums; } .masthead-count.is-spent { color: var(--ink-soft); } .masthead-of { margin: 0.15rem 0 0; font-family: var(--mono); font-size: 0.75rem; letter-spacing: 0.1em; color: var(--ink-soft); } .masthead-date { margin: 0.9rem 0 0; text-align: center; font-size: 0.95rem; color: var(--ink-soft); } .masthead-date b { color: var(--ink); } .masthead-back { margin-left: 0.5rem; white-space: nowrap; } .notice, .alert, .flash { margin: 1rem 0 0; padding: 0.65rem 0.85rem; border-radius: var(--radius); font-size: 0.9rem; } .notice { background: var(--lane-wash); } .flash { background: var(--lane-wash); } .alert { background: var(--flag-wash); color: var(--ink); } /* --------------------------------------------------------------- bands Every measurable thing is a band that fills. Protein and water fill towards a floor to reach; calories fill towards a ceiling, so the band itself is the budget and running past it turns the whole thing hot. */ .log { display: grid; gap: var(--gap); margin: 0; } .band { position: relative; display: grid; align-items: center; gap: 0 0.5rem; grid-template-columns: 1fr auto 2rem; grid-template-areas: "label entry tick" "note note tick"; min-height: 4.25rem; padding: 0.7rem 0.85rem; background: var(--chalk); border: 1px solid var(--grout); border-radius: var(--radius); overflow: hidden; } /* The fill runs inside a track that stops short of the tick, so a band at 99% never slides its water line underneath the verdict. */ .band-track { position: absolute; inset: 0 3.35rem 0 0; /* clears the tick column, its gap and the padding */ overflow: hidden; } /* The water line is painted as the last two pixels of the fill's own gradient rather than a border, so an empty band shows nothing at all. */ .band-fill { position: absolute; inset: 0 auto 0 0; width: var(--fill, 0%); background: linear-gradient(to right, var(--lane-wash) calc(100% - 2px), var(--lane) calc(100% - 2px)); transition: width 220ms ease-out; } .band-label { grid-area: label; position: relative; font-family: var(--display); font-size: 1.5rem; font-weight: 600; letter-spacing: 0.01em; } .band-note { grid-area: note; position: relative; font-family: var(--mono); font-size: 0.7rem; letter-spacing: 0.06em; text-transform: uppercase; color: var(--ink-soft); } .band-entry { grid-area: entry; position: relative; display: flex; align-items: baseline; gap: 0.3rem; } .band-input { width: 4.5ch; padding: 0; border: 0; border-bottom: 2px solid var(--grout); border-radius: 0; background: transparent; color: inherit; font-family: var(--mono); font-size: 1.5rem; font-variant-numeric: tabular-nums; text-align: right; appearance: textfield; } .band-input::-webkit-inner-spin-button, .band-input::-webkit-outer-spin-button { appearance: none; margin: 0; } .band-input:focus { outline: 0; border-bottom-color: var(--flag); } .band-unit { font-family: var(--mono); font-size: 0.75rem; color: var(--ink-soft); } .band-tick { grid-area: tick; position: relative; justify-self: end; font-size: 1.5rem; line-height: 1; color: var(--grout); } .band-tick::before { content: "○"; } .band.is-met { border-color: var(--lane); } .band.is-met .band-tick { color: var(--lane); } .band.is-met .band-tick::before { content: "●"; } /* Past the ceiling there is nothing left to measure, so the meter gives way to the whole band going hot. */ .band.is-over { border-color: var(--flag); background: var(--flag-wash); } .band.is-over .band-fill { background: none; } .band.is-over .band-tick { color: var(--flag); } .band.is-over .band-tick::before { content: "▲"; } /* the workout band is one tap on the whole thing */ .band-toggle { grid-template-areas: "label state tick"; grid-template-rows: auto; cursor: pointer; -webkit-tap-highlight-color: transparent; } .band-check { position: absolute; opacity: 0; width: 1px; height: 1px; } .band-check:focus-visible ~ .band-label { outline: 2px solid var(--flag); outline-offset: 3px; } .band-state { grid-area: state; font-family: var(--mono); font-size: 0.75rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--ink-soft); } .state-on { display: none; } .band-check:checked ~ .band-state .state-on { display: inline; color: var(--lane); } .band-check:checked ~ .band-state .state-off { display: none; } .band-toggle:active { transform: scale(0.995); } /* ----------------------------------------------------------- gratitude */ .gratitude { position: relative; margin: 0; padding: 0.7rem 0.85rem 0.9rem; background: var(--chalk); border: 1px solid var(--grout); border-radius: var(--radius); } .gratitude.is-met { border-color: var(--lane); } .gratitude legend { padding: 0 0.35rem; margin-left: -0.35rem; font-family: var(--display); font-size: 1.5rem; font-weight: 600; } .gratitude-hint { margin: 0 0 0.6rem; font-family: var(--mono); font-size: 0.7rem; letter-spacing: 0.06em; text-transform: uppercase; color: var(--ink-soft); } .gratitude-lines { list-style: none; counter-reset: line; margin: 0; padding: 0; display: grid; gap: 0.55rem; } .gratitude-lines li { counter-increment: line; display: grid; grid-template-columns: 1.25rem 1fr; align-items: center; } .gratitude-lines li::before { content: counter(line); font-family: var(--mono); font-size: 0.8rem; color: var(--ink-soft); } .gratitude-input { width: 100%; padding: 0.2rem 0; border: 0; border-bottom: 1px solid var(--grout); border-radius: 0; background: transparent; color: inherit; font-family: var(--body); font-size: 1rem; } .gratitude-input:focus { outline: 0; border-bottom-color: var(--flag); } /* --------------------------------------------------------------- saving */ .log-foot { display: flex; align-items: center; justify-content: space-between; gap: 1rem; margin-top: 0.25rem; } .save { display: inline-block; padding: 0.7rem 1.4rem; border: 0; border-radius: var(--radius); background: var(--ink); color: var(--tile); font-family: var(--display); font-size: 1.15rem; font-weight: 600; letter-spacing: 0.03em; text-decoration: none; cursor: pointer; } .save-quiet { background: transparent; color: var(--ink); border: 1px solid var(--grout); } .log-status { margin: 0; font-family: var(--mono); font-size: 0.72rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--lane); } .log-status.is-bad { color: var(--flag); } /* Once the page can save in the background, the button is only there for the no-JavaScript case. */ .has-sync .save-day { display: none; } /* ----------------------------------------------------------------- card Seventy-five tiles, fifteen across. Each one fills from the bottom by how many of the five that day hit, so a glance shows the texture of the whole challenge rather than a row of pass/fail. */ .card { margin-top: 2.25rem; } .card-heading { margin: 0 0 0.7rem; font-family: var(--mono); font-size: 0.7rem; letter-spacing: 0.24em; text-transform: uppercase; font-weight: 400; color: var(--ink-soft); } .card-grid { list-style: none; margin: 0; padding: 0; display: grid; /* minmax(0,…) rather than 1fr: a track that cannot shrink below its content pushes the fifteenth column off the edge on a narrow phone. */ grid-template-columns: repeat(15, minmax(0, 1fr)); gap: 3px; } .tile { position: relative; aspect-ratio: 1; background: var(--chalk); border: 1px solid var(--grout); border-radius: 1px; overflow: hidden; } .tile a { position: absolute; inset: 0; display: block; } .tile-fill { position: absolute; inset: auto 0 0 0; height: calc(var(--score, 0) * 20%); background: var(--lane); transition: height 220ms ease-out; } .tile-full { border-color: var(--lane); } .tile-ahead { background: transparent; border-style: dashed; opacity: 0.5; } .tile-today { outline: 2px solid var(--flag); outline-offset: 1px; z-index: 1; } .tally { display: grid; grid-template-columns: repeat(3, 1fr); gap: 0.5rem; margin: 1.25rem 0 0; padding: 0.9rem 0 0; border-top: 1px solid var(--grout); text-align: center; } .tally dt { font-family: var(--mono); font-size: 0.65rem; letter-spacing: 0.18em; text-transform: uppercase; color: var(--ink-soft); } .tally dd { margin: 0.1rem 0 0; font-family: var(--display); font-size: 2.5rem; font-weight: 600; line-height: 1; font-variant-numeric: tabular-nums; } .legend { list-style: none; margin: 1.1rem 0 0; padding: 0; display: grid; gap: 0.3rem; font-family: var(--mono); font-size: 0.72rem; color: var(--ink-soft); } .legend li { display: grid; grid-template-columns: 1fr auto; border-bottom: 1px dotted var(--grout); padding-bottom: 0.2rem; } .legend b { color: var(--ink); font-variant-numeric: tabular-nums; } /* --------------------------------------------------------------- sheets */ .sheet { margin: 1.5rem 0 0; padding: 1rem; background: var(--chalk); border: 1px solid var(--grout); border-radius: var(--radius); } .sheet-heading { margin: 0 0 0.5rem; font-family: var(--display); font-size: 1.5rem; font-weight: 600; } .sheet-note { margin: 0.9rem 0 0; font-size: 0.85rem; color: var(--ink-soft); } .field { margin-bottom: 1rem; } .field label { display: block; margin-bottom: 0.25rem; font-family: var(--mono); font-size: 0.7rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--ink-soft); } .field-row { display: flex; align-items: center; gap: 0.6rem; } .field input, .field select { padding: 0.5rem 0.6rem; border: 1px solid var(--grout); border-radius: var(--radius); background: var(--tile); color: inherit; font-family: var(--mono); font-size: 1rem; } .field-row input { width: 7rem; } .field-unit { font-size: 0.8rem; color: var(--ink-soft); } .restore { margin-top: 1.25rem; padding-top: 1rem; border-top: 1px solid var(--grout); display: grid; gap: 0.5rem; justify-items: start; } .restore label { font-family: var(--mono); font-size: 0.7rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--ink-soft); } .restore input { font-size: 0.85rem; } /* --------------------------------------------------------------- footer */ .footer { max-width: 34rem; margin: 0 auto; padding: 1.5rem 1rem calc(2rem + env(safe-area-inset-bottom)); display: flex; gap: 1.25rem; justify-content: center; font-family: var(--mono); font-size: 0.72rem; letter-spacing: 0.14em; text-transform: uppercase; } .footer a { color: var(--ink-soft); text-decoration: none; } .footer a:hover { color: var(--lane); } @media (prefers-reduced-motion: reduce) { *, *::before, *::after { transition-duration: 0.01ms !important; animation-duration: 0.01ms !important; } }