:root{--bg:#08090A;--bg2:#0B0C0D;--card:#141619;--line:#1E2126;--ink:#F4F4F5;--mute:#9EA1AD;--green:#00E37A;--red:#FF5C5C;--sleep:#2A2D33;--amber:#F0B23C;
--font-body:"Plus Jakarta Sans",system-ui,-apple-system,sans-serif;--font-display:"Space Grotesk",system-ui,sans-serif;--font-mono:"IBM Plex Mono",monospace;
--space-8:8px;--space-12:12px;--space-16:16px;--space-20:20px;--space-24:24px;--space-32:32px;--space-40:40px;
--radius-card:18px;--radius-input:16px;--radius-sheet:32px;--radius-pill:999px}
*{box-sizing:border-box}html{background:var(--bg);color:var(--ink);font:16px/1.4 var(--font-body)}
body{margin:0;padding:0 var(--space-16) var(--space-40)}
main{max-width:520px;margin-inline:auto}
.top{max-width:520px;margin-inline:auto;padding:var(--space-16) 0}.wordmark{height:60px}
.eyebrow{font-size:12px;letter-spacing:.14em;text-transform:uppercase;color:var(--mute)}
.big{font-family:var(--font-display);font-weight:600;font-size:44px;letter-spacing:-.03em}
.mono{font-family:var(--font-mono);font-size:13px}
.muted{color:var(--mute)}.drift{color:var(--red)}
.row{display:flex;justify-content:space-between;align-items:baseline}
.bar{height:6px;background:var(--line);border-radius:var(--radius-pill);margin-top:var(--space-8)}.bar span{display:block;height:100%;background:var(--green);border-radius:var(--radius-pill)}
.ringwrap{display:flex;justify-content:center;padding:var(--space-16) 0}.ringwrap svg{width:min(320px,80vw);height:auto}
.now{display:flex;justify-content:space-between;align-items:flex-start;gap:var(--space-12);padding:var(--space-12) 0;border-top:1px solid var(--line);border-bottom:1px solid var(--line)}
.dot{display:inline-block;width:8px;height:8px;border-radius:50%;background:var(--green);margin-inline-end:var(--space-8)}
.nowlabel{font-weight:700;font-size:22px}
.btn{background:var(--card);color:var(--ink);border:1px solid var(--line);border-radius:var(--radius-pill);padding:var(--space-12) var(--space-16);font:inherit;cursor:pointer;list-style:none}
.btn.primary{background:var(--green);color:var(--bg);border-color:var(--green);font-weight:700}
.btn.ghost{background:transparent}
.btn.linklike{background:transparent;border-color:transparent;text-decoration:underline;color:var(--mute);padding:var(--space-8) var(--space-16)}
a.link-mute{color:var(--mute);text-decoration:none}
a.link-mute:hover,a.link-mute:focus-visible{text-decoration:underline}
/* The "Today accounted for" block (label/percentage/bar) is a single link
   to Sweep -- same "plain-looking text that's actually a link" convention
   as .link-mute just below it on this page, not new button chrome: no
   colour/underline of its own (color:inherit leaves .eyebrow/.big/.drift's
   real colours untouched), only a subtle hover/focus affordance on the
   label, mirroring .link-mute's own hover/focus underline reveal. block
   display so the label/row/bar stack exactly as they did as bare section
   children. */
a.coverage-link{display:block;color:inherit;text-decoration:none}
a.coverage-link:hover .eyebrow,a.coverage-link:focus-visible .eyebrow{text-decoration:underline}
summary{list-style:none}summary::-webkit-details-marker{display:none}summary::marker{display:none}
.switch>summary::after,.splitgap>summary::after,.splitblock>summary::after,.confirm>summary::after,.reclassify>summary::after{content:'+';margin-inline-start:var(--space-8);font-weight:700;display:inline-block}
.switch[open]>summary::after,.splitgap[open]>summary::after,.splitblock[open]>summary::after,.confirm[open]>summary::after,.reclassify[open]>summary::after{content:'\2715'}
.switch{position:relative}
/* Once open, the sheet has its own header+close (see _sheet_header.html) --
   the trigger that opened it is no longer needed for anything and used to
   sit awkwardly inside the fixed-position sheet, visually overlapping real
   tile options. visibility (not display) so .actions' flex layout doesn't
   reflow when it disappears. */
.switch[open]>summary{visibility:hidden}
.switch:not([open]) .grid{display:none}
.switch[open] .grid{position:fixed;left:0;right:0;bottom:0;top:auto;width:100%;max-width:520px;margin-inline:auto;margin-top:0;z-index:2;
  background:var(--bg2);padding:var(--space-24) var(--space-16) var(--space-32);border-radius:var(--radius-sheet) var(--radius-sheet) 0 0;
  border:1px solid var(--line);border-bottom:none;box-shadow:0 -8px 32px rgba(0,0,0,.5);max-height:70vh;overflow-y:auto}
.switch[open] .grid::before{content:'';position:absolute;top:10px;left:50%;transform:translateX(-50%);width:36px;height:4px;border-radius:var(--radius-pill);background:var(--line)}
/* Reusable sheet header (see _sheet_header.html): a label plus an explicit
   close control fixed to the sheet's own top-right corner, independent of
   wherever the trigger that opened it happens to sit -- the trigger used
   to double as the only way to dismiss, which put it awkwardly inside the
   opened grid alongside real options. */
.sheet-header{position:relative;display:flex;align-items:center;min-height:24px;margin-bottom:var(--space-16)}
.grid>.sheet-header{grid-column:1/-1}
.sheet-close{position:absolute;top:-8px;right:-8px;background:transparent;border:none;color:var(--mute);font-size:22px;line-height:1;cursor:pointer;padding:var(--space-8)}
.grid{display:grid;grid-template-columns:repeat(4,1fr);gap:var(--space-8);margin-top:var(--space-12)}
.tile{border-radius:var(--radius-card);padding:var(--space-16) var(--space-8);font:inherit;font-size:13px;cursor:pointer;background:#0F1A14;color:var(--green);border:1px solid #1E4D35}
.tile.drift{background:#1A1012;color:var(--red);border-color:#4D2121}
.timeline{margin-top:var(--space-16)}.slot{display:flex;gap:var(--space-12);margin-bottom:var(--space-8)}.slot .t{color:var(--mute);width:44px;padding-top:var(--space-16);flex:none}
.card{flex:1;border-radius:var(--radius-card);padding:var(--space-16);border:1px solid var(--line);background:var(--card)}
/* Ring info sheets (Period view's .period-info, Phase 3; Detail view's
   .entry-info/.start-info popovers, Phase 4): no visible trigger of their
   own (the ring itself is the trigger, see today.html's inline scripts) --
   closed is fully invisible, not just collapsed, since there's nothing to
   show until a tap opens one. Reuses .card's own look once open rather
   than new styling. */
.period-info:not([open]),.entry-info:not([open]),.start-info:not([open]){display:none}
.period-info[open],.entry-info[open],.start-info[open]{border-radius:var(--radius-card);padding:var(--space-16);border:1px solid var(--line);background:var(--card);margin-top:var(--space-12)}
/* Ring selection (Phase 5): the ring's own visual echo of whichever info
   sheet/popover is open (see today.html's toggle listeners) -- a spatial/
   opacity change only, never a fill-colour change, since fill colour is
   load-bearing (the chosen/drift intent ramp) and recolouring it for
   selection would risk misreading as a different ratio than reality.
   [data-period]/[data-entry] pop outward via a per-element --dx/--dy
   (embedded by ring.py from that element's own real angle -- a generic
   CSS rule can't know which direction "outward" is on its own).
   [data-start] (a tick, not a wedge) instead scales longer, anchored at
   its own inner point (transform-origin, also embedded by ring.py) rather
   than the default bounding-box centre, so it grows outward away from the
   ring instead of also eating into the ring band -- scaling doubles as
   "thicker" too, since CSS transform scales the whole rendered stroke. */
[data-period],[data-entry],[data-start]{transition:opacity .15s ease,transform .15s ease}
[data-period].dimmed,[data-entry].dimmed,[data-start].dimmed{opacity:.3}
[data-period].selected,[data-entry].selected{transform:translate(var(--dx,0px),var(--dy,0px))}
[data-start].selected{transform:scale(1.4)}
.card summary{cursor:pointer}.card b{display:block;font-weight:700}.card small{color:var(--mute)}
.card.chosen{background:#0C1A12;border-color:#1E4D35}.card.chosen b{color:var(--green)}
.card.drift{background:#1C0F10;border-color:#4D2121}.card.drift b{color:var(--red)}
.card.sleep{background:var(--card);color:var(--mute)}
.card.verified{border-width:2px}
.card.gap{background:#1A1C20;border:1px dashed var(--line)}.card.gap b{color:var(--mute)}   /* #1A1C20 = ring.py's TRACK, the ring's own unlogged-gray -- was sharing .card.drift's red before, indistinguishable from a real drifted card */
.actions{display:flex;gap:var(--space-8);margin-top:var(--space-12)}
.login{padding:var(--space-40) 0}.login h1{font-weight:700;font-size:32px;letter-spacing:-.03em}
.login input{width:100%;padding:var(--space-12);border-radius:var(--radius-input);border:1px solid var(--line);background:var(--card);color:var(--ink);font:inherit;margin:var(--space-12) 0}
:focus-visible{outline:2px solid var(--green);outline-offset:2px}
@media (prefers-reduced-motion:no-preference){.bar span{transition:width .4s}}
.h1{font-weight:700;font-size:30px;letter-spacing:-.03em;margin:var(--space-8) 0 var(--space-8)}
.h2{display:block;font-weight:700;font-size:22px;margin:var(--space-8) 0 var(--space-8)}
.green{color:var(--green)}.small{font-size:13px}.wide{width:100%;margin-top:var(--space-12);padding:var(--space-16);border-radius:var(--radius-pill)}
.tile.sel{position:relative;display:flex;flex-direction:column;align-items:center;gap:var(--space-8);background:var(--card);color:var(--mute);border-color:var(--line)}
.tile.sel input{position:absolute;opacity:0;inset:0}.tile.sel:has(input:checked){background:#0F1A14;color:var(--green);border-color:var(--green)}
.tile.sel b{font-family:var(--font-display);font-size:22px;color:var(--ink)}.tile.sel:has(input:checked) b{color:var(--green)}
/* Intent-aware selectable tiles (split's segment picker): the base .tile
   intent color applies whether or not selected -- selection highlights
   with a bolder border in that SAME color, never an override to green
   regardless of intent. Plain .tile.sel above (duration picker, focus's
   activity picker) has no intent to preserve and keeps its old behavior. */
.tile.chosen.sel{background:#0F1A14;color:var(--green);border-color:#1E4D35}
.tile.drift.sel{background:#1A1012;color:var(--red);border-color:#4D2121}
.tile.chosen.sel:has(input:checked){border-color:var(--green);border-width:2px}
.tile.drift.sel:has(input:checked){border-color:var(--red);border-width:2px}
.insight{background:#0C1A12;border:1px solid #1E4D35;border-radius:var(--radius-card);padding:var(--space-16);margin:var(--space-16) 0}
.center{text-align:center}.pill{display:inline-block;padding:var(--space-8) var(--space-20);border-radius:var(--radius-pill);background:#0F1A14;color:var(--green);border:1px solid #1E4D35;font-weight:700}
.timer{position:relative;display:inline-block;margin:var(--space-24) 0 var(--space-8)}.timerlabel{position:absolute;inset:0;display:flex;flex-direction:column;justify-content:center}
.actions.center{justify-content:center}.btn.danger{background:#1C0F10;color:var(--red);border-color:#4D2121}
.stack{display:flex;flex-direction:column;gap:var(--space-12)}
.row-btn{text-align:start;padding:var(--space-16);padding-inline-end:var(--space-32);border-radius:var(--radius-card);position:relative}
.row-btn::after{content:'\203A';position:absolute;inset-inline-end:var(--space-16);top:50%;transform:translateY(-50%);color:var(--mute);font-size:20px}
.gapcard{margin-bottom:var(--space-12)}.gapcard b{font-size:18px}.chosen-ink{color:var(--green)}.drift-ink{color:var(--red)}
.in{flex:1;padding:var(--space-12);border-radius:var(--radius-input);border:1px solid var(--line);background:var(--bg2);color:var(--ink);font:inherit}
textarea.in{width:100%;min-height:120px;resize:vertical;display:block;margin-top:var(--space-12)}
.chips{display:flex;gap:var(--space-8);flex-wrap:wrap;margin-top:var(--space-12)}
.chip{position:relative;display:inline-flex;cursor:pointer}
.chip input{position:absolute;opacity:0;inset:0;margin:0}
.chip span{padding:var(--space-8) var(--space-16);border-radius:var(--radius-pill);background:var(--card);color:var(--mute);border:1px solid var(--line)}
.chip:has(input:checked) span{background:#0F1A14;color:var(--green);border-color:var(--green)}
.actions.split>*{flex:1;text-align:center}
.cutrow{display:flex;gap:var(--space-8);align-items:center}
.cutrow .remove-cut{flex:none;padding:var(--space-8) var(--space-12);font-size:18px;line-height:1}
.notif{background:#1A1C20;border-radius:22px;padding:var(--space-16);margin-top:var(--space-24)}.grid.three{grid-template-columns:repeat(3,1fr)}
.mono-num{font-variant-numeric:tabular-nums}
nav.tabs{display:flex;gap:var(--space-16);margin-top:var(--space-8)}nav.tabs a{color:var(--mute);text-decoration:none;padding:var(--space-8) var(--space-16);border-radius:var(--radius-pill);border:1px solid var(--ink)}
nav.tabs a.on{color:var(--bg);background:var(--ink);font-weight:700}
.filterrow{display:flex;gap:var(--space-8);flex-wrap:wrap;margin:var(--space-16) 0}
.filterrow a{padding:var(--space-8) var(--space-16);border-radius:var(--radius-pill);background:var(--card);color:var(--mute);border:1px solid var(--line);text-decoration:none;font-size:13px}
.filterrow a.on{background:var(--ink);color:var(--bg);font-weight:700;border-color:var(--ink)}
.journal-day{display:flex;align-items:center;gap:var(--space-12);margin:var(--space-24) 0 var(--space-12)}
.journal-ring{flex:none;width:42px;height:42px}.journal-ring svg{width:42px;height:42px}
.journal-thread-note{margin-top:var(--space-12);padding-top:var(--space-12);border-top:1px solid var(--line)}
.history-cards{display:grid;gap:var(--space-16);margin-top:var(--space-20);justify-items:center}
.history-card{display:flex;flex-direction:column;align-items:center;gap:var(--space-8);text-decoration:none;color:var(--ink);position:relative}
.history-ring{display:block;position:relative}.history-ring svg{width:100%;height:100%}
.history-date{font-size:12px;color:var(--mute)}
.history-notedot{display:flex;align-items:center;gap:4px;font-size:11px;color:var(--mute);position:absolute;top:-2px;right:-2px}
.history-notedot .dot{width:6px;height:6px;margin-inline-end:0;background:var(--green)}
.history-chipgrid{display:grid;grid-auto-flow:column;grid-template-rows:repeat(7,1fr);gap:3px;overflow-x:auto;padding:var(--space-16) 0;margin-top:var(--space-8)}
.history-chip{width:12px;height:12px;border-radius:3px;display:block;position:relative}
.history-chip.empty{background:transparent}
.chip-dot{position:absolute;top:-2px;right:-2px;width:5px;height:5px;border-radius:50%;background:var(--ink)}

.period-row{display:flex;flex-direction:column;gap:var(--space-8)}
.period-row .actions{margin-top:0}
.period-row .row1-badge{display:none}
/* Row 1's resolver defines where the whole day starts (day_boundaries()
   treats parts[0] specially) -- this already caused one real, shipped bug
   (4 Part Day's original ordering), so whichever row is physically first
   gets a persistent, hard-to-miss badge and border, kept in sync by JS on
   every add/remove/reorder, not a one-time instructions paragraph. */
.period-row.is-first{border-color:var(--amber);border-width:2px}
.period-row.is-first .row1-badge{display:inline-block;width:max-content}
.pill.row1-badge{background:#2A1F0A;color:var(--amber);border-color:#4D3B14;font-size:12px;padding:var(--space-8) var(--space-12)}
.field-clock,.field-solar,.field-prayer{display:flex;gap:var(--space-8)}
/* An open block past a flat 3-hour threshold (see today() /
   LONG_OPEN_THRESHOLD_MIN) -- amber like row1-badge above (attention, not
   the red/green chosen-vs-drift intent colors, since this doesn't know or
   claim which one applies), but block-level and wider since this needs to
   be genuinely hard to miss, not a small inline tag. */
.pill.long-open{display:block;width:100%;text-align:center;box-sizing:border-box;background:#2A1F0A;color:var(--amber);border-color:#4D3B14;font-size:13px;margin-top:var(--space-12)}

@media (min-width:768px){
  main,.top{max-width:680px}
  body{padding-inline:var(--space-24)}
  .login{max-width:400px;margin-inline:auto}
}
@media (min-width:1200px){
  body{padding:var(--space-32)}
  .top{max-width:1200px}
  body.dashboard main{max-width:1200px;display:grid;grid-template-columns:430px 1fr;gap:var(--space-20);align-items:start}
}
