/* ============================================================
   COMPONENTS

   Two families, kept deliberately apart:
     CONTENT  — goal cards. Rich, dimensional, colourful.
     CHROME   — island, sheets, toasts. Translucent, restrained.
   ============================================================ */

/* ============================================================
   FLOATING ISLAND — primary navigation
   ============================================================ */
/* A functional layer that floats clear of the content: translucent,
   blurred, and physically detached. Content passes beneath it. */
.island {
  position: fixed;
  left: 50%;
  bottom: calc(var(--safe-bottom) + 14px);
  transform: translateX(-50%);
  z-index: 60;
  width: min(calc(100% - 40px), 372px);
  height: var(--island-h);
  padding: 6px;
  display: flex;
  border-radius: 999px;
  /* the island is one object; its lanes stack in the same box */
  isolation: isolate;
  background: var(--mat-island);
  -webkit-backdrop-filter: var(--blur-island);
  backdrop-filter: var(--blur-island);
  border: 0.5px solid rgba(255,255,255,0.12);
  box-shadow:
    0 8px 28px rgba(0,0,0,0.22),
    inset 0 1px 0 rgba(255,255,255,0.12);
  transition: opacity var(--dur-standard) var(--settle),
              transform var(--dur-standard) var(--settle);
}

/* The selection is a change in material — a slightly brighter pane of the
   same glass the island is made of. No outline, no border, no accent. */
.island-indicator {
  position: absolute;
  z-index: 1;
  top: 6px;
  bottom: 6px;
  left: 0;
  border-radius: 999px;
  transform-origin: center;
  /* The selected pane carries a trace of the destination's accent, set by
     the tab it is currently under. No border, no outline. */
  background: var(--sel-soft, rgba(255,255,255,0.11));
  -webkit-backdrop-filter: var(--blur-pill);
  backdrop-filter: var(--blur-pill);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.16);
  /* 250ms, restrained spring — the pane slides, the island does not move */
  transition: left 250ms var(--snap),
              width 250ms var(--snap),
              background-color 250ms linear,
              transform 190ms var(--settle);
  will-change: left, width, transform;
}
.island-indicator::after {
  content: "";
  position: absolute;
  inset: 1px;
  border-radius: 999px;
  background: radial-gradient(120% 100% at 50% 0%,
    rgba(255,255,255,0.16), transparent 68%);
  pointer-events: none;
}
:root[data-theme="light"] .island-indicator {
  box-shadow: 0 1px 3px rgba(0,0,0,0.05);
}

.island-tab {
  position: relative;
  z-index: 2;
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  /* The mark leads; the word only names it. More air between them, and the
     word set smaller, so the two read as one object instead of colliding. */
  gap: 6px;
  /* At rest the island is neutral: inactive tabs are grey, and only the
     selected one shows its destination's accent. Secondary tone, because
     the pane's backdrop is whatever content scrolls beneath it. */
  color: var(--text-2);
  border-radius: 999px;
  transition: color var(--dur-fast) var(--settle);
}
/* Size is set per icon in JS (OPTICAL_SCALE), so nothing here may override
   it — this rule only carries the state transition. */
.island-tab svg {
  transition: transform 250ms var(--snap), opacity 200ms linear, color 200ms linear;
  opacity: 0.85;
}
/* Same type ramp as everything else; the selected label gains contrast,
   never size. */
.island-tab span {
  font-size: 9px;
  font-weight: 600;
  letter-spacing: 0.01em;
  line-height: 1;
  transition: color 200ms linear;
}
.island-tab[aria-selected="true"] { color: var(--tab-accent, var(--text-1)); }
/* Scale only. An earlier version also nudged the icon up half a pixel,
   which meant the selected tab's contents no longer sat on the centre line
   of the pane behind them. */
.island-tab[aria-selected="true"] svg {
  opacity: 1;
  transform: scale(1.12);
}
.island-tab[aria-selected="true"] span { color: var(--text-1); }
.island-tab:active svg { transform: scale(0.92); }

/* ============================================================
   GOAL CARD — the product's central object
   ============================================================ */
/* Content surfaces are glass. A goal's colour is carried in the material —
   a tint you read through, plus the mark and the progress — never a slab of
   fill. A screen of ten commitments stays airy rather than becoming a paint
   chart. */
.goal-card {
  position: relative;
  display: block;
  width: 100%;
  text-align: left;
  padding: 20px;
  border-radius: var(--r-card);
  overflow: hidden;
  isolation: isolate;
  color: var(--text-1);

  /* Glass. The panel is translucent and blurred, and the goal's colour is
     carried *through* the material rather than painted onto it — the card
     looks like a pane holding the colour of the thing it displays. */
  background:
    linear-gradient(180deg,
      color-mix(in srgb, var(--g-tint, var(--g1)) var(--glass-colour), transparent) 0%,
      color-mix(in srgb, var(--g-tint, var(--g1)) calc(var(--glass-colour) * 0.35), transparent) 100%),
    linear-gradient(180deg, var(--glass-tint) 0%, var(--glass-tint-2) 100%);
  -webkit-backdrop-filter: var(--blur-glass);
  backdrop-filter: var(--blur-glass);
  border: 0.5px solid var(--glass-edge);
  box-shadow: var(--lift-2), inset 0 1px 0 var(--glass-sheen);

  transition: transform var(--dur-micro) var(--settle),
              box-shadow var(--dur-standard) var(--settle),
              background var(--dur-standard) var(--settle),
              border-color var(--dur-standard) var(--settle);
}


.goal-card:active { transform: scale(0.985); }
.goal-card.is-complete { --glass-colour: 19%; }
.goal-card.is-resting { color: var(--text-2); --glass-colour: 5%; }

.gc-head {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  margin-bottom: var(--s-4);
  min-height: 28px;
}
.goal-card.is-compact .gc-head { margin-bottom: var(--s-3); }

/* The goal's mark: a well of the goal's colour set into the glass. */
.gc-icon {
  flex: 0 0 auto;
  width: 38px;
  height: 38px;
  border-radius: 12px;
  display: grid;
  place-items: center;
  color: var(--g-icon, var(--g1));
  background: color-mix(in srgb, var(--g1) 34%, transparent);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.20);
  transition: background var(--dur-standard) var(--settle);
}
.gc-icon svg { width: 21px; height: 21px; }

.gc-spacer { flex: 1 1 auto; }

.gc-badge {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  height: 28px;
  padding: 0 11px;
  border-radius: var(--r-pill);
  /* A cut-out pill: the ink becomes the fill and the hue becomes the text,
     so a badge never sits at 3:1 on a bright card. */
  background: var(--mat-control);
  border: none;
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--text-2);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.gc-badge svg { width: 13px; height: 13px; }


.gc-name {
  font-size: var(--t-meta);
  font-weight: 600;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--text-2);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* the answer to "what do I do today" */
.gc-today {
  margin-top: 8px;
  display: flex;
  align-items: baseline;
  gap: 7px;
  font-variant-numeric: tabular-nums;
}
.gc-today .value {
  font-size: 38px;
  font-weight: 700;
  letter-spacing: -0.042em;
  line-height: 1.02;
  color: var(--text-1);
}
/* On a saturated surface, secondary type is set large and opaque enough to
   clear the large-text contrast bar rather than relying on opacity. */
.gc-today .qualifier {
  font-size: 19px;
  font-weight: 600;
  color: var(--text-2);
  letter-spacing: -0.02em;
}
.gc-today.is-done .value { font-size: 26px; }

.gc-bar {
  position: relative;
  height: 6px;
  margin-top: var(--s-4);
  border-radius: var(--r-pill);
  background: var(--track);
  overflow: hidden;
}
.gc-bar i {
  position: absolute;
  inset: 0 auto 0 0;
  display: block;
  border-radius: var(--r-pill);
  background: var(--g-progress, var(--g1));
  transition: width var(--dur-progress) var(--settle);
}

.gc-foot {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s-3);
  margin-top: var(--s-4);
  /* the symbol occupies the right of the card, so content stops short of it */
  padding-right: 0;
  font-size: var(--t-meta);
  font-weight: 500;
  color: var(--text-2);
  font-variant-numeric: tabular-nums;
}
/* stacked: two supporting lines on one left edge, clear of the symbol */
.gc-foot.is-stacked {
  flex-direction: column;
  align-items: flex-start;
  gap: 3px;
}
.gc-foot.is-stacked .right { text-align: left; }
.gc-foot b { font-weight: 700; color: var(--text-1); }
.gc-foot .right { flex: 0 0 auto; font-weight: 600; color: var(--text-2); }

/* total progress as a lit edge along the bottom of the card */
.gc-rest {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 28px;
  padding: 0 12px;
  border-radius: var(--r-pill);
  background: var(--mat-control);
  font-size: 12.5px;
  font-weight: 600;
  color: var(--text-2);
}

/* light mode: the same card as a luminous tint rather than a deep one */


/* ---------- compact card, used inside a group ---------- */
.goal-card.is-compact { padding: 15px 18px 17px; }
.goal-card.is-compact .gc-head { margin-bottom: var(--s-3); }
.goal-card.is-compact .gc-icon { width: 34px; height: 34px; }
.goal-card.is-compact .gc-icon svg { width: 19px; height: 19px; }
.goal-card.is-compact .gc-today .value { font-size: 26px; }
.goal-card.is-compact .gc-foot { margin-top: var(--s-3); }

/* ============================================================
   GROUP — the old "routines", now just how goals travel together
   ============================================================ */
.group { display: flex; flex-direction: column; gap: var(--s-2); }
.group-head {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  width: 100%;
  min-height: 44px;
  padding: 0 var(--s-1);
  text-align: left;
  color: var(--text-2);
}
.group-head .label {
  flex: 1 1 auto;
  font-size: var(--t-meta);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.group-head .count { font-size: var(--t-meta); font-weight: 600; color: var(--text-3); }
.group-head .chev {
  width: 16px; height: 16px;
  color: var(--text-3);
  transition: transform var(--dur-standard) var(--settle);
}
.group.is-open .group-head .chev { transform: rotate(90deg); }
.group-body {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows var(--dur-standard) var(--settle);
}
.group.is-open .group-body { grid-template-rows: 1fr; }
.group-body > div {
  overflow: hidden;
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
}

/* ============================================================
   DAY FORM — the daily hero
   ============================================================ */
/* ============================================================
   THE ACTIVITY DIAL — Today's hero
   ============================================================ */
/* Capsules, not a stroke. Each is a short radial line with round caps, so
   the ring reads as a set of distinct physical parts rather than as a
   circular progress bar. */
.dial {
  position: relative;
  width: min(70vw, 268px);
  aspect-ratio: 1;
  margin: var(--s-8) auto 0;
  display: grid;
  place-items: center;
}
.dial svg { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }

.dial .cap {
  stroke: var(--dial-track);
  stroke-linecap: round;
  /* An unearned capsule is shorter and set back toward the centre. That is
     deliberate: Volt and Electric Cyan are almost as light as any track
     quiet enough to be a resting state, so lit-vs-unlit cannot rest on
     luminance alone. Length and weight carry it too. */
  transform-origin: 50px 50px;
  transform: scale(0.87);
  transition: stroke var(--dur-fast) var(--settle),
              stroke-width 340ms var(--snap),
              transform 340ms var(--snap),
              opacity var(--dur-fast) linear;
}
/* An earned capsule gains a little weight as it lights — the "slight scale
   increase" of the sequence, done on the one property that can grow a
   round-capped line from its own centre line. */
.dial .cap.is-on { stroke-width: 4.8; transform: scale(1); }

/* The capsule about to be earned: a touch brighter than the unfilled ones,
   breathing slowly, so the eye knows where the day is. */
.dial .cap.is-current {
  stroke: var(--dial-track-strong);
  transform: scale(0.94);
  animation: cap-breathe 2.6s ease-in-out infinite;
}
@keyframes cap-breathe {
  0%, 100% { opacity: 0.7; stroke-width: 4.1; }
  50%      { opacity: 1;   stroke-width: 4.5; }
}

/* The dial's shadow is neutral and it is a shadow, not a halo. A blurred
   copy of the capsules — grey or otherwise — sits *around* every stroke and
   drains the colour out of it. A real drop shadow falls underneath. */
.dial .dial-glow { display: none; }
.dial .dial-caps { filter: drop-shadow(var(--dial-drop)); }
/* the neutral field behind the dial is a whisper, not a shadow */
.dial-bloom { opacity: 0.6; }
.dial .cap-glow {
  stroke: transparent;
  stroke-linecap: round;
  transform-origin: 50px 50px;
  transform: scale(0.87);
  transition: stroke var(--dur-fast) var(--settle),
              stroke-width 340ms var(--snap),
              transform 340ms var(--snap);
}

/* A very soft accent field behind the whole dial, coloured by the
   commitment currently in play. */
/* A ring, not a fill — the light comes off the capsules, so the centre
   stays clean for the metric. */
.dial-bloom {
  position: absolute;
  inset: -4%;
  border-radius: 50%;
  pointer-events: none;
  background: radial-gradient(circle at 50% 50%,
    transparent 46%,
    var(--dial-shadow) 63%,
    transparent 82%);
  filter: blur(12px);
  transition: background var(--dur-progress) var(--settle),
              opacity var(--dur-progress) var(--settle);
}

/* The completed day. The dial settles: everything lit lifts a little, the
   bloom widens, and Volt appears once — as a hairline, not a flood. */
.dial.is-complete .cap.is-on { stroke-width: 5.2; }
/* The one place colour is allowed into the dial's shadow: a completed day
   gets a single restrained pass of Volt, and nothing else. */
.dial.is-complete .dial-bloom {
  background: radial-gradient(circle at 50% 50%,
    transparent 42%,
    var(--dial-shadow-strong) 58%,
    color-mix(in srgb, var(--volt) 8%, transparent) 72%,
    transparent 86%);
}

.dial-label {
  position: relative;
  text-align: center;
  transition: transform var(--dur-progress) var(--snap);
}
.dial.is-pop .dial-label { transform: scale(1.045); }
.dial-metric {
  font-size: clamp(44px, 13.5vw, 58px);
  transition: color var(--dur-standard) var(--settle);
  font-weight: 700;
  letter-spacing: -0.045em;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  color: var(--text-1);
}
.dial-metric .sep { color: var(--text-3); margin: 0 2px; font-weight: 500; }
.dial-sub {
  margin-top: 9px;
  font-size: var(--t-meta);
  font-weight: 600;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--text-3);
}
.dial.is-complete .dial-sub { color: var(--volt); }

@media (prefers-reduced-motion: reduce) {
  .dial .cap.is-current { animation: none; opacity: 0.85; }
}

.dayform-caption {
  margin-top: var(--s-5);
  text-align: center;
  font-size: var(--t-secondary);
  color: var(--text-2);
  letter-spacing: -0.01em;
  min-height: 21px;
  transition: color var(--dur-standard) var(--settle);
}
.dayform-caption.is-complete { color: var(--text-1); font-weight: 600; }



/* small ring, used where a card is too heavy */
.mini-ring { width: 26px; height: 26px; overflow: visible; }
.mini-ring .mr-track { fill: none; stroke: var(--track); stroke-width: 3; }
.mini-ring .mr-fill {
  fill: none; stroke: var(--g2); stroke-width: 3; stroke-linecap: round;
  transform: rotate(-90deg); transform-origin: 50% 50%;
  transition: stroke-dashoffset var(--dur-progress) var(--settle);
}

/* ============================================================
   BUTTONS
   ============================================================ */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-2);
  min-height: var(--ctl-lg);
  padding: 0 var(--s-6);
  border-radius: var(--r-pill);
  font-size: var(--t-body);
  font-weight: 600;
  letter-spacing: var(--tt-body);
  transition: transform var(--dur-micro) var(--settle),
              background-color var(--dur-micro) linear,
              opacity var(--dur-micro) linear,
              filter var(--dur-micro) linear;
}
.btn:active { transform: scale(0.975); }
.btn:disabled { opacity: 0.36; transform: none; }
.btn svg { width: 20px; height: 20px; }
.btn-block { width: 100%; }

.btn-primary {
  /* Neutral, and high contrast. This used to fall back to the goal colour
     variables, which meant any screen without a goal attached — Mind, most
     of all — rendered its primary action in whichever accent happened to be
     the default. The interface provides the structure; the user provides
     the colour. */
  background: var(--text-1);
  color: var(--bg);
}
.btn-primary:active { opacity: 0.86; }
.btn-primary:disabled { opacity: 0.35; }

.btn-secondary {
  background: var(--mat-control);
  color: var(--text-1);
  border: 0.5px solid var(--border);
}
.btn-secondary:active { background: var(--mat-control-hi); }

.btn-quiet { background: transparent; color: var(--accent); font-weight: 500; min-height: 48px; }
.btn-danger { background: transparent; color: var(--destructive); }

/* ============================================================
   QUICK ACTIONS
   ============================================================ */
.quick-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--s-2); }
.quick {
  min-height: 66px;
  padding: var(--s-3) var(--s-5);
  border-radius: var(--r-pill);
  background: var(--field-fill);
  border: 0.5px solid var(--field-edge);
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  gap: 2px;
  transition: transform var(--dur-micro) var(--settle),
              background-color var(--dur-micro) linear,
              border-color var(--dur-micro) linear;
}
.quick:active {
  transform: scale(0.97);
  background: color-mix(in srgb, var(--g2) 22%, var(--mat-control));
  border-color: color-mix(in srgb, var(--g2) 34%, transparent);
}
.quick b {
  font-size: 20px; font-weight: 700; letter-spacing: -0.028em;
  font-variant-numeric: tabular-nums; color: var(--text-1);
}
.quick span { font-size: var(--t-meta); color: var(--text-2); }

/* ============================================================
   CHIPS
   ============================================================ */
.chip-wrap { display: flex; flex-wrap: wrap; gap: var(--s-2); }
.chip {
  min-height: 44px;
  padding: 0 var(--s-4);
  border-radius: var(--r-pill);
  background: var(--mat-control);
  border: 0.5px solid var(--border);
  color: var(--text-2);
  font-size: var(--t-secondary);
  font-weight: 500;
  letter-spacing: -0.01em;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  transition: transform var(--dur-micro) var(--snap),
              background-color var(--dur-fast) var(--settle),
              color var(--dur-fast) var(--settle),
              border-color var(--dur-fast) var(--settle);
}
.chip:active { transform: scale(0.95); }
.chip[aria-pressed="true"] {
  background: var(--accent);
  border-color: transparent;
  color: var(--accent-ink, #fff);
  font-weight: 600;
  transform: scale(1.02);
}
/* the write-your-own chip, and the field it becomes */
.chip.is-custom { border-style: dashed; color: var(--text-3); }
.chip-input {
  min-height: 44px;
  padding: 0 var(--s-4);
  border-radius: var(--r-pill);
  background: var(--mat-control);
  border: 0.5px solid var(--accent, var(--border));
  color: var(--text-1);
  font-size: var(--t-secondary);
  text-align: center;
  width: 11ch;
}
.chip-input::placeholder { color: var(--text-3); }

/* ============================================================
   LISTS
   ============================================================ */
.list {
  border-radius: var(--r-card);
  background: linear-gradient(180deg, var(--glass-tint) 0%, var(--glass-tint-2) 100%);
  -webkit-backdrop-filter: var(--blur-glass);
  backdrop-filter: var(--blur-glass);
  border: 0.5px solid var(--glass-edge);
  box-shadow: var(--lift-1), inset 0 1px 0 var(--glass-sheen);
  overflow: hidden;
}
.list-row {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  width: 100%;
  min-height: 54px;
  padding: var(--s-3) var(--s-4);
  text-align: left;
  transition: background-color var(--dur-micro) linear;
}
.list-row + .list-row { border-top: 0.5px solid var(--hairline); }
button.list-row:active { background: var(--surface-2); }
/* A row whose control is the point: the control gets a fixed, pill-shaped
   slot on the right and the label takes what is left, so Theme sits on the
   same right edge as the switches above and below it. */
.list-row.is-control { min-height: 62px; }
.list-row .lr-control { flex: 0 0 178px; max-width: 55%; }
.list-row .lr-label { flex: 1 1 auto; min-width: 0; font-size: var(--t-body); letter-spacing: var(--tt-body); }
.list-row .lr-value { flex: 0 0 auto; color: var(--text-2); font-size: var(--t-secondary); }
.list-row .lr-chev { width: 17px; height: 17px; color: var(--text-3); flex: 0 0 auto; }
.list-row.is-danger .lr-label { color: var(--destructive); }
.list-note { padding: var(--s-2) var(--s-1) 0; font-size: var(--t-meta); color: var(--text-3); line-height: 1.45; }
.list-title { padding: 0 var(--s-1) var(--s-2); }

/* ---------- switch ---------- */
.switch {
  flex: 0 0 auto;
  position: relative;
  width: 51px; height: 31px;
  border-radius: var(--r-pill);
  background: var(--surface-3);
  transition: background-color var(--dur-fast) var(--settle);
}
.switch[aria-checked="true"] { background: var(--positive); }
.switch::after { content: ""; position: absolute; left: 0; right: 0; top: -7px; bottom: -7px; }
.switch i {
  position: absolute;
  top: 2px; left: 2px;
  width: 27px; height: 27px;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 2px 5px rgba(0,0,0,0.24);
  transition: transform var(--dur-fast) var(--snap);
}
.switch[aria-checked="true"] i { transform: translateX(20px); }

/* ---------- segmented ---------- */
.segmented {
  position: relative;
  display: flex;
  gap: 2px;
  height: var(--ctl-md);
  padding: 4px;
  border-radius: var(--r-pill);
  background: var(--field-fill);
  border: 0.5px solid var(--field-edge);
}
.segmented button {
  flex: 1 1 0; min-width: 0;
  position: relative; z-index: 2;
  height: var(--ctl-sm);
  border-radius: var(--r-pill);
  font-size: var(--t-meta);
  font-weight: 600;
  color: var(--text-2);
  transition: color var(--dur-fast) var(--settle);
}
.segmented button::after { content: ""; position: absolute; left: 0; right: 0; top: -5px; bottom: -5px; }
/* The ink of the selected segment is a property of the pill it sits on —
   not of the page behind it. That is the whole reason the label used to
   vanish: white text following the theme, on a pill that had gone white. */
.segmented button[aria-selected="true"] { color: var(--seg-ink); }
.segmented .seg-ind {
  position: absolute; z-index: 1;
  /* the same 4px the shell pads with, on every side */
  top: 4px; bottom: 4px; left: 0;
  border-radius: var(--r-pill);
  background: var(--seg-fill);
  box-shadow: var(--seg-lift);
  transition: transform var(--dur-standard) var(--snap),
              width var(--dur-standard) var(--snap);
}

/* ============================================================
   FIELDS
   ============================================================ */
.field { display: block; }
.field + .field { margin-top: var(--s-5); }
.field-label {
  display: block;
  font-size: var(--t-body);
  font-weight: 600;
  letter-spacing: var(--tt-body);
  margin-bottom: var(--s-2);
}
.field-hint { margin-top: var(--s-2); font-size: var(--t-meta); color: var(--text-3); line-height: 1.45; }
.input {
  width: 100%;
  /* an explicit height, not a minimum — a native date field renders a
     pixel shorter than a text field otherwise, and the row goes crooked */
  height: var(--ctl-lg);
  padding: 0 var(--s-5);
  border-radius: var(--r-pill);
  background: var(--field-fill);
  border: 0.5px solid var(--field-edge);
  color: var(--text-1);
  font-size: var(--t-body);
  letter-spacing: var(--tt-body);
  transition: border-color var(--dur-fast) var(--settle),
              background-color var(--dur-fast) var(--settle);
}
.input::placeholder { color: var(--text-3); }
.input:focus { border-color: var(--accent); background: var(--field-fill-hi); }
textarea.input { padding: var(--s-4) var(--s-5); min-height: 120px; line-height: 1.5; resize: none; border-radius: var(--r-lg); }
.input-row { display: flex; gap: var(--s-2); align-items: stretch; }
.input-row .input { flex: 1 1 auto; min-width: 0; }
.input-suffix {
  /* The amount is the answer; the unit only qualifies it. So the number
     takes the room and the unit pill is sized to its own content. */
  flex: 0 0 auto;
  display: grid; place-items: center;
  padding: 0 var(--s-2);
  width: 106px;
  height: var(--ctl-lg);
  border-radius: var(--r-pill);
  background: var(--field-fill);
  border: 0.5px solid var(--field-edge);
  color: var(--text-2);
  font-size: var(--t-secondary);
}
/* The unit field fills its pill: the visible shape is the suffix, so the
   whole suffix has to be the tap target, not the 24px of text inside it.
   `stretch` rather than a percentage — the pill has a hairline border, and
   100% of its padding box lands a pixel short of its own outer height. */
.input-suffix .input {
  min-height: 0;
  height: auto;
  align-self: stretch;
  width: 100%;
  border: none; background: none; padding: 0;
  text-align: center;
}

/* pickers */
.picker-groups { display: flex; flex-direction: column; gap: var(--s-5); }
.picker-group-title { margin-bottom: var(--s-2); color: var(--text-3); }
.picker-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(52px, 1fr)); gap: var(--s-2); }
.picker-cell {
  aspect-ratio: 1;
  border-radius: 50%;
  background: var(--field-fill);
  border: 0.5px solid var(--field-edge);
  color: var(--text-2);
  display: grid; place-items: center;
  transition: transform var(--dur-micro) var(--snap),
              background-color var(--dur-fast) var(--settle),
              border-color var(--dur-fast) var(--settle),
              color var(--dur-fast) var(--settle);
}
.picker-cell svg { width: 23px; height: 23px; }
.picker-cell:active { transform: scale(0.92); }
.picker-cell[aria-pressed="true"] {
  color: var(--g-progress, var(--g1));
  background: color-mix(in srgb, var(--g1) 24%, transparent);
  border-color: color-mix(in srgb, var(--g1) 40%, transparent);
}
.swatch-row { display: flex; flex-wrap: wrap; gap: var(--s-3); }
.swatch {
  position: relative;
  width: 40px; height: 40px;
  border-radius: 50%;
  background: linear-gradient(150deg, var(--g1), var(--g2));
  box-shadow: 0 3px 10px color-mix(in srgb, var(--g2) 34%, transparent);
  transition: transform var(--dur-micro) var(--snap);
}
.swatch:active { transform: scale(0.9); }
.swatch::after { content: ""; position: absolute; inset: -2px; }
.swatch[aria-pressed="true"]::before {
  content: "";
  position: absolute; inset: -5px;
  border-radius: 50%;
  border: 2px solid var(--g1);
}

/* days of week */
.dow-row { display: flex; gap: 6px; }
.dow {
  flex: 1 1 0; min-width: 0;
  height: var(--ctl-md);
  border-radius: var(--r-pill);
  background: var(--field-fill);
  border: 0.5px solid var(--field-edge);
  color: var(--text-2);
  font-size: var(--t-meta);
  font-weight: 700;
  transition: transform var(--dur-micro) var(--snap),
              background-color var(--dur-fast) var(--settle),
              color var(--dur-fast) var(--settle);
}
.dow:active { transform: scale(0.93); }
/* Selected is a tint and a weight change, not a slab of gradient. Seven
   saturated pills in a row was the loudest thing in the editor. */
.dow[aria-pressed="true"] {
  background: color-mix(in srgb, var(--g1, var(--accent)) 26%, transparent);
  border-color: color-mix(in srgb, var(--g1, var(--accent)) 42%, transparent);
  color: var(--text-1);
  font-weight: 700;
}

/* ============================================================
   SHEET
   ============================================================ */
.scrim {
  position: fixed; inset: 0; z-index: 90;
  background: var(--scrim);
  opacity: 0;
  transition: opacity var(--dur-sheet) var(--settle);
}
.scrim.is-in { opacity: 1; }

.sheet {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 91;
  max-height: 92dvh;
  display: flex;
  flex-direction: column;
  border-radius: var(--r-card) var(--r-card) 0 0;
  background: var(--mat-sheet);
  -webkit-backdrop-filter: var(--blur-sheet);
  backdrop-filter: var(--blur-sheet);
  border-top: 0.5px solid var(--border-strong);
  box-shadow: var(--sheet-lift), inset 0 1px 0 var(--edge-light);
  transform: translate3d(0, 100%, 0);
  transition: transform var(--dur-sheet) var(--settle);
  overscroll-behavior: contain;
}
.sheet.is-in { transform: none; }
.sheet-inner {
  width: 100%; max-width: var(--page-max);
  margin: 0 auto;
  display: flex; flex-direction: column;
  min-height: 0;
}
.grabber {
  flex: 0 0 auto;
  width: 36px; height: 4px;
  border-radius: 2px;
  background: var(--text-3);
  opacity: 0.6;
  margin: 8px auto 0;
}
.sheet-head {
  flex: 0 0 auto;
  display: flex; align-items: center; gap: var(--s-2);
  min-height: 54px;
  padding: 0 var(--s-4);
}
.sheet-head .title {
  flex: 1 1 auto;
  text-align: center;
  font-size: var(--t-body);
  font-weight: 600;
  letter-spacing: var(--tt-body);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* The header's own layout puts these at the edges. The buttons themselves
   stay symmetric — an earlier version gave them a 70px box and pushed the
   label to one side of it, so the tap target and the word it contained had
   different centres. */
.sheet-head .side {
  flex: 0 0 auto;
  min-height: 44px;
  padding: 0 var(--s-2);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--accent);
  font-size: var(--t-body);
  letter-spacing: var(--tt-body);
}
.sheet-head .side.right { font-weight: 600; }
.sheet-head .side:active { opacity: 0.55; }
.sheet-head .side:disabled { opacity: 0.34; }
.sheet-body {
  flex: 1 1 auto; min-height: 0;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding: var(--s-2) var(--s-4) calc(var(--safe-bottom) + var(--s-6));
}
.sheet-foot {
  flex: 0 0 auto;
  padding: var(--s-3) var(--s-4) calc(var(--safe-bottom) + var(--s-3));
  border-top: 0.5px solid var(--hairline);
}

/* ============================================================
   TOAST
   ============================================================ */
.toast-layer {
  position: fixed;
  left: 0; right: 0;
  bottom: calc(var(--island-h) + var(--safe-bottom) + 24px);
  z-index: 95;
  display: flex; flex-direction: column; align-items: center; gap: var(--s-2);
  pointer-events: none;
}
.toast {
  max-width: calc(100% - 40px);
  padding: 12px var(--s-5);
  border-radius: var(--r-pill);
  background: var(--mat-sheet);
  -webkit-backdrop-filter: var(--blur-sheet);
  backdrop-filter: var(--blur-sheet);
  border: 0.5px solid var(--border-strong);
  box-shadow: var(--lift-2);
  font-size: var(--t-secondary);
  font-weight: 600;
  color: var(--text-1);
  letter-spacing: -0.01em;
  display: flex; align-items: center; gap: var(--s-2);
  opacity: 0;
  transform: translate3d(0, 12px, 0);
  transition: opacity var(--dur-fast) var(--settle), transform var(--dur-fast) var(--settle);
}
.toast.is-in { opacity: 1; transform: none; }
.toast svg { width: 17px; height: 17px; flex: 0 0 auto; }
.toast.is-error { color: var(--critical); }
.toast.is-best { color: var(--volt); }

/* ============================================================
   CONSISTENCY CALENDAR
   ============================================================ */
.cal {
  --cal-complete: linear-gradient(150deg, var(--g1), var(--g2));
  --cal-partial:  color-mix(in srgb, var(--g2) 18%, transparent);
}
.cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 6px; }
.cal-dow {
  text-align: center;
  font-size: 10px; font-weight: 700;
  color: var(--text-3);
  letter-spacing: 0.05em;
  padding-bottom: 2px;
}
.cal-cell {
  position: relative;
  aspect-ratio: 1;
  min-width: 0;
  border-radius: 10px;
  display: grid; place-items: center;
  font-size: 11px; font-weight: 500;
  line-height: 1;
  color: var(--text-3);
  background: var(--track);
  transition: transform var(--dur-micro) var(--snap);
}
/* A calendar cell is small by design — seven across a phone. The hit area
   is not: it extends past the visible square to a full 44pt target, which
   is why the padding is measured against the cell rather than fixed. */
.cal-cell::before {
  content: "";
  position: absolute;
  left: 50%; top: 50%;
  width: 44px; height: 44px;
  transform: translate(-50%, -50%);
}
.cal-cell.is-empty::before, .cal-cell.is-future::before { content: none; }
.cal-cell:active { transform: scale(0.88); }
.cal-cell.s-complete {
  background: var(--g1);
  color: var(--gink, #000); font-weight: 700;
}
.cal-cell.s-partial {
  background: color-mix(in srgb, var(--g2) 16%, transparent);
  color: var(--text-2);
  box-shadow: inset 0 0 0 1.5px color-mix(in srgb, var(--g2) 40%, transparent);
}
/* A missed day is information, not decoration — it reads. */
.cal-cell.s-missed { background: var(--track); color: var(--text-2); }
.cal-cell.s-rest { background: var(--surface-2); color: transparent; }
.cal-cell.s-rest::after {
  content: ""; position: absolute;
  width: 10px; height: 1.5px; border-radius: 1px; background: var(--text-3);
}
.cal-cell.s-off { background: transparent; box-shadow: inset 0 0 0 1px var(--hairline); color: var(--text-3); opacity: .6; }
.cal-cell.s-none { background: transparent; box-shadow: inset 0 0 0 1px var(--hairline); }
.cal-cell.is-today { box-shadow: 0 0 0 2px var(--text-1); }
/* A day that has not happened carries no information, so it is an empty
   slot rather than a faded number — which also stops it being text that
   cannot meet contrast. */
.cal-cell.is-future {
  color: transparent;
  background: transparent;
  box-shadow: inset 0 0 0 1px var(--hairline);
  pointer-events: none;
}

.cal-legend { display: flex; flex-wrap: wrap; gap: var(--s-3); margin-top: var(--s-4); }
.cal-legend span { display: inline-flex; align-items: center; gap: 6px; font-size: var(--t-meta); color: var(--text-3); }
.cal-legend i { position: relative; width: 11px; height: 11px; border-radius: 3.5px; display: block; flex: 0 0 auto; }
.cal-legend i.is-rest::after {
  content: ""; position: absolute;
  left: 2px; right: 2px; top: 50%;
  height: 1.5px; margin-top: -0.75px; border-radius: 1px;
  background: var(--text-3);
}

/* dot strip */
.dots { display: flex; gap: 3px; align-items: center; }
.dots i { width: 6px; height: 6px; border-radius: 2px; background: var(--card-track, var(--track)); display: block; }
.dots i.d-complete { background: var(--card-ink, var(--g2)); }
.dots i.d-partial  { background: color-mix(in srgb, var(--card-ink, var(--g2)) 45%, transparent); }
.dots i.d-rest     { height: 2px; align-self: center; }

/* ============================================================
   EMPTY / SKELETON
   ============================================================ */
.empty { padding: var(--s-10) var(--s-4); text-align: center; }
.empty h3 { font-size: var(--t-section); font-weight: 600; letter-spacing: var(--tt-section); }
.empty p { margin-top: var(--s-2); font-size: var(--t-secondary); color: var(--text-2); line-height: 1.45; }
.empty .btn { margin-top: var(--s-6); }

.skeleton { border-radius: var(--r-card); background: var(--surface); animation: sk 1.4s ease-in-out infinite; }
@keyframes sk { 0%,100% { opacity: .5 } 50% { opacity: .8 } }

/* ============================================================
   MIND
   ============================================================ */
.orb-stage { position: relative; height: 190px; display: grid; place-items: center; margin-top: var(--s-4); }
/* One colour with a single soft light from above — not a shaded sphere.
   The old version mixed toward white at the top and toward black at the
   bottom, which is what made every mood look muddy in the middle. */
.orb {
  width: 132px; height: 132px;
  border-radius: 50%;
  background:
    radial-gradient(circle at 50% 22%,
      color-mix(in srgb, var(--mood) 72%, #fff) 0%,
      transparent 62%),
    var(--mood);
  transition: background var(--dur-standard) var(--settle),
              transform var(--dur-standard) var(--settle),
              filter var(--dur-standard) var(--settle);
  will-change: transform;
}
.orb-halo {
  position: absolute;
  width: 214px; height: 214px;
  border-radius: 50%;
  background: radial-gradient(circle, color-mix(in srgb, var(--mood) 30%, transparent) 0%, transparent 64%);
  filter: blur(26px);
  opacity: 0.45;
  transition: background var(--dur-standard) var(--settle), transform var(--dur-standard) var(--settle);
  pointer-events: none;
}
.mood-word {
  margin-top: var(--s-5);
  text-align: center;
  font-size: var(--t-section);
  font-weight: 600;
  letter-spacing: var(--tt-section);
}
.spectrum { position: relative; height: 56px; margin-top: var(--s-5); touch-action: none; display: grid; align-items: center; }
.spectrum-track {
  height: 8px; border-radius: var(--r-pill);
  background: linear-gradient(90deg, #5E5CE6 0%, #8A8F99 50%, #FF4401 100%);
  opacity: 0.9;
}
.spectrum-knob {
  position: absolute; top: 50%;
  width: 32px; height: 32px;
  margin: -16px 0 0 -16px;
  border-radius: 50%;
  background: var(--mood);
  box-shadow: 0 0 0 3px var(--bg), var(--lift-2);
  transition: transform var(--dur-micro) var(--settle);
}
.spectrum.is-dragging .spectrum-knob { transform: scale(1.12); }
.spectrum-ends { display: flex; justify-content: space-between; margin-top: var(--s-2); font-size: var(--t-meta); color: var(--text-3); }

.mind-strip { display: flex; align-items: flex-end; gap: 3px; height: 76px; padding: var(--s-2) 0; }
.mind-strip i { flex: 1 1 0; min-width: 0; border-radius: 3px; background: var(--c, var(--surface-2)); display: block; }

.mind-entry {
  display: flex; gap: var(--s-3);
  padding: var(--s-3) 0;
  border-top: 0.5px solid var(--hairline);
  text-align: left; width: 100%;
}
.mind-entry:first-child { border-top: none; }
.mind-dot {
  flex: 0 0 auto;
  width: 32px; height: 32px; border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, color-mix(in srgb, var(--mood) 82%, #fff), var(--mood));
  margin-top: 2px;
}
.mind-dot.is-note { background: var(--surface-2); display: grid; place-items: center; color: var(--text-3); }
.mind-dot.is-note svg { width: 15px; height: 15px; }
.mind-entry .me-body { flex: 1 1 auto; min-width: 0; }
.mind-entry .me-top { display: flex; align-items: baseline; justify-content: space-between; gap: var(--s-3); }
.mind-entry .me-word { font-size: var(--t-body); font-weight: 600; letter-spacing: var(--tt-body); }
.mind-entry .me-when { font-size: var(--t-meta); color: var(--text-3); flex: 0 0 auto; }
.mind-entry .me-tags { margin-top: 3px; font-size: var(--t-meta); color: var(--text-2); }
.mind-entry .me-note { margin-top: 6px; font-size: var(--t-secondary); color: var(--text-2); line-height: 1.45; }

.insight {
  padding: var(--s-4);
  border-radius: var(--r-lg);
  background: var(--surface);
  border: 0.5px solid var(--border);
  display: flex; gap: var(--s-3);
}
.insight svg { width: 20px; height: 20px; color: var(--accent); flex: 0 0 auto; margin-top: 1px; }
.insight p { font-size: var(--t-secondary); line-height: 1.5; color: var(--text-1); }

/* ============================================================
   ENTRY LOG + STATS
   ============================================================ */
.entry-row {
  display: flex; align-items: center; gap: var(--s-3);
  width: 100%; min-height: 48px;
  padding: var(--s-2) 0;
  border-top: 0.5px solid var(--hairline);
  text-align: left;
}
.entry-row:first-child { border-top: none; }
.entry-row .er-when { flex: 0 0 96px; font-size: var(--t-meta); color: var(--text-3); }
.entry-row .er-amt { flex: 1 1 auto; font-size: var(--t-body); font-variant-numeric: tabular-nums; letter-spacing: var(--tt-body); }
.er-del {
  flex: 0 0 auto;
  width: 44px; height: 44px;
  display: grid; place-items: center;
  color: var(--text-3);
  border-radius: 50%;
  transition: transform var(--dur-micro) var(--snap), color var(--dur-micro);
}
.er-del:active { transform: scale(0.86); color: var(--destructive); }
.er-del svg { width: 16px; height: 16px; }

.stats { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--s-3); }
.stat b {
  display: block;
  font-size: 25px; font-weight: 700; letter-spacing: -0.032em;
  font-variant-numeric: tabular-nums;
}
.stat span { display: block; margin-top: 3px; font-size: var(--t-meta); color: var(--text-2); }
.stat.is-best b { color: var(--volt); }

/* ============================================================
   CAROUSEL — Today's small cards
   ============================================================ */
.carousel-head { margin-top: var(--s-8); }
/* Scrolls edge to edge, but the first and last card line up with the page
   margin, so nothing ever touches the bezel. */
.carousel {
  display: flex;
  gap: var(--s-3);
  overflow-x: auto;
  scroll-snap-type: x proximity;
  scroll-padding-left: var(--page-pad);
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  margin-inline: calc(var(--page-pad) * -1);
  padding-inline: var(--page-pad);
  /* A horizontal scroller clips vertically too, so the cards' shadows need
     room inside the scroll box or they get sheared off along the frame. */
  padding-block: 14px 24px;
  margin-block: -10px -16px;
}
.carousel::-webkit-scrollbar { display: none; }
.carousel > div { flex: 0 0 auto; scroll-snap-align: start; }

/* An action card: what is still owed on this commitment today. Graphite,
   with the goal's colour carried by its mark and its ring. */
.goal-chip {
  position: relative;
  width: 128px;
  min-height: 142px;
  padding: 14px;
  border-radius: 24px;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  text-align: left;
  overflow: hidden;
  color: var(--text-1);
  background:
    linear-gradient(180deg,
      color-mix(in srgb, var(--g-tint, var(--g1)) var(--glass-colour), transparent) 0%,
      color-mix(in srgb, var(--g-tint, var(--g1)) calc(var(--glass-colour) * 0.35), transparent) 100%),
    linear-gradient(180deg, var(--glass-tint) 0%, var(--glass-tint-2) 100%);
  -webkit-backdrop-filter: var(--blur-glass);
  backdrop-filter: var(--blur-glass);
  border: 0.5px solid var(--glass-edge);
  box-shadow: var(--lift-2), inset 0 1px 0 var(--glass-sheen);
  transition: transform var(--dur-micro) var(--settle),
              background var(--dur-standard) var(--settle),
              border-color var(--dur-standard) var(--settle);
}

.goal-chip:active { transform: scale(0.95); }
.goal-chip.is-quiet { opacity: 0.5; }

.chip-icon {
  width: 34px; height: 34px;
  border-radius: 11px;
  display: grid; place-items: center;
  background: color-mix(in srgb, var(--g1) 34%, transparent);
  color: var(--g-icon, var(--g1));
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.20);
  transition: transform var(--dur-standard) var(--snap);
}
.chip-name {
  margin-top: var(--s-3);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  /* Tertiary type does not belong on a coloured surface: the card carries a
     wash, and the faintest tier stops clearing 4.5:1 the moment it does. */
  color: var(--text-2);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
}
.chip-body { flex: 1 1 auto; display: flex; flex-direction: column; justify-content: flex-end; }
.chip-value {
  font-size: 30px;
  font-weight: 700;
  letter-spacing: -0.04em;
  line-height: 1;
  color: var(--text-1);
  font-variant-numeric: tabular-nums;
}
.chip-label { margin-top: 3px; font-size: 12.5px; font-weight: 600; color: var(--text-2); }
.chip-state { font-size: 17px; font-weight: 600; letter-spacing: -0.02em; color: var(--text-2); }
.chip-bar {
  width: 100%;
  height: 3px;
  margin-top: var(--s-3);
  border-radius: 2px;
  background: var(--track);
  overflow: hidden;
}
.chip-bar i {
  display: block; height: 100%; border-radius: 2px;
  background: var(--g-progress, var(--g1));
  transition: width var(--dur-progress) var(--settle);
}

/* ---- clearing the day ----
   A finished card acknowledges, compresses, and leaves. What remains
   slides into its place, so the screen gets lighter as the day is cleared. */
.carousel-item {
  flex: 0 0 auto;
  scroll-snap-align: start;
  transition: transform var(--dur-standard) var(--settle);
}
.carousel-item.is-clearing {
  pointer-events: none;
  animation: chip-clear 620ms var(--settle) forwards;
}
@keyframes chip-clear {
  0%   { transform: scale(1);    opacity: 1; }
  22%  { transform: scale(1.06); opacity: 1; }
  55%  { transform: scale(0.92); opacity: 0.7; }
  100% { transform: scale(0.7);  opacity: 0; }
}
.carousel-item.is-collapsing {
  width: 0 !important;
  margin-right: calc(var(--s-3) * -1);
  transition: width var(--dur-standard) var(--settle),
              margin-right var(--dur-standard) var(--settle);
}
.goal-chip.is-settling .chip-icon { transform: scale(1.12); }

.carousel-cleared {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  padding: var(--s-5) 0 var(--s-3);
  font-size: var(--t-secondary);
  font-weight: 600;
  color: var(--text-2);
}
.carousel-cleared svg { width: 18px; height: 18px; color: var(--positive); }

/* ============================================================
   DISCIPLINES — a sequence, drawn as a chain
   ============================================================ */
.discipline-stack { display: flex; flex-direction: column; gap: var(--s-3); }

.discipline {
  padding: var(--s-5);
  border-radius: var(--r-card);
  background: linear-gradient(180deg, var(--glass-tint) 0%, var(--glass-tint-2) 100%);
  -webkit-backdrop-filter: var(--blur-glass);
  backdrop-filter: var(--blur-glass);
  border: 0.5px solid var(--glass-edge);
  box-shadow: var(--lift-1), inset 0 1px 0 var(--glass-sheen);
}
.discipline-top {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s-3);
  margin-bottom: var(--s-4);
}
.discipline-name { font-size: var(--t-body); font-weight: 700; letter-spacing: var(--tt-body); }
.discipline-count {
  font-size: var(--t-meta); font-weight: 600; color: var(--text-2);
  font-variant-numeric: tabular-nums; flex: 0 0 auto;
}

/* the chain: nodes are steps, links are the run between them */
.chain { display: flex; align-items: center; }
.chain-node {
  flex: 0 0 auto;
  width: 30px; height: 30px;
  border-radius: 50%;
  display: grid; place-items: center;
  background: var(--mat-control);
  border: 1px solid var(--border);
  color: var(--text-3);
  transition: background-color var(--dur-standard) var(--settle),
              color var(--dur-standard) var(--settle),
              transform var(--dur-standard) var(--snap);
}
.chain-node.is-done { background: var(--g1); border-color: transparent; color: var(--gink, #fff); }
.chain-node.is-next {
  border-color: var(--g1);
  color: var(--g1);
  background: color-mix(in srgb, var(--g1) 16%, transparent);
  transform: scale(1.1);
}
.chain-node.is-skipped { opacity: 0.4; }
.chain-link {
  flex: 1 1 0; min-width: 8px; height: 3px;
  background: var(--track);
  transition: background-color var(--dur-standard) var(--settle);
}
.chain-link.is-done { background: color-mix(in srgb, var(--g-progress, var(--g1)) 78%, transparent); }

.discipline-next {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  width: 100%;
  min-height: 52px;
  margin-top: var(--s-4);
  padding: var(--s-2) var(--s-3);
  text-align: left;
  border-radius: var(--r-sm);
  background: var(--mat-control);
  transition: transform var(--dur-micro) var(--settle),
              background-color var(--dur-micro) linear;
}
button.discipline-next:active { transform: scale(0.98); background: var(--mat-control-hi); }
.dn-icon {
  flex: 0 0 auto;
  width: 30px; height: 30px;
  border-radius: 9px;
  display: grid; place-items: center;
  background: var(--g1);
  color: var(--gink, #fff);
}
.dn-text { flex: 1 1 auto; min-width: 0; }
.dn-text b { display: block; font-size: var(--t-secondary); font-weight: 600; letter-spacing: -0.01em; }
.dn-text span { display: block; margin-top: 1px; font-size: var(--t-meta); color: var(--text-2); }
.dn-chev { flex: 0 0 auto; color: var(--text-3); }
.discipline-next.is-done { color: var(--positive); font-weight: 600; font-size: var(--t-secondary); justify-content: center; }
.discipline-next.is-idle { color: var(--text-3); font-size: var(--t-secondary); justify-content: center; }

/* ============================================================
   MIND PROMPT — the other half of the daily loop
   ============================================================ */
.mind-prompt {
  display: flex;
  align-items: center;
  gap: var(--s-4);
  width: 100%;
  min-height: 72px;
  padding: var(--s-4);
  text-align: left;
  border-radius: var(--r-pill);
  background: linear-gradient(180deg, var(--glass-tint) 0%, var(--glass-tint-2) 100%);
  -webkit-backdrop-filter: var(--blur-glass);
  backdrop-filter: var(--blur-glass);
  border: 0.5px solid var(--glass-edge);
  box-shadow: var(--lift-1), inset 0 1px 0 var(--glass-sheen);
  transition: transform var(--dur-micro) var(--settle);
}
.mind-prompt:active { transform: scale(0.985); }
.mp-orb {
  flex: 0 0 auto;
  width: 40px; height: 40px;
  border-radius: 50%;
  background: radial-gradient(circle at 34% 30%,
    color-mix(in srgb, var(--mood) 82%, #fff), var(--mood));
  box-shadow: 0 0 18px color-mix(in srgb, var(--mood) 38%, transparent);
}
.mp-text { flex: 1 1 auto; min-width: 0; }
.mp-title {
  display: block;
  font-size: var(--t-body);
  font-weight: 600;
  letter-spacing: var(--tt-body);
  color: var(--text-1);
}
.mp-sub { display: block; margin-top: 3px; font-size: var(--t-meta); color: var(--text-2); }
.mp-chev { flex: 0 0 auto; color: var(--text-3); }

/* ============================================================
   COLOUR PICKER — family, then tone
   ============================================================ */
.color-picker { display: block; }

.family-row {
  display: flex;
  gap: var(--s-3);
  overflow-x: auto;
  scrollbar-width: none;
  margin-inline: calc(var(--s-4) * -1);
  padding: 4px var(--s-4) var(--s-2);
}
.family-row::-webkit-scrollbar { display: none; }

.family {
  position: relative;
  flex: 0 0 auto;
  width: var(--tap); height: var(--tap);
  display: grid; place-items: center;
  border-radius: 50%;
  transition: transform var(--dur-fast) var(--snap);
}
.family::after { content: ""; position: absolute; inset: -1px; }
.family-dot {
  width: 34px; height: 34px;
  border-radius: 50%;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.28), 0 2px 8px rgba(0,0,0,0.32);
  transition: width var(--dur-fast) var(--snap),
              height var(--dur-fast) var(--snap),
              background var(--dur-standard) var(--settle);
}
.family:active { transform: scale(0.9); }
/* The selected swatch keeps its size and gains a ring. Growing it made the
   whole row shift by a pixel and a half every time you changed your mind. */
.family.is-on .family-dot {
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.28),
    0 0 0 2px var(--bg),
    0 0 0 4px currentColor;
}
.family.is-on { color: var(--text-1); }
.family.is-on::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  border: 2px solid var(--text-1);
  opacity: 0.85;
}

.tone-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-top: var(--s-4);
  margin-bottom: var(--s-2);
}
.tone-label {
  font-size: var(--t-meta);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-3);
}
.tone-name { font-size: var(--t-secondary); font-weight: 600; color: var(--text-1); }

.tone-slider {
  position: relative;
  height: 44px;
  touch-action: none;
  display: grid;
  align-items: center;
}
.tone-track {
  height: 12px;
  border-radius: 6px;
  box-shadow: inset 0 1px 2px rgba(0,0,0,0.30);
  transition: background var(--dur-standard) var(--settle);
}
.tone-ticks {
  position: absolute;
  left: 18px; right: 18px;
  display: flex;
  justify-content: space-between;
  pointer-events: none;
}
.tone-ticks i {
  width: 3px; height: 3px;
  border-radius: 50%;
  background: rgba(255,255,255,0.5);
  transition: opacity var(--dur-fast) var(--settle);
}
.tone-ticks i.on { opacity: 0; }
.tone-thumb {
  position: absolute;
  top: 50%;
  width: 30px; height: 30px;
  margin: -15px 0 0 -15px;
  border-radius: 50%;
  border: 3px solid var(--bg-raised);
  box-shadow: 0 2px 10px rgba(0,0,0,0.42), inset 0 1px 0 rgba(255,255,255,0.24);
  transition: left var(--dur-fast) var(--settle),
              background var(--dur-standard) var(--settle),
              transform var(--dur-micro) var(--settle);
}
.tone-slider.is-dragging .tone-thumb { transform: scale(1.14); }

/* ============================================================
   THE DAILY LINE
   ============================================================ */
/* Third plane. No surface, no border, no card — the page itself, set at
   the weight of a footnote so it never competes with the dial or the work
   still to do above it. */
.daily-quote {
  margin: var(--s-12) auto 0;
  padding: 0 var(--s-4) var(--s-6);
  max-width: 27ch;
  text-align: center;
}
.dq-text {
  font-family: var(--font-quote);
  font-size: 20px;
  font-weight: 500;
  line-height: 1.4;
  letter-spacing: -0.02em;
  color: var(--text-1);
  text-wrap: balance;
}
/* The second nuance: the attribution drops two steps in size, weight and
   tone at once, so the line reads as one object with a quiet signature
   rather than as two competing pieces of text. */
.dq-who {
  margin-top: var(--s-4);
  font-family: var(--font-quote);
  font-size: var(--t-label);
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--text-3);
}

/* ---------- Mind: the section mark ---------- */
.mind-mark-row {
  display: flex;
  align-items: center;
  gap: var(--s-4);
  padding-top: var(--s-2);
}
.mind-mark {
  flex: 0 0 auto;
  width: 56px; height: 56px;
  border-radius: 50%;
  display: grid; place-items: center;
  color: var(--mood, var(--text-2));
  background: color-mix(in srgb, var(--mood, var(--text-3)) 18%, transparent);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.14);
}

/* ============================================================
   THE WEEKLY REVIEW
   ============================================================ */
.review-head { padding-top: var(--s-5); }
.review-nav { display: flex; align-items: center; gap: var(--s-3); }
.review-range { flex: 1 1 auto; min-width: 0; text-align: center; }
.review-range .t-meta { margin-top: 2px; color: var(--text-3); }
.review-step {
  flex: 0 0 auto;
  width: 44px; height: 44px;
  display: grid; place-items: center;
  border-radius: 50%;
  background: var(--glass-tint);
  -webkit-backdrop-filter: var(--blur-control);
  backdrop-filter: var(--blur-control);
  border: 0.5px solid var(--glass-edge);
  color: var(--text-1);
  transition: transform var(--dur-micro) var(--snap), opacity var(--dur-fast) linear;
}
.review-step:active { transform: scale(0.92); }
.review-step:disabled { opacity: 0.3; }

/* the week in one number */
.review-headline { text-align: center; padding: var(--s-10) 0 var(--s-6); }
.rh-figure {
  font-size: clamp(52px, 16vw, 68px);
  font-weight: 700;
  letter-spacing: -0.05em;
  line-height: 1;
  color: var(--text-1);
}
.rh-figure .rh-sep { color: var(--text-3); margin: 0 3px; font-weight: 500; }
.rh-figure .rh-of  { color: var(--text-2); }
.rh-label {
  margin-top: 10px;
  font-size: var(--t-meta);
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--text-3);
}
.rh-verdict {
  margin: var(--s-5) auto 0;
  max-width: 30ch;
  font-size: var(--t-body);
  line-height: 1.45;
  letter-spacing: var(--tt-body);
  color: var(--text-2);
  text-wrap: pretty;
}

/* seven days, as height */
.week-strip {
  display: flex;
  gap: 6px;
  align-items: flex-end;
  padding: var(--s-4) 0 var(--s-8);
}
.ws-col { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; align-items: center; gap: 8px; }
.ws-bar {
  position: relative;
  width: 100%;
  height: 64px;
  border-radius: var(--r-pill);
  background: var(--track);
  overflow: hidden;
  display: flex;
  align-items: flex-end;
}
.ws-bar i {
  display: block;
  width: 100%;
  border-radius: var(--r-pill);
  background: var(--text-1);
  transition: height var(--dur-progress) var(--settle);
}
/* A day where everything held gets Volt — the one accent reserved for it. */
.ws-bar.is-full i { background: var(--volt-ink); }
/* A day the plan never asked for is not a gap in the week. */
.ws-bar.is-empty { background: transparent; box-shadow: inset 0 0 0 1px var(--hairline); }
.ws-day { font-size: var(--t-label); font-weight: 600; color: var(--text-3); }

/* one commitment's week */
.review-rows { display: flex; flex-direction: column; gap: var(--s-2); }
.review-row {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  padding: var(--s-3) var(--s-4);
  border-radius: var(--r-lg);
  background: linear-gradient(180deg, var(--glass-tint) 0%, var(--glass-tint-2) 100%);
  -webkit-backdrop-filter: var(--blur-glass);
  backdrop-filter: var(--blur-glass);
  border: 0.5px solid var(--glass-edge);
}
.rr-icon {
  flex: 0 0 auto;
  width: 34px; height: 34px;
  border-radius: 11px;
  display: grid; place-items: center;
  color: var(--g-icon, var(--g1));
  background: color-mix(in srgb, var(--g1) 34%, transparent);
}
.rr-body { flex: 1 1 auto; min-width: 0; }
.rr-name {
  font-size: var(--t-secondary);
  font-weight: 600;
  letter-spacing: var(--tt-body);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.rr-meta { margin-top: 2px; font-size: var(--t-meta); color: var(--text-2); font-variant-numeric: tabular-nums; }
/* seven dots: the shape of the week at a glance */
.rr-marks { flex: 0 0 auto; display: flex; gap: 3px; }
.rr-marks i { width: 5px; height: 5px; border-radius: 50%; background: var(--track-strong); display: block; }
.rr-marks i.m-complete { background: var(--g-progress, var(--g1)); }
.rr-marks i.m-partial  { background: color-mix(in srgb, var(--g-progress, var(--g1)) 45%, transparent); }
.rr-marks i.m-missed   { background: var(--track-strong); }
.rr-marks i.m-rest, .rr-marks i.m-off, .rr-marks i.m-none, .rr-marks i.m-future { background: var(--hairline); }
.rr-count {
  flex: 0 0 auto;
  font-size: var(--t-meta);
  font-weight: 700;
  color: var(--text-2);
  min-width: 34px;
  text-align: right;
}

.review-mind { font-size: var(--t-secondary); color: var(--text-2); line-height: 1.5; }
.review-mind b { color: var(--text-1); font-weight: 600; }
.review-note textarea { margin-top: var(--s-2); }
.review-actions { margin-top: var(--s-4); }

/* the Sunday invitation on Today */
.review-call {
  display: flex;
  align-items: center;
  gap: var(--s-4);
  width: 100%;
  min-height: 68px;
  margin-top: var(--s-8);
  padding: var(--s-4) var(--s-5);
  text-align: left;
  border-radius: var(--r-pill);
  background: linear-gradient(180deg, var(--glass-tint) 0%, var(--glass-tint-2) 100%);
  -webkit-backdrop-filter: var(--blur-glass);
  backdrop-filter: var(--blur-glass);
  border: 0.5px solid var(--glass-edge);
  box-shadow: var(--lift-1), inset 0 1px 0 var(--glass-sheen);
  transition: transform var(--dur-micro) var(--settle);
}
.review-call:active { transform: scale(0.985); }
.rc-mark {
  flex: 0 0 auto;
  width: 38px; height: 38px;
  border-radius: 50%;
  display: grid; place-items: center;
  color: var(--volt);
  background: color-mix(in srgb, var(--volt) 16%, transparent);
}
.rc-text { flex: 1 1 auto; min-width: 0; }
.rc-title { font-size: var(--t-body); font-weight: 600; letter-spacing: var(--tt-body); }
.rc-sub { margin-top: 2px; font-size: var(--t-meta); color: var(--text-2); }
.rc-chev { flex: 0 0 auto; color: var(--text-3); }

/* ============================================================
   ROUTINES
   ============================================================ */
.section-head { display: flex; align-items: center; gap: var(--s-3); }
.section-add {
  flex: 0 0 auto;
  width: 32px; height: 32px;
  display: grid; place-items: center;
  border-radius: 50%;
  background: var(--mat-control);
  color: var(--text-1);
  transition: transform var(--dur-micro) var(--snap), background-color var(--dur-micro) linear;
}
.section-add::before {
  content: ""; position: absolute;
  width: var(--tap); height: var(--tap);
}
.section-add { position: relative; }
.section-add:active { transform: scale(0.9); background: var(--mat-control-hi); }

.routine-stack { display: flex; flex-direction: column; gap: var(--s-2); }
.routine-note { padding-top: var(--s-2); }

.routine-card {
  padding: var(--s-4);
  border-radius: var(--r-card);
  background:
    linear-gradient(180deg,
      color-mix(in srgb, var(--g-tint, var(--g1)) calc(var(--glass-colour) * 0.7), transparent) 0%,
      transparent 100%),
    linear-gradient(180deg, var(--glass-tint) 0%, var(--glass-tint-2) 100%);
  -webkit-backdrop-filter: var(--blur-glass);
  backdrop-filter: var(--blur-glass);
  border: 0.5px solid var(--glass-edge);
  box-shadow: var(--lift-1), inset 0 1px 0 var(--glass-sheen);
}
.routine-card.is-complete { --glass-colour: 22%; }

.rc-head { display: flex; align-items: center; gap: var(--s-3); }
.rc-icon {
  flex: 0 0 auto;
  width: 36px; height: 36px;
  border-radius: 11px;
  display: grid; place-items: center;
  color: var(--g-icon, var(--g1));
  background: color-mix(in srgb, var(--g1) 30%, transparent);
}
.rc-title { flex: 1 1 auto; min-width: 0; }
.rc-name {
  font-size: var(--t-body);
  font-weight: 600;
  letter-spacing: var(--tt-body);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.rc-sub { margin-top: 1px; font-size: var(--t-meta); color: var(--text-2); }
.rc-edit {
  position: relative;
  flex: 0 0 auto;
  width: 32px; height: 32px;
  display: grid; place-items: center;
  border-radius: 50%;
  color: var(--text-3);
  transition: transform var(--dur-micro) var(--snap), color var(--dur-micro) linear;
}
.rc-edit::before { content: ""; position: absolute; width: var(--tap); height: var(--tap); }
.rc-edit:active { transform: scale(0.9); color: var(--text-1); }

/* the chain: one link per step, in order */
.rc-chain { display: flex; gap: 4px; margin-top: var(--s-4); }
.chain-link {
  flex: 1 1 0;
  height: 5px;
  border-radius: var(--r-pill);
  background: var(--track);
  display: block;
  transition: background-color var(--dur-fast) var(--settle);
}
.chain-link.is-complete { background: var(--g-progress, var(--g1)); }
.chain-link.is-partial  { background: color-mix(in srgb, var(--g-progress, var(--g1)) 45%, transparent); }
.chain-link.is-skipped  { background: var(--hairline); }

.rc-next {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  width: 100%;
  min-height: var(--tap);
  margin-top: var(--s-3);
  padding: 0 var(--s-3);
  border-radius: var(--r-pill);
  background: var(--mat-control);
  text-align: left;
  transition: transform var(--dur-micro) var(--settle), background-color var(--dur-micro) linear;
}
.rc-next:active { transform: scale(0.98); background: var(--mat-control-hi); }
.rc-next-label {
  flex: 0 0 auto;
  font-size: var(--t-label);
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--text-3);
}
.rc-next-name {
  flex: 1 1 auto; min-width: 0;
  font-size: var(--t-secondary);
  font-weight: 600;
  letter-spacing: var(--tt-body);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.rc-chev { flex: 0 0 auto; color: var(--text-3); }

/* ---------- the routine editor ---------- */
.routine-preview { margin-bottom: var(--s-6); }
.routine-empty-note {
  margin-top: var(--s-2);
  font-size: var(--t-secondary);
  color: var(--text-2);
  line-height: 1.5;
}
.routine-steps {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin: var(--s-2) 0 0;
  padding: 0;
  list-style: none;
}
.routine-step {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  min-height: 56px;
  padding: 0 var(--s-2) 0 var(--s-3);
  border-radius: var(--r-pill);
  background: color-mix(in srgb, var(--g1) 12%, var(--mat-control));
  border: 0.5px solid color-mix(in srgb, var(--g1) 22%, transparent);
}
.rs-index {
  flex: 0 0 auto;
  width: 22px; height: 22px;
  display: grid; place-items: center;
  border-radius: 50%;
  font-size: var(--t-label);
  font-weight: 700;
  color: var(--g-icon, var(--g1));
  background: color-mix(in srgb, var(--g1) 26%, transparent);
}
.rs-icon { flex: 0 0 auto; display: grid; place-items: center; color: var(--g-icon, var(--g1)); }
.rs-name {
  flex: 1 1 auto; min-width: 0;
  font-size: var(--t-secondary);
  font-weight: 600;
  letter-spacing: var(--tt-body);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.rs-move { flex: 0 0 auto; display: flex; }
.rs-arrow {
  position: relative;
  width: 30px; height: 34px;
  display: grid; place-items: center;
  color: var(--text-2);
  border-radius: 8px;
}
.rs-arrow::before { content: ""; position: absolute; width: var(--tap); height: var(--tap); }
.rs-arrow:disabled { opacity: 0.25; }
.rs-arrow .is-up { transform: rotate(180deg); }
.rs-arrow:active:not(:disabled) { color: var(--text-1); }
.rs-remove {
  position: relative;
  flex: 0 0 auto;
  width: 32px; height: 32px;
  display: grid; place-items: center;
  border-radius: 50%;
  color: var(--text-3);
  transition: transform var(--dur-micro) var(--snap), color var(--dur-micro) linear;
}
.rs-remove::before { content: ""; position: absolute; width: var(--tap); height: var(--tap); }
.rs-remove:active { transform: scale(0.88); color: var(--destructive); }

.routine-pool { margin-top: var(--s-4); }
.routine-pool-title { margin-bottom: var(--s-2); color: var(--text-3); }
.chip.routine-add {
  gap: 7px;
  color: var(--text-1);
  border-color: color-mix(in srgb, var(--g1) 30%, transparent);
}
.chip.routine-add svg { color: var(--g-icon, var(--g1)); }

/* ============================================================
   SUPPLIED ARTWORK — normalisation
   ============================================================ */
/* These marks come from several icon sets and are drawn at several
   weights on several grids. Rendering them raw puts a hairline pulse
   next to a solid boxing glove. Two rules bring them into one family:
   the box is square and centred, and anything stroked is pulled back to
   the weight the rest of the interface uses. */
svg[data-supplied] { display: block; overflow: visible; }

/* A filled silhouette reads heavier than an outline of the same box, so
   the solid ones are set a little smaller. It is optical compensation, not
   a fix: those seven would have to be redrawn as outlines for the set to
   be genuinely uniform. */
svg[data-supplied="fill"] { transform: scale(0.87); transform-origin: center; }

/* every place a mark sits in a frame, it sits in the middle of it */
.gc-icon, .chip-icon, .rc-icon, .rr-icon, .mind-mark,
.picker-cell, .suggest, .rs-icon, .island-tab {
  line-height: 0;
}
.gc-icon svg, .chip-icon svg, .rc-icon svg, .rr-icon svg,
.picker-cell svg, .rs-icon svg { display: block; }

/* ============================================================
   THE ISLAND'S TWO LANES
   ============================================================ */
.island-lane { display: flex; flex: 1 1 auto; min-width: 0; position: relative; }
.island-lane[hidden] { display: none; }

/* the way out, always leading */
.island-back {
  position: relative;
  flex: 0 0 auto;
  width: 44px;
  display: grid; place-items: center;
  border-radius: 999px;
  color: var(--text-1);
  transition: transform var(--dur-micro) var(--snap), background-color var(--dur-micro) linear;
}
.island-back:active { transform: scale(0.9); background: rgba(255,255,255,0.08); }

.island-choices {
  position: relative;
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  gap: 2px;
}
.island-choice {
  position: relative; z-index: 2;
  flex: 1 1 0; min-width: 0;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: -0.005em;
  color: var(--text-2);
  white-space: nowrap;
  transition: color var(--dur-fast) var(--settle);
}
.island-choice[aria-selected="true"] { color: var(--text-1); }

/* the same travelling pane the destinations use */
.ctx-indicator {
  position: absolute;
  z-index: 1;
  top: 0; bottom: 0; left: 0;
  border-radius: 999px;
  background: rgba(255,255,255,0.11);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.14);
  transition: transform 250ms var(--snap), width 250ms var(--snap);
}
:root[data-theme="light"] .ctx-indicator {
  background: rgba(255,255,255,0.92);
  box-shadow: 0 1px 3px rgba(0,0,0,0.06);
}

/* a screen that belongs to no destination lights none of them */
.island-indicator[hidden] { display: none; }

/* ============================================================
   THE READING LIBRARY
   ============================================================ */
/* A shelf, not a checklist. It borrows the glass, the radii, the spacing
   scale and the goal's own colour from everything else — the only new idea
   here is the cover. */
.lib-empty { padding-top: var(--s-2); }
.lib-block + .lib-block { margin-top: var(--s-8); }
.lib-title { margin-bottom: var(--s-3); color: var(--text-3); }

/* ---------- the cover ---------- */
.lib-cover {
  flex: 0 0 auto;
  position: relative;
  width: 44px;
  aspect-ratio: 2 / 3;
  border-radius: 4px 7px 7px 4px;
  overflow: hidden;
  background: var(--surface-2);
  /* a spine, and the light that falls across a standing book */
  box-shadow:
    inset 3px 0 0 rgba(0,0,0,0.22),
    inset -1px 0 0 rgba(255,255,255,0.10),
    var(--lift-1);
}
.lib-cover img { width: 100%; height: 100%; object-fit: cover; display: block; }
.lib-cover.is-drawn {
  background:
    linear-gradient(160deg,
      color-mix(in srgb, var(--g1) calc(46% + var(--lift, 0%)), transparent),
      color-mix(in srgb, var(--g2) calc(64% + var(--lift, 0%)), transparent));
  display: grid;
  place-items: center;
}
.lib-initials {
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.02em;
  color: var(--gink, #fff);
  opacity: 0.92;
  transform: rotate(var(--tilt, 0deg));
}
.lib-cover.is-large { width: 78px; border-radius: 5px 10px 10px 5px; }
.lib-cover.is-large .lib-initials { font-size: 21px; }

/* ---------- currently reading ---------- */
.lib-open {
  display: flex;
  gap: var(--s-4);
  padding: var(--s-4);
  border-radius: var(--r-card);
  background:
    linear-gradient(180deg,
      color-mix(in srgb, var(--g-tint, var(--g1)) calc(var(--glass-colour) * 0.8), transparent) 0%,
      transparent 100%),
    linear-gradient(180deg, var(--glass-tint) 0%, var(--glass-tint-2) 100%);
  -webkit-backdrop-filter: var(--blur-glass);
  backdrop-filter: var(--blur-glass);
  border: 0.5px solid var(--glass-edge);
  box-shadow: var(--lift-1), inset 0 1px 0 var(--glass-sheen);
}
.lib-open-body { flex: 1 1 auto; min-width: 0; }
.lib-name {
  font-size: var(--t-body);
  font-weight: 600;
  letter-spacing: var(--tt-body);
  line-height: 1.25;
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}
.lib-author {
  margin-top: 2px;
  font-size: var(--t-meta);
  color: var(--text-2);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.lib-bar {
  height: 5px;
  margin-top: var(--s-3);
  border-radius: var(--r-pill);
  background: var(--track);
  overflow: hidden;
}
.lib-bar i {
  display: block; height: 100%;
  border-radius: var(--r-pill);
  background: var(--g-progress, var(--g1));
  transition: width var(--dur-progress) var(--settle);
}
.lib-meta { margin-top: 7px; font-size: var(--t-meta); color: var(--text-2); }
.lib-left { margin-top: 1px; font-size: var(--t-meta); color: var(--text-3); }

.lib-actions { display: flex; gap: var(--s-2); margin-top: var(--s-3); }
.lib-action {
  min-height: 34px;
  padding: 0 var(--s-4);
  border-radius: var(--r-pill);
  background: var(--mat-control);
  color: var(--text-1);
  font-size: var(--t-meta);
  font-weight: 600;
  transition: transform var(--dur-micro) var(--snap), background-color var(--dur-micro) linear;
}
.lib-action::before { content: ""; position: absolute; }
.lib-action { position: relative; }
.lib-action:active { transform: scale(0.95); background: var(--mat-control-hi); }

/* ---------- nothing open ---------- */
.lib-start {
  display: flex;
  align-items: center;
  gap: var(--s-4);
  width: 100%;
  padding: var(--s-3) var(--s-4);
  text-align: left;
  border-radius: var(--r-lg);
  background: var(--mat-control);
  transition: transform var(--dur-micro) var(--settle), background-color var(--dur-micro) linear;
}
.lib-start:active { transform: scale(0.985); background: var(--mat-control-hi); }
.lib-chev { flex: 0 0 auto; color: var(--text-3); }

/* ---------- up next ---------- */
.lib-queue {
  list-style: none;
  margin: 0; padding: 0;
  display: flex; flex-direction: column; gap: 6px;
}
.lib-row {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  padding: var(--s-2) var(--s-2) var(--s-2) var(--s-3);
  border-radius: var(--r-lg);
  background: var(--mat-control);
}
.lib-row-body { flex: 1 1 auto; min-width: 0; }
.lib-row .lib-name { font-size: var(--t-secondary); -webkit-line-clamp: 1; }
.lib-move { flex: 0 0 auto; display: flex; }
.lib-open-now {
  position: relative;
  flex: 0 0 auto;
  width: 32px; height: 32px;
  display: grid; place-items: center;
  border-radius: 50%;
  color: var(--g-icon, var(--g1));
  background: color-mix(in srgb, var(--g1) 22%, transparent);
  transition: transform var(--dur-micro) var(--snap);
}
.lib-open-now::before { content: ""; position: absolute; width: var(--tap); height: var(--tap); }
.lib-open-now:active { transform: scale(0.9); }

/* ---------- completed ---------- */
/* Two columns, so a long shelf reads as an accumulation rather than as an
   ever-growing list. */
.lib-shelf {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: var(--s-2);
}
.lib-done {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  padding: var(--s-2);
  border-radius: var(--r-md);
  text-align: left;
  transition: transform var(--dur-micro) var(--snap), background-color var(--dur-micro) linear;
}
.lib-done:active { transform: scale(0.97); background: var(--mat-control); }
.lib-done .lib-cover { width: 32px; }
.lib-done .lib-initials { font-size: 10px; }
.lib-done-body { flex: 1 1 auto; min-width: 0; }
.lib-done .lib-name { font-size: var(--t-meta); font-weight: 600; -webkit-line-clamp: 2; }
.lib-done .lib-author { font-size: 11px; }
