/* span — design foundation.
   Neutral-grey paper, Lato at hiccup-style sizes/weights (bold headings,
   black display), quiet and editorial. Activities carry deep-ink accent
   colors (11 muted hues + neutral grey); error red stays reserved.
   Dark theme follows replicant.fun/hiccup: soft blue-grey, not black.
   /styleguide is the living reference for everything in here. */

/* Lato has no CJK glyphs: Japanese and Chinese ride Noto Sans (JP/SC),
   applied by the page language below. Offline these fall back to system
   fonts, same as any external font. Lato itself stays vendored. */
@import url('https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@100..900&family=Noto+Sans+SC:wght@100..900&display=swap');

@font-face {
  font-family: "Lato";
  src: url("/assets/lato-light-93430320.woff2") format("woff2");
  font-weight: 300;
  font-display: swap;
}
@font-face {
  font-family: "Lato";
  src: url("/assets/lato-regular-ed5505fb.woff2") format("woff2");
  font-weight: 400;
  font-display: swap;
}
@font-face {
  font-family: "Lato";
  src: url("/assets/lato-bold-3cf28fc1.woff2") format("woff2");
  font-weight: 700;
  font-display: swap;
}
@font-face {
  font-family: "Lato";
  src: url("/assets/lato-black-540da9ba.woff2") format("woff2");
  font-weight: 900;
  font-display: swap;
}

:root {
  /* Neutral paper + pure ink (light) */
  --paper: rgb(242, 242, 242);
  --ink: rgb(0, 0, 0);
  --ink-rgb: 0, 0, 0;

  --error: rgb(196, 43, 28);

  /* Deep-ink activity palette — 11 muted hues + neutral grey.
     Activity.tint indexes into these (0..11). */
  --activity-0: #21B14C;  /* green */
  --activity-1: #12B5A5;  /* teal */
  --activity-2: #3E8DF9;  /* azure — the scribble blue */
  --activity-3: #7A6BF2;  /* violet */
  --activity-4: #AD5BDD;  /* orchid */
  --activity-5: #F0538D;  /* rose */
  --activity-6: #FF6B4A;  /* coral — the scribble coral */
  --activity-7: #FF8A1E;  /* orange */
  --activity-8: #F5A800;  /* amber */
  --activity-9: #A2B517;  /* lime */
  --activity-10: #2EBD8B; /* sea */
  --activity-11: #7A828E; /* neutral */

  /* Heatmap ramp — forest at rising strength; level 0 is faint ink */
  --heat-rgb: 33, 177, 76;
  --heat-0: rgba(var(--ink-rgb), 0.06);
  --heat-1: rgba(var(--heat-rgb), 0.18);
  --heat-2: rgba(var(--heat-rgb), 0.40);
  --heat-3: rgba(var(--heat-rgb), 0.68);
  --heat-4: rgba(var(--heat-rgb), 1);

  --subtle: rgba(var(--ink-rgb), 0.55);
  --hairline: rgba(var(--ink-rgb), 0.16);
  --surface: rgba(var(--ink-rgb), 0.05);
  /* Form-control boundary: stronger than the decorative hairline so inputs
     clear WCAG 1.4.11's 3:1 (adapts per theme via --ink-rgb). */
  --field-border: rgba(var(--ink-rgb), 0.44);
  /* Legible green for the "username available" hint (activity-0 as text is
     only 2.5:1 on paper). Dark theme's brighter green already passes. */
  --ok-text: #0F7A32;

  /* Spacing scale */
  --space-1: 0.2rem;
  --space-2: 0.4rem;
  --space-3: 0.8rem;
  --space-4: 1.2rem;
  --space-5: 1.6rem;
  --space-6: 2.4rem;
  --space-7: 3.2rem;
  --space-8: 4.8rem;
  --space-9: 6.4rem;

  /* Type scale — hiccup's ladder (12/14/16/20/24/30/48) on the 62.5% root */
  --text-tiny: 1.2rem;
  --text-small: 1.4rem;
  --text-body: 1.6rem;
  --text-large: 2rem;
  --text-heading: 2.4rem;
  --text-title: 3rem;
  --text-display: 4.8rem;
  --text-figure: 5.6rem;

  --radius: 0.2rem;
  --measure: 64rem;
}

@media (prefers-color-scheme: dark) {
  :root {
    color-scheme: dark;
    /* hiccup's dark: soft blue-grey paper, whitish ink */
    --paper: rgb(29, 35, 42);
    --ink: rgb(235, 236, 240);
    --ink-rgb: 235, 236, 240;
    --error: rgb(232, 90, 74);
    --activity-0: #37C767;
    --activity-1: #2BCFBE;
    --activity-2: #62A5FF;
    --activity-3: #948AFF;
    --activity-4: #C577F0;
    --activity-5: #FF74A6;
    --activity-6: #FF8266;
    --activity-7: #FFA04D;
    --activity-8: #FFB833;
    --activity-9: #BFD435;
    --activity-10: #4AD8A6;
    --activity-11: #9AA3AF;
    --heat-rgb: 55, 199, 103;
    --ok-text: #37C767; /* dark theme's brighter green passes on dark paper */
  }
}
:root[data-theme="light"] {
  color-scheme: light;
  --paper: rgb(242, 242, 242);
  --ink: rgb(0, 0, 0);
  --ink-rgb: 0, 0, 0;
  --error: rgb(196, 43, 28);
  --activity-0: #21B14C;
  --activity-1: #12B5A5;
  --activity-2: #3E8DF9;
  --activity-3: #7A6BF2;
  --activity-4: #AD5BDD;
  --activity-5: #F0538D;
  --activity-6: #FF6B4A;
  --activity-7: #FF8A1E;
  --activity-8: #F5A800;
  --activity-9: #A2B517;
  --activity-10: #2EBD8B;
  --activity-11: #7A828E;
  --heat-rgb: 33, 177, 76;
  --ok-text: #0F7A32;
}
:root[data-theme="dark"] {
  color-scheme: dark;
  --paper: rgb(29, 35, 42);
  --ink: rgb(235, 236, 240);
  --ink-rgb: 235, 236, 240;
  --error: rgb(232, 90, 74);
  --activity-0: #37C767;
  --activity-1: #2BCFBE;
  --activity-2: #62A5FF;
  --activity-3: #948AFF;
  --activity-4: #C577F0;
  --activity-5: #FF74A6;
  --activity-6: #FF8266;
  --activity-7: #FFA04D;
  --activity-8: #FFB833;
  --activity-9: #BFD435;
  --activity-10: #4AD8A6;
  --activity-11: #9AA3AF;
  --heat-rgb: 55, 199, 103;
  --ok-text: #37C767; /* dark theme's brighter green passes on dark paper */
}

/* ---- Base ---------------------------------------------------------- */

html {
  font-size: 62.5%;
  -webkit-text-size-adjust: 100%;
  /* A liquid feel: in-page jumps glide, and the page doesn't chain its
     scroll to whatever is behind it (no rubber-band bleed to the browser). */
  scroll-behavior: smooth;
  overscroll-behavior-y: none;
}
/* Honour reduced-motion: no glide for those who ask for stillness — which
   also keeps the automated browser's scroll instant, so it doesn't race. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
}

/* Phone-first sizes read small on big screens: scale the root and the
   whole rem-based rhythm (type, spacing, tiles) zooms coherently. */
@media (min-width: 880px) {
  html { font-size: 70%; }
}
@media (min-width: 1400px) {
  html { font-size: 75%; }
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: "Lato", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  font-size: var(--text-body);
  font-weight: 400;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

/* The signed-out landing: hero and a still-life of the home screen, with
   scribbble-style color accents (the only place span allows itself vivid
   ink). Phone-first; from 880px the hero goes two-column. */
:root {
  --scribble-coral: #FF6B4A;
  --scribble-amber: #FFB020;
  --scribble-azure: #3E8DF9;
}
.wrap--wide { max-width: 78rem; }
/* Shared by every signed-out page (landing, /why, auth) via
   shared/_public_header. */
.public-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: var(--space-4) 0 var(--space-8);
}
.public-header__nav { display: flex; align-items: center; gap: var(--space-4); font-size: var(--text-small); }
.landing__hero-grid { display: grid; gap: var(--space-8); }
.landing__hero { position: relative; }
/* h1-qualified: .display (a later rule, same specificity) zeroes margins,
   and the scribble underline needs the room below. */
h1.landing__headline { position: relative; display: inline-block; margin-bottom: var(--space-7); }
.landing__sub { max-width: 34ch; }
.landing__cta-row { position: relative; display: inline-block; margin: 0; }
.landing__note { font-size: var(--text-small); margin-top: var(--space-3); }
.landing__scribble { position: absolute; pointer-events: none; }
.landing__scribble--underline { width: 12rem; left: 0; bottom: -1.1rem; }
.landing__scribble--spark { width: 2rem; right: -1.5rem; top: -1.1rem; }
/* #85 is a near-square hand loop; preserveAspectRatio:none lets it flatten
   into a wide ellipse that lassos the clock. z-index:-1 keeps it behind the
   digits so the brush ring never covers them. */
.landing__scribble--circle { width: 12rem; height: 5.2rem; left: 50%; top: 50%; transform: translate(-50%, -50%); z-index: -1; }
/* #50's arrowhead points up-right; rotate it so the head dives down at the
   circled time from the top-left. */
.landing__scribble--arrow { width: 5.5rem; top: -2.2rem; left: 1.5rem; transform: rotate(68deg); }
.landing__mockwrap { position: relative; margin: var(--space-6) 0; }
.landing__mock {
  background: var(--surface);
  border-radius: var(--radius);
  padding: var(--space-6);
}
/* z-index:0 makes this a stacking context so the circle scribble (z-index:-1)
   sits behind the digits instead of painting over them. */
.landing__clock { font-weight: 900; font-size: var(--text-title); margin: 0; position: relative; display: inline-block; z-index: 0; }
.landing__label { font-size: var(--text-small); margin: 0 0 var(--space-4); }
.landing__tiles { display: flex; gap: var(--space-4); margin-bottom: var(--space-4); }
.landing__tiles .tile__circ { width: 3rem; height: 3rem; }
.landing__heat { display: flex; gap: 3px; --heat-cell: 1.2rem; }
.landing__features {
  display: flex;
  gap: var(--space-6);
  margin: var(--space-9) 0;
}
.landing__features > div { flex: 1; }
.landing__illustration { display: inline-block; width: 4.4rem; }
.landing__illustration svg { width: 100%; height: auto; }
.landing__features h3 { font-size: var(--text-body); margin: var(--space-2) 0; }
.landing__features p { font-size: var(--text-small); }
.landing__foot { text-align: center; margin: var(--space-9) 0; }
.landing__foot .subtle { font-size: var(--text-small); margin-top: var(--space-4); }
@media (min-width: 880px) {
  .landing__hero-grid {
    grid-template-columns: 1.15fr 1fr;
    align-items: center;
    gap: var(--space-9);
    min-height: 24rem;
  }
  h1.landing__headline { font-size: 3.6rem; line-height: 1.12; max-width: 16ch; }
  .landing__mockwrap { margin: 0; }
}
@media (max-width: 540px) {
  .landing__features { flex-direction: column; }
  .landing__scribble--spark { right: -1.3rem; }
}

/* The studio's quiet signature at the bottom of every page. */
.site-footer {
  margin-top: var(--space-9);
  padding-top: var(--space-5);
  border-top: 1px solid var(--hairline);
  text-align: center;
}
.site-footer .subtle { font-size: var(--text-tiny); margin: 0; }
.site-footer__landmark {
  width: 1.5rem;
  height: 1.5rem;
  display: inline-block;
  vertical-align: -0.3rem;
}
/* One quiet links row under the studio mark; the landing adds its
   illustration credit here, middot-separated only when present. */
.site-footer .site-footer__links {
  display: flex;
  justify-content: center;
  gap: var(--space-2);
  margin-top: var(--space-2);
}
.site-footer__links > * + *::before { content: "·"; margin-right: var(--space-2); }
.site-footer__credit { opacity: 0.7; }

/* /why — the maker's essay. It borrows the public chrome (public-header,
   landing__foot) and reads as one quiet column. */
.why__essay { max-width: 62ch; margin: 0 auto; }
/* h1-qualified: .display (a later rule, same specificity) zeroes margins. */
h1.why__headline { position: relative; display: inline-block; margin-bottom: var(--space-7); }
.why__essay p { margin: 0 0 var(--space-5); }
.why__scribble { position: absolute; pointer-events: none; }
.why__scribble--underline { width: 12rem; left: 0; bottom: -1.1rem; }
.why__squares {
  display: inline-flex;
  gap: 3px;
  margin-left: var(--space-1);
  vertical-align: baseline;
  --heat-cell: 0.85rem;
}
.why__signed { margin-top: var(--space-7); }
.why__reading { max-width: 62ch; margin: var(--space-9) auto; }
.why__reading h2 { font-size: var(--text-body); margin: 0 0 var(--space-3); }
.why__reading-list { list-style: none; padding: 0; margin: 0; font-size: var(--text-small); }
.why__reading-list li { margin-bottom: var(--space-2); }

/* /pricing — the values first, the numbers second. Sibling of /why:
   same public chrome, same quiet column, plus two hairline tier cards. */
.pricing__lead { max-width: 62ch; margin: 0 auto; }
/* h1-qualified: .display (a later rule, same specificity) zeroes margins. */
h1.pricing__headline { position: relative; display: inline-block; margin-bottom: var(--space-7); }
.pricing__lead p { margin: 0 0 var(--space-5); }
.pricing__scribble { position: absolute; pointer-events: none; width: 12rem; left: 0; bottom: -1.1rem; }
.pricing__values { max-width: 62ch; margin: var(--space-7) auto; display: grid; gap: var(--space-5); }
.pricing__values h2 { font-size: var(--text-body); margin: 0 0 var(--space-1); }
.pricing__values p { margin: 0; font-size: var(--text-small); }
.pricing__support { max-width: 62ch; margin: var(--space-8) auto 0; }
.pricing__support > .btn { margin-top: var(--space-4); }
.pricing__tiers { max-width: 62ch; margin: var(--space-8) auto; display: grid; gap: var(--space-5); }
.pricing__tier {
  border: 1px solid var(--hairline);
  border-radius: var(--radius);
  padding: var(--space-5);
}
.pricing__tier h2 { font-size: var(--text-heading); margin: 0 0 var(--space-2); }
.pricing__tier > .subtle { font-size: var(--text-small); margin: 0 0 var(--space-4); }
.pricing__price { font-size: var(--text-large); margin: 0 0 var(--space-2); }
.pricing__price-alt { font-size: var(--text-small); }
.pricing__soon {
  font-size: var(--text-tiny);
  vertical-align: middle;
  padding: var(--space-1) var(--space-2);
  border: 1px solid var(--hairline);
  border-radius: var(--radius);
}
.pricing__feats { list-style: none; padding: 0; margin: 0 0 var(--space-5); font-size: var(--text-small); }
.pricing__feats li { margin-bottom: var(--space-2); padding-left: var(--space-4); position: relative; }
/* the heatmap's filled square as the bullet — the product's own mark */
.pricing__feats li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.45em;
  width: 0.65rem;
  height: 0.65rem;
  border-radius: 2px;
  background: var(--scribble-amber);
}
.pricing__interest { display: flex; gap: var(--space-2); flex-wrap: wrap; }
.pricing__interest .field { flex: 1; min-width: 12rem; margin: 0; }
.pricing__note { font-size: var(--text-tiny); margin: var(--space-3) 0 0; }
@media (min-width: 880px) {
  .pricing__values { grid-template-columns: 1fr 1fr; gap: var(--space-6) var(--space-7); }
  .pricing__tiers { max-width: 76ch; grid-template-columns: 1fr 1fr; align-items: start; }
}

/* /donate — the coffee pitch. Sibling of /why and /pricing:
   same public chrome, same quiet column. */
.donate__lead { max-width: 62ch; margin: 0 auto; }

/* /privacy — the plain account of what span stores. Sibling of /why:
   same public chrome, same quiet column. English-only by design. */
.privacy__essay { max-width: 62ch; margin: 0 auto; }
/* h1-qualified: .display (a later rule, same specificity) zeroes margins. */
h1.privacy__headline { margin-bottom: var(--space-2); }
.privacy__essay h2 { font-size: var(--text-body); margin: var(--space-7) 0 var(--space-3); }
.privacy__essay p { margin: 0 0 var(--space-5); }
/* after the p rule and essay-qualified: outranks .privacy__essay p (0,1,1) */
.privacy__essay .privacy__updated { margin-bottom: var(--space-7); }
.privacy__essay ul { margin: 0 0 var(--space-5); padding-left: 1.2rem; }
.privacy__essay li { margin-bottom: var(--space-3); }

/* OAuth-first auth: stacked provider buttons, a quiet divider, the email
   form folded behind a disclosure. */
.oauth { display: flex; flex-direction: column; gap: var(--space-3); max-width: 24rem; }
.oauth__btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-3);
  width: 100%;
  padding: var(--space-3) var(--space-4);
  background: var(--paper);
  color: var(--ink);
  border: 1px solid var(--hairline);
  border-radius: var(--radius);
  font: inherit;
  font-size: var(--text-small);
  font-weight: 700;
  cursor: pointer;
}
.oauth__btn:hover { border-color: var(--ink); }
.oauth__logo { width: 1.8rem; height: 1.8rem; flex: none; }
.oauth__or { font-size: var(--text-small); margin: var(--space-4) 0; }
.oauth-email summary {
  cursor: pointer;
  font-size: var(--text-small);
  text-decoration: underline;
  list-style: none;
}
.oauth-email summary::-webkit-details-marker { display: none; }
.oauth-email[open] summary { margin-bottom: var(--space-4); }

/* Auth pages: the tagline sits close under the heading; the motif is a
   quiet row of activity-ink dots echoing the tile grid. */
.auth-tagline { margin-top: calc(-1 * var(--space-4)); }
.auth-motif {
  display: flex;
  gap: var(--space-2);
  margin-bottom: var(--space-6);
}
.auth-motif span { width: 0.75rem; height: 0.75rem; border-radius: 50%; }
.auth-motif span:nth-child(1) { background: var(--activity-0); }
.auth-motif span:nth-child(2) { background: var(--activity-2); }
.auth-motif span:nth-child(3) { background: var(--activity-5); }
.auth-motif span:nth-child(4) { background: var(--activity-7); }
.auth-motif span:nth-child(5) { background: var(--activity-9); }
.auth-motif span:nth-child(6) { background: var(--activity-3); }

/* Onboarding's suggestion chips toggle instead of submitting: hidden
   checkbox, picked state rings the chip like a selected tile. */
.onboarding-pick { cursor: pointer; }
.onboarding-pick input { position: absolute; opacity: 0; pointer-events: none; }
.onboarding-pick:has(input:checked) {
  border-color: var(--ink);
  box-shadow: 0 0 0 1px var(--ink);
}

/* The language switcher: a flag that unfolds into flag+name rows.
   Signed out it sits alone in a right-aligned bar above the auth card. */
.locale-menu { position: relative; }
.locale-menu summary {
  list-style: none;
  cursor: pointer;
  display: flex;
  align-items: center;
}
.locale-menu summary::-webkit-details-marker { display: none; }
.locale-menu__flag {
  width: 2rem;
  height: 1.5rem;
  border-radius: 2px;
  box-shadow: 0 0 0 1px var(--hairline);
  display: block;
}
.locale-menu__list {
  position: absolute;
  right: 0;
  top: calc(100% + var(--space-2));
  z-index: 10;
  background: var(--paper);
  border: 1px solid var(--hairline);
  border-radius: var(--radius);
  padding: var(--space-2);
  min-width: 16rem;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);
}
.locale-menu__item {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  width: 100%;
  padding: var(--space-2) var(--space-3);
  border: none;
  border-radius: var(--radius);
  background: transparent;
  color: var(--ink);
  font: inherit;
  font-size: var(--text-small);
  text-align: left;
  cursor: pointer;
}
.locale-menu__item:hover { background: var(--surface); }
.locale-menu__item.is-current { font-weight: 700; }
.locale-bar {
  display: flex;
  justify-content: flex-end;
  margin-bottom: var(--space-4);
}

/* The notification bell dropdown: same details-menu shape as the locale
   picker, with a wider panel for the longer notification lines. */
.notif-menu { position: relative; }
.notif-menu summary { list-style: none; cursor: pointer; }
.notif-menu summary::-webkit-details-marker { display: none; }
.notif-menu__list {
  position: absolute;
  right: 0;
  top: calc(100% + var(--space-2));
  z-index: 10;
  background: var(--paper);
  border: 1px solid var(--hairline);
  border-radius: var(--radius);
  padding: var(--space-2);
  min-width: 20rem;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);
}
.notif-menu__item {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius);
  color: var(--ink);
  font-size: var(--text-small);
  text-decoration: none;
}
.notif-menu__item:hover { background: var(--surface); }
.notif-menu__dot {
  flex: none;
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 999px;
  background: transparent;
}
.notif-menu__item.is-unread .notif-menu__dot { background: var(--activity-6); }
.notif-menu__empty {
  padding: var(--space-2) var(--space-3);
  font-size: var(--text-small);
}
.notif-menu__all {
  display: block;
  margin-top: var(--space-2);
  padding: var(--space-2) var(--space-3);
  border-top: 1px solid var(--hairline);
  color: var(--ink);
  font-size: var(--text-small);
  font-weight: 700;
  text-decoration: none;
}
.notif-menu__all:hover { background: var(--surface); }

/* CJK pages lead with their Noto family; Lato still covers Latin glyphs
   and numerals inside them. */
:lang(ja) body {
  font-family: "Noto Sans JP", "Lato", ui-sans-serif, system-ui, sans-serif;
}
:lang(zh-CN) body {
  font-family: "Noto Sans SC", "Lato", ui-sans-serif, system-ui, sans-serif;
}

h1, h2, h3 {
  font-weight: 700;
  line-height: 1.2;
  text-wrap: balance;
  margin: 0 0 var(--space-4);
}
h1 { font-size: var(--text-title); }
h2 { font-size: var(--text-heading); }
h3 { font-size: var(--text-large); }

p { margin: 0 0 var(--space-4); }

a {
  color: var(--ink);
  text-decoration: underline;
  /* Quiet faint-ink underline at rest; a:hover lifts it to full ink. */
  text-decoration-color: rgba(var(--ink-rgb), 0.26);
  text-underline-offset: 0.2em;
}
a:hover { text-decoration-color: var(--ink); }

hr {
  border: 0;
  border-top: 1px solid var(--hairline);
  margin: var(--space-7) 0;
}

strong, b { font-weight: 700; }

::selection { background: rgba(var(--ink-rgb), 0.14); }

/* Keyboard focus is always visible, on both themes; mouse stays quiet. */
:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* ---- Layout -------------------------------------------------------- */

.wrap {
  max-width: var(--measure);
  margin: 0 auto;
  padding: var(--space-5) var(--space-5) var(--space-9);
}

.site-header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-5);
  padding: var(--space-5) 0 var(--space-7);
}

.site-header__wordmark {
  font-weight: 900;
  font-size: var(--text-body);
  text-decoration: none;
}

/* Inline (not flex) so the link's baseline stays the text's — .site-header
   aligns wordmark and nav by baseline. The mark hangs off the text line,
   nudged to optically center on the lowercase x-height. */
.site-header__wordmark .logo-mark {
  vertical-align: -0.34em;
  margin-right: 7px;
}

.site-header nav {
  display: flex;
  align-items: baseline;
  gap: var(--space-5);
  font-size: var(--text-small);
}

/* Primary nav links: text on desktop (icons hidden here); quiet by default,
   the current tab carries the ink. */
.site-header nav > a { display: inline-flex; align-items: center; color: var(--subtle); text-decoration: none; }
.site-header nav > a:hover { color: var(--ink); }
.site-header nav > a.is-current { color: var(--ink); text-decoration: underline; text-underline-offset: 3px; font-weight: 700; }
.site-header nav > a .icon { display: none; }

/* Hairline divider marking the boundary between the primary links and the
   bell + utilities cluster. */
.nav-divider {
  align-self: center;
  width: 1px;
  height: 1.1em;
  background: var(--hairline);
}

/* Tight on phones: primary nav links show their icon, the label goes sr-only
   (still announced) so the tabs stay accessible. Placed after the base rule
   above so it wins the cascade at this width. */
@media (max-width: 540px) {
  .site-header nav > a .icon {
    display: inline-flex;
    width: 1.5rem;
    height: 1.5rem;
    vertical-align: 0;
  }
  .site-header nav > a .nav-label {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
    border: 0;
  }
}

.stack > * + * { margin-top: var(--space-4); }
.stack-lg > * + * { margin-top: var(--space-7); }

/* The board heading: name first, its activity mark trailing as an accent. */
.board-title .icon {
  width: 0.85em;
  height: 0.85em;
  margin-left: var(--space-3);
  vertical-align: -0.08em;
}

/* ---- Notification bell + badge -------------------------------------- */
.site-header__bell {
  position: relative;
  display: inline-flex;
  align-items: center;
  color: inherit;
  text-decoration: none;
}

.site-header__bell .icon { width: 1.15em; height: 1.15em; }

.site-header__badge {
  position: absolute;
  top: -0.5em;
  right: -0.6em;
  min-width: 1.15em;
  padding: 0 0.3em;
  border-radius: 999px;
  background: var(--activity-6);
  color: var(--paper);
  font-size: 0.68em;
  line-height: 1.55;
  font-weight: 700;
  text-align: center;
}

.site-header__badge.is-empty { display: none; }

/* ---- Username search + accessibility hidden label ------------------- */
.search-row {
  display: flex;
  gap: var(--space-3);
  align-items: center;
}

.search-row input[type="search"] { flex: 1; min-width: 0; }

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

.notification.is-unread .data-row__name { font-weight: 700; }

/* ---- Circle leaderboard --------------------------------------------- */
.leaderboard .stats__row.is-me .stats__name { font-weight: 700; }

.callout {
  padding: var(--space-4);
  border: 1px solid var(--ink);
  border-radius: var(--space-2);
}

/* ---- Type utilities ------------------------------------------------- */

.display {
  font-size: var(--text-display);
  font-weight: 900;
  line-height: 1.05;
  margin: 0;
}

.eyebrow, .label {
  font-size: var(--text-small);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--subtle);
  margin: 0 0 var(--space-3);
}

.subtle { color: var(--subtle); }

.tnum {
  font-feature-settings: "tnum";
  font-variant-numeric: tabular-nums;
}

/* ---- Figure — the signature element --------------------------------- */

.figure { display: flex; flex-direction: column; }

.figure__value {
  font-size: var(--text-figure);
  font-weight: 900;
  line-height: 1;
  font-feature-settings: "tnum";
  font-variant-numeric: tabular-nums;
}

.figure--sm .figure__value { font-size: var(--text-display); }

.figure__value .unit {
  font-size: 0.45em;
  font-weight: 400;
  color: var(--subtle);
  margin-inline-start: 0.1em;
}

.figure__label {
  font-size: var(--text-small);
  color: var(--subtle);
  margin-top: var(--space-3);
}

.figure__actions {
  display: flex;
  gap: var(--space-3);
  margin-top: var(--space-5);
}

/* ---- Focus veil — a quiet stage while a span runs -------------------- */

.focus-veil {
  position: fixed;
  inset: 0;
  z-index: 60; /* above the navbar (10) and the feedback fab (50) */
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: var(--space-5);
  background: var(--paper); /* fallback when color-mix is unsupported */
  background: color-mix(in srgb, var(--paper) 85%, transparent);
  -webkit-backdrop-filter: blur(20px);
  backdrop-filter: blur(20px);
  opacity: 0;
  transition: opacity 0.3s ease;
}

.focus-veil.is-visible { opacity: 1; }

@media (prefers-reduced-motion: reduce) {
  .focus-veil { transition: none; }
}

/* ---- Command menu — Cmd/Ctrl+K palette -------------------------------- */

.command-menu {
  border: 1px solid var(--hairline);
  border-radius: var(--radius);
  background: var(--paper);
  color: var(--ink);
  padding: var(--space-3);
  width: min(28rem, calc(100% - var(--space-5)));
}

.command-menu::backdrop { background: rgba(0, 0, 0, 0.4); }

.command-menu__input {
  width: 100%;
  box-sizing: border-box; /* no global reset; width:100% + padding overflows the dialog otherwise */
  border: 1px solid var(--field-border);
  border-radius: var(--radius);
  background: transparent;
  color: var(--ink);
  font: inherit;
  padding: var(--space-3);
  margin-bottom: var(--space-3);
}

.command-menu__list {
  display: flex;
  flex-direction: column;
  max-height: 50vh;
  overflow-y: auto;
}

.command-menu__row {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3);
  border: 0;
  border-radius: var(--radius);
  background: none;
  color: var(--ink);
  font: inherit;
  text-align: start;
  text-decoration: none;
  cursor: pointer;
}

.command-menu__row.is-active,
.command-menu__row:hover { background: var(--surface); }

.command-menu__row .icon { width: 1.2em; height: 1.2em; flex: none; }

.command-menu__key {
  margin-inline-start: auto;
  font-size: var(--text-small);
  font-family: inherit;
  color: var(--subtle);
  border: 1px solid var(--hairline);
  border-radius: var(--radius);
  padding: 0 var(--space-2);
}

/* ---- Tint bar — activity breakdown ---------------------------------- */

.tint-bar {
  display: flex;
  height: 1rem;
  border-radius: var(--radius);
  overflow: hidden;
  gap: 2px;
}

.tint-bar__seg { min-width: 2px; }

.tint-bar__seg.is-1, .data-row__swatch.is-1 { background: var(--activity-0); }
.tint-bar__seg.is-2, .data-row__swatch.is-2 { background: var(--activity-1); }
.tint-bar__seg.is-3, .data-row__swatch.is-3 { background: var(--activity-2); }
.tint-bar__seg.is-4, .data-row__swatch.is-4 { background: var(--activity-3); }
.tint-bar__seg.is-5, .data-row__swatch.is-5 { background: var(--activity-4); }
.tint-bar__seg.is-6, .data-row__swatch.is-6 { background: var(--activity-5); }
.tint-bar__seg.is-7, .data-row__swatch.is-7 { background: var(--activity-6); }
.tint-bar__seg.is-8, .data-row__swatch.is-8 { background: var(--activity-7); }
.tint-bar__seg.is-9, .data-row__swatch.is-9 { background: var(--activity-8); }
.tint-bar__seg.is-10, .data-row__swatch.is-10 { background: var(--activity-9); }
.tint-bar__seg.is-11, .data-row__swatch.is-11 { background: var(--activity-10); }
.tint-bar__seg.is-12, .data-row__swatch.is-12 { background: var(--activity-11); }

.activity-ink.is-1 { color: var(--activity-0); }
.activity-ink.is-2 { color: var(--activity-1); }
.activity-ink.is-3 { color: var(--activity-2); }
.activity-ink.is-4 { color: var(--activity-3); }
.activity-ink.is-5 { color: var(--activity-4); }
.activity-ink.is-6 { color: var(--activity-5); }
.activity-ink.is-7 { color: var(--activity-6); }
.activity-ink.is-8 { color: var(--activity-7); }
.activity-ink.is-9 { color: var(--activity-8); }
.activity-ink.is-10 { color: var(--activity-9); }
.activity-ink.is-11 { color: var(--activity-10); }
.activity-ink.is-12 { color: var(--activity-11); }

/* ---- Theme toggle ------------------------------------------------------ */

.theme-toggle {
  appearance: none;
  border: 0;
  background: none;
  padding: 0;
  cursor: pointer;
  color: var(--subtle);
  line-height: 1;
}
.theme-toggle:hover { color: var(--ink); }

/* Show the icon for the theme you'd switch to: moon in light, sun in dark.
   Doubled class keeps these ahead of the generic .icon display rule. */
.theme-toggle .icon.theme-toggle__sun { display: none; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .theme-toggle .icon.theme-toggle__sun { display: inline-flex; }
  :root:not([data-theme="light"]) .theme-toggle .icon.theme-toggle__moon { display: none; }
}
:root[data-theme="dark"] .theme-toggle .icon.theme-toggle__sun { display: inline-flex; }
:root[data-theme="dark"] .theme-toggle .icon.theme-toggle__moon { display: none; }

/* ---- Icons ------------------------------------------------------------ */

.icon {
  display: inline-flex;
  width: 1.8rem;
  height: 1.8rem;
  flex: none;
  vertical-align: -0.3rem;
}

.icon svg { width: 100%; height: 100%; }

.figure__label .icon { width: 1.4rem; height: 1.4rem; vertical-align: -0.2rem; }

/* ---- Avatars (vendored DiceBear thumbs, CC0) ------------------------ */
.avatar {
  display: inline-flex;
  width: 2.4rem;
  height: 2.4rem;
  flex: none;
  border-radius: 999px;
  overflow: hidden;
  vertical-align: -0.6rem;
}
.avatar svg { width: 100%; height: 100%; }

/* Row-leading avatar sits before a @username. */
.avatar--row { margin-right: var(--space-3); }

.avatar--lg { width: 5.6rem; height: 5.6rem; vertical-align: 0; }

/* Current face + Change, side by side. */
.avatar-trigger { display: flex; align-items: center; gap: var(--space-4); }

/* The shared turbo_confirm dialog: one quiet question, cancel first. */
.confirm-dialog {
  border: 1px solid var(--hairline);
  border-radius: var(--radius);
  background: var(--paper);
  color: var(--ink);
  padding: var(--space-6);
  max-width: 30rem;
  width: calc(100% - var(--space-5));
}
.confirm-dialog::backdrop { background: rgba(0, 0, 0, 0.4); }
.confirm-dialog__message { margin: 0 0 var(--space-5); }
.confirm-dialog__actions {
  display: flex;
  justify-content: flex-end;
  gap: var(--space-3);
}

/* The face × color dialog, same paper as the feedback dialog. */
.avatar-dialog {
  border: 1px solid var(--hairline);
  border-radius: var(--radius);
  background: var(--paper);
  color: var(--ink);
  padding: var(--space-6);
  max-width: 34rem;
  width: calc(100% - var(--space-5));
}
.avatar-dialog::backdrop { background: rgba(0, 0, 0, 0.4); }
.avatar-dialog__title { margin: 0 0 var(--space-4); }
.avatar-dialog .label { margin: var(--space-5) 0 var(--space-3); }
.avatar-dialog .tint-picker { flex-wrap: wrap; }
.avatar-dialog > .btn { margin-top: var(--space-6); }

/* Same shape as the icon picker: hidden radios, ring on the pick. */
.avatar-picker {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  max-width: 36rem;
}
.avatar-picker__option { cursor: pointer; }
.avatar-picker__option input { position: absolute; opacity: 0; }
.avatar-picker__option .avatar {
  width: 3.6rem;
  height: 3.6rem;
  vertical-align: 0;
}
.avatar-picker__option input:checked + .avatar {
  outline: 2px solid var(--ink);
  outline-offset: 2px;
}
/* Dashed, so keyboard focus (which lands on the first radio the moment the
   dialog opens) doesn't read as a second checked face. */
.avatar-picker__option input:focus-visible + .avatar {
  outline: 2px dashed var(--subtle);
  outline-offset: 2px;
}

.icon-picker {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  max-width: 32rem;
}

.icon-picker__option { cursor: pointer; }

.icon-picker__option input { position: absolute; opacity: 0; }

.icon-picker__option .icon {
  width: 2.4rem;
  height: 2.4rem;
  padding: var(--space-2);
  border: 1px solid var(--hairline);
  border-radius: var(--radius);
  color: var(--subtle);
}

.icon-picker__option input:checked + .icon {
  color: var(--ink);
  outline: 2px solid var(--ink);
  outline-offset: 2px;
}

/* ---- Heatmap — the year wall ----------------------------------------- */

.heatmap { --heat-cell: 1.1rem; }

.heatmap__scroll {
  overflow-x: auto;
  padding-bottom: var(--space-2);
  /* The wall pins to today (right edge); the oldest visible month clips at the
     left viewport edge. Fade that edge so the past recedes instead of hard-
     cutting a half-word — today's column stays crisp. */
  -webkit-mask-image: linear-gradient(to right, transparent 0, #000 var(--space-6));
  mask-image: linear-gradient(to right, transparent 0, #000 var(--space-6));
}

.heatmap__months {
  display: grid;
  grid-template-columns: repeat(52, calc(var(--heat-cell) + 1px));
  font-size: var(--text-small);
  color: var(--subtle);
  margin-bottom: var(--space-2);
  width: max-content;
}

.heatmap__month { grid-row: 1; white-space: nowrap; }

.heatmap__grid {
  display: grid;
  grid-auto-flow: column;
  grid-template-rows: repeat(7, var(--heat-cell));
  grid-auto-columns: var(--heat-cell);
  gap: 1px;
  width: max-content;
}

.heatmap__cell { display: inline-block; width: var(--heat-cell); height: var(--heat-cell); }

.heatmap__cell.is-level-0 { background: var(--heat-0); }
.heatmap__cell.is-level-1 { background: var(--heat-1); }
.heatmap__cell.is-level-2 { background: var(--heat-2); }
.heatmap__cell.is-level-3 { background: var(--heat-3); }
.heatmap__cell.is-level-4 { background: var(--heat-4); }
.heatmap__cell.is-future { background: transparent; }

/* Filtered to one activity, the wall glows in that activity's ink. The
   ramp derives from currentColor (set by activity-ink is-N), mirroring the
   default alphas — no second palette to keep in sync, dark mode for free. */
.heatmap__filter { flex-wrap: wrap; }
.heatmap__filter .icon { width: 1.3rem; height: 1.3rem; vertical-align: -0.2rem; margin-right: var(--space-1); }
/* Cells are links, and links carry their own ink — inherit the wall's. */
.is-tinted .heatmap__cell { color: inherit; }
.is-tinted .heatmap__cell.is-level-1 { background: color-mix(in srgb, currentColor 18%, transparent); }
.is-tinted .heatmap__cell.is-level-2 { background: color-mix(in srgb, currentColor 40%, transparent); }
.is-tinted .heatmap__cell.is-level-3 { background: color-mix(in srgb, currentColor 68%, transparent); }
.is-tinted .heatmap__cell.is-level-4 { background: currentColor; }

/* The quiet beat: stopping a span deepens today's square (color eases in)
   with one soft pulse. The square is the reward — nothing else performs. */
.heatmap__cell.is-today { transition: background-color 0.6s ease; }
.heatmap__cell.is-fed { animation: heat-fed 0.6s ease; }
@keyframes heat-fed {
  50% { transform: scale(1.35); }
}
@media (prefers-reduced-motion: reduce) {
  .heatmap__cell.is-today { transition: none; }
  .heatmap__cell.is-fed { animation: none; }
}

.heatmap__legend {
  display: flex;
  align-items: center;
  gap: 3px;
  font-size: var(--text-small);
  margin-top: var(--space-3);
}

/* ---- Data rows ------------------------------------------------------- */

.data-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.data-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-5);
  padding: var(--space-4) 0;
  border-bottom: 1px solid var(--hairline);
}

/* The section <hr> already closes the list — no hairline on the last row */
.data-list > .data-row:last-child,
.data-list > .day-group:last-child > summary.data-row {
  border-bottom: 0;
}

.data-row__name {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-width: 0;
}

.data-row__swatch {
  width: 1rem;
  height: 1rem;
  border-radius: var(--radius);
  flex: none;
}

.data-row__value {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  font-feature-settings: "tnum";
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* ---- Activity tiles — the Streaks-style grid -------------------------- */

.tile-grid__heading { margin-top: var(--space-4); }

.tile-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(9.6rem, 1fr));
  gap: var(--space-6) var(--space-3);
}

.tile-grid form.button_to { display: contents; }

.tile {
  appearance: none;
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  color: var(--ink);
  cursor: pointer;
  text-decoration: none;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  /* long names must not widen the grid track */
  min-width: 0;
  max-width: 100%;
}

.tile__circ {
  width: 6rem;
  height: 6rem;
  border-radius: 50%;
  border: 1px solid var(--hairline);
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: var(--space-3);
}
.tile:hover .tile__circ { border-color: currentColor; }

.tile__circ .icon { width: 2.4rem; height: 2.4rem; }

/* Daily-budget progress: a ring in the activity's ink around the circle,
   set clear of the circle's border and the selected/running shadows */
.tile__circ { position: relative; }
.tile__ring {
  position: absolute;
  top: -7px;
  left: -7px;
  /* Explicit box, not inset-stretching: Safari sizes an absolutely
     positioned SVG by its intrinsic rules otherwise and misaligns it.
     The arc's 12-o'clock start is an SVG transform for the same reason.
     7px keeps the ring just clear of the selected-state shadow. */
  width: calc(100% + 14px);
  height: calc(100% + 14px);
}
.tile__ring circle { fill: none; stroke-width: 3.5; }
.tile__ring-track { stroke: var(--hairline); }
.tile__ring-arc { stroke: currentColor; stroke-linecap: round; }

/* A running budgeted tile's live ring IS the running signal — the shadow
   ring underneath would collide with it. */
.tile__circ.is-running:has(.tile__ring) {
  box-shadow: none;
  border-color: var(--hairline);
}

/* Armed but not started: a solid ring, quieter than the running one */
.tile__circ.is-selected {
  border-color: currentColor;
  box-shadow: 0 0 0 1px currentColor;
}

.picker__name {
  font-weight: 700;
  align-self: center;
}

/* Idle arming renders the name span empty (the headline carries the name);
   an empty span is still a flex item, so without this the row's gap pushes
   Start off the hero's left alignment edge. */
.picker__name:empty { display: none; }

/* Invisible, not display:none — the reserved box keeps the layout still
   when the Start button appears, so a tap never lands on shifted tiles. */
.picker { visibility: hidden; }
.picker.is-armed { visibility: visible; }

/* Manual entry: a quiet dashed circle that navigates, starts nothing */
.tile__circ--add {
  border-style: dashed;
  color: var(--subtle);
}
.tile:hover .tile__circ--add { color: var(--ink); }

/* The running badge wears its activity's color as a ring */
.tile__circ.is-running {
  border-color: transparent;
  box-shadow: 0 0 0 3px currentColor;
}

.tile__name {
  font-weight: 700;
  font-size: var(--text-small);
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tile__time { font-size: var(--text-small); }

/* ---- Suggestions — one-tap template chips ------------------------------ */

.suggestions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
}

.suggestions form.button_to { display: contents; }

.suggestion {
  appearance: none;
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  background: none;
  border: 1px solid var(--hairline);
  border-radius: var(--radius);
  color: var(--ink);
  font: inherit;
  font-size: var(--text-small);
  padding: var(--space-2) var(--space-3);
  cursor: pointer;
}
.suggestion:hover { border-color: var(--ink); }

.suggestion .icon { width: 1.6rem; height: 1.6rem; }

/* ---- Day groups — today's unique activities, expandable -------------- */

.day-group summary {
  cursor: pointer;
  list-style: none;
}
.day-group summary::-webkit-details-marker { display: none; }

/* a quiet unfold affordance */
.day-group summary .data-row__value::after {
  content: "+";
  color: var(--subtle);
  font-weight: 700;
}
.day-group[open] summary .data-row__value::after { content: "–"; }

.day-group__breakdown {
  list-style: none;
  margin: 0;
  padding: 0 0 var(--space-3) var(--space-7);
}

.day-group__span {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-5);
  padding: var(--space-2) 0;
  font-size: var(--text-small);
}

/* quiet backfill affordance: per-group "add" link */
.day-group__add {
  padding: var(--space-2) 0;
  font-size: var(--text-small);
}

.add-span {
  font-size: var(--text-small);
  margin: var(--space-3) 0 0;
}

/* linked cells navigate to their day */
a.heatmap__cell:hover { outline: 1px solid var(--ink); }

/* prev / today / next stepping on the day view */
.day-nav {
  display: flex;
  gap: var(--space-3);
  font-size: var(--text-small);
  /* pull back the links' own padding so the row still aligns left */
  margin: var(--space-2) 0 0 calc(-1 * var(--space-3));
}

/* Roomy hit areas without changing the layout's look. */
.day-nav a {
  padding: var(--space-3);
  display: inline-flex;
  align-items: center;
}

/* ---- Buttons --------------------------------------------------------- */

.btn {
  display: inline-block;
  appearance: none;
  border: 1px solid var(--ink);
  border-radius: var(--radius);
  background: var(--ink);
  color: var(--paper);
  font: inherit;
  font-size: var(--text-small);
  font-weight: 700;
  line-height: 1;
  padding: var(--space-3) var(--space-4);
  text-decoration: none;
  cursor: pointer;
}
.btn:hover { opacity: 0.85; }

.btn--secondary {
  background: transparent;
  color: var(--ink);
}

.btn--tertiary {
  background: transparent;
  color: var(--ink);
  border-color: var(--hairline);
}
.btn--tertiary:hover { border-color: var(--ink); opacity: 1; }

/* Semantic ghosts: color says what the action does to you. Green = you gain
   (join, accept, invite), red = you lose (leave, decline, remove, delete).
   Same anatomy as tertiary — the hue *is* the signal — with the border
   tinted at rest so the pair reads apart before hover. */
.btn--danger {
  background: transparent;
  color: var(--error);
  border-color: color-mix(in srgb, var(--error) 45%, transparent);
}
.btn--danger:hover { border-color: var(--error); opacity: 1; }

.btn--positive {
  background: transparent;
  color: var(--ok-text);
  border-color: color-mix(in srgb, var(--ok-text) 45%, transparent);
}
.btn--positive:hover { border-color: var(--ok-text); opacity: 1; }

/* Ko-fi support: an amber ghost in the semantic-button family. Warmth without
   shouting — a donation is an invitation, not a demand. */
.btn--kofi {
  background: transparent;
  color: var(--ink);
  border-color: color-mix(in srgb, var(--scribble-amber) 55%, transparent);
}
.btn--kofi:hover { border-color: var(--scribble-amber); opacity: 1; }
.btn--kofi .icon {
  color: var(--scribble-amber);
  vertical-align: -0.15em;
  margin-right: var(--space-2);
}

/* The breakdown's × is icon-only: give it a comfortable square target. */
.day-group__span .btn--danger {
  min-width: 4.4rem;
  min-height: 4.4rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  font-size: var(--text-body);
}

/* button_to wraps its button in a form */
form.button_to { display: inline; margin: 0; }

/* ---- Forms ----------------------------------------------------------- */

.field { margin: 0 0 var(--space-5); }

.field label {
  display: block;
  font-size: var(--text-small);
  font-weight: 700;
  color: var(--subtle);
  margin-bottom: var(--space-2);
}

/* Every control kind shares one box: hairline, radius, 44px touch target. */
.field input[type="text"],
.field input[type="email"],
.field input[type="password"],
.field input[type="number"],
.field input[type="date"],
.field input[type="time"],
.field select,
.field textarea,
.search-row input[type="search"] {
  width: 100%;
  min-height: 4.4rem;
  box-sizing: border-box;
  border: 1px solid var(--field-border);
  border-radius: var(--radius);
  background: transparent;
  color: var(--ink);
  font: inherit;
  padding: var(--space-2) var(--space-3);
}

/* Text-like inputs drop native chrome; selects keep their chevron and
   date/time inputs their pickers (color-scheme keeps those theme-true). */
.field input[type="text"],
.field input[type="email"],
.field input[type="password"],
.field input[type="number"],
.search-row input[type="search"] {
  appearance: none;
}

.field input:focus,
.field select:focus,
.field textarea:focus,
.search-row input[type="search"]:focus {
  border-color: var(--ink);
}

.field input[type="checkbox"] {
  width: 2rem;
  height: 2rem;
  accent-color: var(--ink);
  vertical-align: -0.4rem;
  margin-right: var(--space-2);
}

/* Inline label for checkbox rows (block labels sit above their control) */
.field--check label { display: inline; }

/* Live username feedback on settings — tints the hint line. */
.subtle.is-ok  { color: var(--ok-text); }
.subtle.is-bad { color: var(--error); }

/* Rails wraps invalid fields; mark the control, don't disturb layout. */
.field_with_errors { display: contents; }
.field_with_errors input,
.field_with_errors select,
.field_with_errors textarea {
  border-color: var(--error);
}

.form-errors {
  list-style: none;
  margin: 0 0 var(--space-5);
  padding: var(--space-4);
  border: 1px solid var(--error);
  border-radius: var(--radius);
  color: var(--error);
  font-size: var(--text-small);
}

/* Duration picker — preset chips over a backing minutes input. */
.duration-picker__chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-bottom: var(--space-3);
}

.chip {
  appearance: none;
  min-height: 4rem;
  padding: var(--space-2) var(--space-4);
  border: 1px solid var(--hairline);
  border-radius: var(--radius);
  background: transparent;
  color: var(--ink);
  font: inherit;
  font-size: var(--text-small);
  cursor: pointer;
}
.chip:hover { border-color: var(--ink); }
.chip[aria-pressed="true"] {
  background: var(--ink);
  color: var(--paper);
  border-color: var(--ink);
}

/* With JS the raw input only shows for Custom; without it, it stays put. */
.duration-picker--ready .duration-picker__input[hidden] { display: none; }

.tint-picker { display: flex; gap: var(--space-3); }

.tint-picker__option { cursor: pointer; }

.tint-picker__option input { position: absolute; opacity: 0; }

.tint-picker__option .data-row__swatch {
  display: block;
  width: 2.4rem;
  height: 2.4rem;
  border: 1px solid var(--hairline);
}

.tint-picker__option input:checked + .data-row__swatch {
  outline: 2px solid var(--ink);
  outline-offset: 2px;
}

/* ---- Flash + auth ---------------------------------------------------- */

/* Notifications: a quiet card on the surface tint, marked by an accent rail
   on the leading edge (ink for a notice, error red for an alert, amber for a
   gentle nag) — legible without shouting. */
.flash {
  font-size: var(--text-small);
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--hairline);
  border-inline-start: 3px solid var(--ink);
  border-radius: var(--radius);
  padding: var(--space-3) var(--space-4);
  margin: 0 0 var(--space-5);
}
.flash--alert {
  color: var(--error);
  border-inline-start-color: var(--error);
}
/* The email-confirmation nag: an amber rail, still quiet. The resend button is
   a plain inline link, not a heavy .btn — the banner shouldn't shout. */
.flash--nag {
  border-inline-start-color: var(--scribble-amber);
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
}
.flash--nag .flash__resend { display: inline; }
.flash--nag .flash__resend button,
.timezone__use {
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  color: var(--ink);
  text-decoration: underline;
  cursor: pointer;
}
/* The detected-zone suggestion sits just under the select, quiet. */
.timezone__prompt { margin-top: var(--space-2); }

.auth {
  max-width: 36rem;
  margin: var(--space-9) auto 0;
}
.auth h1 { margin-bottom: var(--space-6); }
.auth .subtle { font-size: var(--text-small); margin-top: var(--space-6); }

/* Feedback: a floating button on every signed-in page opens an in-place
   dialog, so a bug can be reported without leaving the view. */
.feedback-fab {
  position: fixed;
  right: var(--space-4);
  bottom: var(--space-4);
  width: 4.4rem;
  height: 4.4rem;
  border-radius: 50%;
  border: 1px solid var(--hairline);
  background: var(--ink);
  color: var(--paper);
  display: grid;
  place-items: center;
  cursor: pointer;
  z-index: 50;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.18);
}
.feedback-fab .icon { width: 2rem; height: 2rem; }
.feedback-dialog {
  border: 1px solid var(--hairline);
  border-radius: var(--radius);
  background: var(--paper);
  color: var(--ink);
  padding: var(--space-6);
  max-width: 34rem;
  width: calc(100% - var(--space-5));
}
.feedback-dialog::backdrop { background: rgba(0, 0, 0, 0.4); }
.feedback-dialog__title { margin: 0 0 var(--space-2); }
.feedback-dialog .subtle { margin: 0 0 var(--space-5); font-size: var(--text-small); }
.feedback-dialog__actions {
  display: flex;
  justify-content: flex-end;
  gap: var(--space-3);
  margin-top: var(--space-5);
}

/* Stats — a ranked activity-share bar chart. Colour follows the activity's
   tint (identity, never rank); every row is named and numbered so the chart
   never leans on colour alone. Text stays in ink; only the bar fill is tinted. */
.stats__periods { display: flex; gap: var(--space-4); font-size: var(--text-small); }
.stats__periods a { color: var(--subtle); text-decoration: none; }
.stats__periods a.is-current { color: var(--ink); text-decoration: underline; text-underline-offset: 3px; }
.stats__groups { margin-top: var(--space-2); }
.stats__total { font-size: var(--text-large); margin: 0; }
.stats__total .tnum { font-weight: 700; }
.stats__bars { list-style: none; padding: 0; margin: var(--space-5) 0 0; }
.stats__row { margin-bottom: var(--space-4); }
.stats__label {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--space-3);
  margin-bottom: var(--space-2);
}
.stats__name { display: inline-flex; align-items: center; gap: var(--space-2); font-size: var(--text-small); }
.stats__name .icon { width: 1.6rem; height: 1.6rem; }
.stats__value { font-size: var(--text-small); }
/* Recessive track, tinted fill with a rounded data-end anchored to the start. */
.stats__track { height: 0.8rem; background: var(--surface); border-radius: 0.4rem; overflow: hidden; }
.stats__fill { height: 100%; border-radius: 0 0.4rem 0.4rem 0; min-width: 2px; }
.stats__fill--category { background: rgba(var(--ink-rgb), 0.55); }
.stats__bars--categories { margin-bottom: var(--space-6); }
.stats__empty { margin-top: var(--space-6); }

/* Integrations (dev, flag-gated): one card per provider. */
.integrations-page { max-width: 40rem; }
.integrations-page__head { margin-bottom: var(--space-6); }
.integrations-page__head h1 { margin: 0 0 var(--space-2); }

.integration-card { border: 1px solid var(--hairline); border-radius: var(--radius); padding: var(--space-6); }
.integration-card + .integration-card { margin-top: var(--space-6); }
.integration-card__brand { display: flex; align-items: flex-start; gap: var(--space-4); }
.integration-card__brand h2 { margin: 0 0 var(--space-2); font-size: var(--text-large); }
.integration-card__brand > div { flex: 1; }
.integration-card__brand .subtle { font-size: var(--text-small); }
.integration-card__logo { flex: none; display: inline-flex; width: 2.75rem; height: 2.75rem; }
/* Controls hang from the text's indent line, clearing the logo column. */
.integration-card__actions, .integration-card__link, .integration-card__change-key { margin-left: calc(2.75rem + var(--space-4)); }
.integration-card__change-key .integration-card__link { margin-left: 0; }
.integration-card__logo svg { width: 100%; height: 100%; }
.integration-card__logo--wakatime { color: var(--ink); }
.integration-card__synced { font-size: var(--text-tiny); display: flex; align-items: center; gap: var(--space-2); margin: var(--space-3) 0 0 calc(2.75rem + var(--space-4)); }
.integration-card__actions { display: flex; gap: var(--space-3); margin-top: var(--space-5); }
.integration-card__link { margin-top: var(--space-5); }
.integration-card__hint { font-size: var(--text-tiny); margin-top: var(--space-2); }
.integration-card__change-key { margin-top: var(--space-3); font-size: var(--text-small); }
.integration-card__change-key summary { cursor: pointer; }
.integration-card__change-key .integration-card__link { margin-top: var(--space-3); }

.integrations-link { display: flex; align-items: center; gap: var(--space-4); border: 1px solid var(--hairline); border-radius: var(--radius); padding: var(--space-4) var(--space-5); text-decoration: none; color: inherit; }
.integrations-link__logos { display: inline-flex; gap: var(--space-2); }
.integrations-link__logos .integration-card__logo { width: 1.5rem; height: 1.5rem; }
.integrations-link__text { flex: 1; display: flex; flex-direction: column; }
.integrations-link__chevron { font-size: var(--text-heading); color: var(--subtle); }

/* Settings: grouped hairline cards, instant apply. Airy on purpose. */
.settings__head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-4); }
.settings-saved { font-size: var(--text-small); color: var(--subtle); opacity: 0; transition: opacity 0.25s ease; }
.settings-saved.is-showing { opacity: 1; }
.settings-saved.is-error { color: var(--ink); }
@media (prefers-reduced-motion: reduce) { .settings-saved { transition: none; } }

.settings-card { border: 1px solid var(--hairline); border-radius: var(--radius); padding: var(--space-5); }
.settings-card + .settings-card { margin-top: var(--space-6); }
.settings-card__title { margin: 0 0 var(--space-5); font-size: var(--text-heading); }
.settings-email { display: flex; flex-direction: column; gap: var(--space-1); margin-bottom: var(--space-5); }
.settings-email__label { font-weight: 600; font-size: var(--text-small); }
.settings-card .field + .field, .settings-card .field + .field--check { margin-top: var(--space-5); }

.settings select {
  appearance: none; -webkit-appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1l5 5 5-5' fill='none' stroke='%23888888' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right var(--space-3) center;
  padding-right: var(--space-7);
}

.segmented { display: flex; border: 1px solid var(--field-border); border-radius: var(--radius); overflow: hidden; }
.segmented__option { flex: 1; }
.segmented__option input { position: absolute; opacity: 0; pointer-events: none; }
.segmented__option span {
  display: block; text-align: center; padding: var(--space-3) var(--space-2);
  font-size: var(--text-small); cursor: pointer;
}
.segmented__option + .segmented__option span { border-left: 1px solid var(--field-border); }
.segmented__option:has(input:checked) span { background: var(--ink); color: var(--paper); }
.segmented__option:has(input:focus-visible) span { outline: 2px solid var(--ink); outline-offset: -2px; }

.settings-integrations { margin-top: var(--space-8); border-top: 1px solid var(--hairline); padding-top: var(--space-6); }

/* Section label with a plain underlined link on the right — the same link
   vocabulary as the nav items, so "manage" reads as clickable. */
.section-head { display: flex; align-items: center; gap: var(--space-3); }
/* Label hugs the left; the actions (switch, gear Manage) cluster right. */
.section-head > .label { margin-inline-end: auto; }

/* ---- Section-head controls: gear Manage, grouping switch, tooltip ---- */

.section-head__manage { display: inline-flex; color: var(--subtle); }
.section-head__manage:hover { color: var(--ink); }
.section-head__manage .icon { width: 2rem; height: 2rem; }

.switch {
  display: inline-flex; align-items: center; gap: var(--space-2);
  background: none; border: 0; padding: 0; cursor: pointer;
  font: inherit; font-size: var(--text-small); color: var(--subtle);
}
/* The class display beats the UA [hidden] rule; restore it so the server
   and client can hide the switch when grouping isn't meaningful. */
.switch[hidden] { display: none; }
.switch__track {
  position: relative; width: 2.4rem; height: 1.4rem;
  border-radius: 1rem; background: var(--surface);
  border: 1px solid var(--hairline); transition: background 0.15s ease;
}
.switch__thumb {
  position: absolute; top: 1px; inset-inline-start: 1px;
  width: 1rem; height: 1rem; border-radius: 50%;
  background: var(--ink); transition: transform 0.15s ease;
}
.switch[aria-checked="true"] .switch__track { background: var(--ink); border-color: var(--ink); }
.switch[aria-checked="true"] .switch__thumb { transform: translateX(1rem); background: var(--paper); }

/* Hand-rolled tooltip in span's idiom (the "Pico-style" pattern, no Pico). */
[data-tooltip] { position: relative; }
[data-tooltip]::after {
  content: attr(data-tooltip);
  position: absolute; top: calc(100% + 4px); inset-inline-end: 0;
  background: var(--ink); color: var(--paper);
  font-size: var(--text-tiny); white-space: nowrap;
  padding: var(--space-1) var(--space-2); border-radius: var(--radius);
  opacity: 0; pointer-events: none; transition: opacity 0.12s ease; z-index: 20;
}
[data-tooltip]:hover::after, [data-tooltip]:focus-visible::after { opacity: 1; }

@media (prefers-reduced-motion: reduce) {
  .switch__track, .switch__thumb, [data-tooltip]::after { transition: none; }
}
/* The add-activity ghost tile: a big quiet "+" fills the dashed circle. */
.tile__circ--add { font-size: 3.2rem; font-weight: 300; }

/* Sync indicator: a Pico-style spinner while running, a ✓/✗ once settled. */
.spinner {
  display: inline-block;
  width: 1em;
  height: 1em;
  border: 2px solid var(--hairline);
  border-top-color: var(--ink);
  border-radius: 50%;
  animation: spin 0.6s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .spinner { animation-duration: 1.8s; } }
.sync-mark { font-weight: 700; }
.sync-mark--ok { color: var(--activity-0); }   /* the app's green */
.sync-mark--failed { color: var(--error); }
