/* Caveat (SIL Open Font License 1.1), self-hosted: a strict CSP blocks
   fonts.gstatic.com, and local files keep the visitor's address out of
   Google's logs. Latin + Cyrillic only. */
@font-face {
  font-family: 'Caveat';
  font-style: normal;
  font-weight: 400;
  font-display: block;
  src: url('/assets/vendor/fonts/caveat-400-cyrillic.woff2') format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: 'Caveat';
  font-style: normal;
  font-weight: 400;
  font-display: block;
  src: url('/assets/vendor/fonts/caveat-400-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Caveat';
  font-style: normal;
  font-weight: 500;
  font-display: block;
  src: url('/assets/vendor/fonts/caveat-500-cyrillic.woff2') format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: 'Caveat';
  font-style: normal;
  font-weight: 500;
  font-display: block;
  src: url('/assets/vendor/fonts/caveat-500-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Caveat';
  font-style: normal;
  font-weight: 600;
  font-display: block;
  src: url('/assets/vendor/fonts/caveat-600-cyrillic.woff2') format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: 'Caveat';
  font-style: normal;
  font-weight: 600;
  font-display: block;
  src: url('/assets/vendor/fonts/caveat-600-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Caveat';
  font-style: normal;
  font-weight: 700;
  font-display: block;
  src: url('/assets/vendor/fonts/caveat-700-cyrillic.woff2') format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: 'Caveat';
  font-style: normal;
  font-weight: 700;
  font-display: block;
  src: url('/assets/vendor/fonts/caveat-700-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* M PLUS Rounded 1c (SIL OFL 1.1), self-hosted. Used only for text the
   user types: Caveat's script glyphs overhang their advance width, so the
   caret cuts through them inside inputs. */
@font-face {
  font-family: 'M PLUS Rounded 1c';
  font-style: normal;
  font-weight: 400;
  font-display: block;
  src: url('/assets/vendor/fonts/mplus-rounded-1c-400-cyrillic.woff2') format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: 'M PLUS Rounded 1c';
  font-style: normal;
  font-weight: 400;
  font-display: block;
  src: url('/assets/vendor/fonts/mplus-rounded-1c-400-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'M PLUS Rounded 1c';
  font-style: normal;
  font-weight: 500;
  font-display: block;
  src: url('/assets/vendor/fonts/mplus-rounded-1c-500-cyrillic.woff2') format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: 'M PLUS Rounded 1c';
  font-style: normal;
  font-weight: 500;
  font-display: block;
  src: url('/assets/vendor/fonts/mplus-rounded-1c-500-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

:root {
  --paper:      #f2f0e8;
  --sheet:      #ffffff;
  --ink:        #1c1b19;
  --ink-soft:   #6b675f;
  --ink-faint:  #a9a59b;
  --rule:       #e8e5dc;
  --rule-soft:  #f1efe8;
  --green:      #2f7d4f;
  --green-deep: #235f3c;
  --green-soft: #e3f0e7;
  --clay:       #a8503c;
  --miss:       #b8402e;
  --shadow:     0 1px 0 rgba(28, 27, 25, .04), 0 10px 28px -18px rgba(28, 27, 25, .35);

  --serif: "Iowan Old Style", "Palatino Linotype", Palatino, Georgia, "Times New Roman", serif;
  --sans:  ui-sans-serif, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --mono:  ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
  --hand:  "Caveat", "Segoe Script", "Bradley Hand", cursive;
  --input: "M PLUS Rounded 1c", ui-rounded, var(--sans);
}

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  min-height: 100vh;
  font-family: var(--hand);
  font-size: 19px;
  line-height: 1.5;
  color: var(--ink);
  background-color: var(--paper);
  /* Paper grain, drawn with gradients so the page pulls in no images. */
  background-image:
    radial-gradient(circle at 15% 12%, rgba(28,27,25,.026) 0 1px, transparent 1px),
    radial-gradient(circle at 62% 47%, rgba(28,27,25,.022) 0 1px, transparent 1px),
    radial-gradient(circle at 83% 78%, rgba(28,27,25,.026) 0 1px, transparent 1px);
  background-size: 37px 41px, 53px 47px, 61px 59px;
}

/* ------------------------------------------------------------------ sheet */

.sheet {
  position: relative;
  background: var(--sheet);
  border: 1px solid var(--rule);
  border-radius: 2px;
  box-shadow: var(--shadow);
  padding: 28px 30px;
}

/* Faint ruled lines, the way a page of paper actually looks. */
.sheet--ruled::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 2px;
  pointer-events: none;
  background-image: repeating-linear-gradient(
    to bottom, transparent 0 27px, var(--rule-soft) 27px 28px
  );
  opacity: .75;
}

.sheet > * { position: relative; }

.wrap { width: min(760px, calc(100vw - 32px)); margin: 0 auto; padding: 34px 0 24px; }
.wrap--narrow { width: min(430px, calc(100vw - 32px)); padding-top: 8vh; }

/* Auth window: centred on every device, hand-drawn edge like the inputs. */
.auth-page {
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 64px 16px 32px;
}
/* .sheet gets tighter padding under 860px for the tracker screens; the auth
   window is a fixed-width card and must look the same on phone and desktop,
   so it is scoped tighter than that media rule. */
.sheet.auth-card { width: min(400px, 100%); padding: 12px 30px 22px; }
/* The auth window is set in M PLUS Rounded 1c — its soft, round terminals suit
   the hand-drawn paper look better than the system UI face. */
.auth-page,
.auth-card .tab,
.auth-card .field label,
.auth-card .btn { font-family: var(--hand); }
.auth-card .field label { font-weight: 500; }
/* Caveat's script glyphs overhang their advance width (~0.2em right, ~0.1em
   left), so the caret would cut through whatever is typed. The labels stay in
   Caveat; only the typed value uses a face with honest metrics. */
.auth-card .field input {
  font-family: var(--input);
  /* 15px matches the x-height of the 17px Caveat labels (6.87 vs 6.8), so the
     typed text reads at the same visual size as "Логин" / "Пароль". */
  font-size: 15px;
  letter-spacing: .01em;
  font-weight: 400;
}
.auth-card .tab { font-weight: 400; }
.auth-card .tab[aria-selected="true"] { font-weight: 500; }
.auth-card .tab { font-size: 20px; }
.auth-card .field label { font-size: 17px; }
.auth-card .field input { padding: 8px 13px; }
.auth-card .btn { font-size: 18px; padding: 9px 20px; }
.auth-card .btn { font-weight: 700; }

/* Hand-drawn contours. Each control gets its own radius pair and a fraction of
   a degree of tilt, so no two edges repeat and nothing looks machine-made. */
.auth-card .field:first-of-type input {
  border-radius: 195px 24px 255px 16px / 20px 245px 14px 195px;
  --tilt: -0.4deg;
  transform: rotate(var(--tilt));
}
.auth-card .field:nth-of-type(2) input {
  border-radius: 240px 16px 200px 28px / 15px 190px 22px 250px;
  --tilt: 0.35deg;
  transform: rotate(var(--tilt));
}
.auth-card .btn--primary {
  border-radius: 250px 18px 205px 22px / 24px 200px 16px 245px;
  --tilt: -0.25deg;
}
/* Every panel is drawn by the same hand as the auth card: a wobbly contour and
   a fraction of a degree of tilt, varied per panel so none of them repeat. */
.sheet--hand { --tilt: 0deg; transform: rotate(var(--tilt)); }
/* The top panel holds a single row, so it gets tighter vertical padding
   than the taller panels below it. */
.wrap .sheet--hand:nth-of-type(1) {
  border-radius: 250px 16px 220px 20px / 18px 215px 16px 245px;
  --tilt: -0.22deg;
  padding-top: 16px;
  padding-bottom: 16px;
  /* Matches the top gap, so the button sits the same distance from the top and
     right edges of the panel. */
  padding-right: 16px;
}

/* The day button is secondary to the count, so it runs a size smaller. */
.today__actions .btn { font-size: 16px; padding: 7px 16px; }
.wrap .sheet--hand:nth-of-type(2) { border-radius: 215px 22px 255px 15px / 15px 250px 22px 210px; --tilt: 0.2deg; }
.wrap .sheet--hand:nth-of-type(4) {
  padding-top: 16px;
  padding-bottom: 16px;
  padding-left: 20px;
}
/* Same footprint as the day button in the panel above. */
.relapse .btn,
.relapse__row .btn { font-size: 16px; padding: 7px 16px; }
.wrap .sheet--hand:nth-of-type(3) {
  border-radius: 245px 18px 210px 24px / 22px 205px 18px 250px;
  --tilt: -0.16deg;
  padding-bottom: 16px;
}
.stats.stats--hand {
  border: 1px solid var(--ink);
  border-radius: 230px 18px 240px 16px / 16px 235px 20px 225px;
  box-shadow: 0 12px 30px -20px rgba(28, 27, 25, .4);
  transform: rotate(0.18deg);
}

/* Pepe perched on the card's top edge: head and shoulders clear the rule, the
   rest hides behind it. 400x225 source, so height = width / 1.778, and the
   negative top lifts ~55% of him above the edge. `.sheet > *` forces children
   to position:relative, hence the tighter selector here. */
/* The anchor carries the position; the image just fills it. PaperCSS paints a
   dotted underline behind every <a>, which has to be cleared here. */
/* Positioning lives on whichever element is outermost, so the frog stays put
   whether or not the link wrapper is present. A page cached before the wrapper
   existed would otherwise pick up `width:100%` and blow up to panel size. */
.sheet .pepe-link,
.sheet .pepe {
  position: absolute;
  display: block;
  top: -40px;
  right: var(--pepe-right, 20px);
  width: 130px;
  height: auto;
  z-index: 2;
}
.sheet .pepe-link {
  line-height: 0;
  text-decoration: none;
  background: none;
  border: 0;
  outline: none;
  box-shadow: none;
  -webkit-tap-highlight-color: transparent;
}
.sheet .pepe-link:hover,
.sheet .pepe-link:active,
.sheet .pepe-link:focus,
.sheet .pepe-link:focus-visible {
  outline: none;
  border: 0;
  box-shadow: none;
  background: none;
}
/* Wrapped: the link holds the position, the image simply fills it. */
.sheet .pepe-link .pepe {
  position: static;
  top: auto;
  right: auto;
  width: 100%;
  max-width: 100%;
}

.sheet .pepe {
  /* PaperCSS puts a 2px border + rounded corners on every <img>; that framed
     the frog in a black box. */
  border: 0;
  border-radius: 0;
  background: none;
  pointer-events: none;
  user-select: none;
  -webkit-user-drag: none;
  /* No filter here on purpose: a filter forces the browser to rasterise the
     element, and Safari does that at 1x for this 46-frame animated WebP, so the
     frog came out jagged on Retina. Chrome rasterises at 2x and looked fine. */
  image-rendering: auto;
}
@media (max-width: 420px) {
  .sheet .pepe-link,
  .sheet .pepe { width: 108px; top: -33px; right: 14px; }
  .sheet .pepe-link .pepe { width: 100%; top: auto; right: auto; }
}

.sheet--hand {
  border: 1px solid var(--ink);
  border-radius: 255px 15px 225px 15px / 15px 225px 15px 255px;
  box-shadow: 0 12px 30px -20px rgba(28, 27, 25, .4);
}

/* --------------------------------------------------------------- headings */

h1, h2, h3 { font-family: var(--hand); font-weight: 500; letter-spacing: .01em; margin: 0; }

.brand {
  /* The wordmark is a logo, not content - dragging across it shouldn't select. */
  user-select: none;
  -webkit-user-select: none;
  font-family: var(--hand);
  font-size: 34px;
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: lowercase;
  margin: 0;
}
.brand__dot { color: var(--green); }

.tagline { color: var(--ink-soft); font-size: 13px; margin: 4px 0 0; letter-spacing: .04em; }

.section-title {
  font-family: var(--hand);
  font-size: 16px;
  letter-spacing: .02em;
  color: var(--ink-faint);
  margin: 0 0 12px;
}

hr.rule { border: 0; border-image: none; border-top: 1px solid var(--rule); margin: 22px 0; }

/* ----------------------------------------------------------------- topbar */

.topbar {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  margin-bottom: 20px;
}
.topbar__user { font-size: 16px; color: var(--ink-soft); display: flex; align-items: center; gap: 12px; }
.topbar__name { font-family: var(--hand); color: var(--ink); }

/* ------------------------------------------------------------------ forms */

.field { position: relative; margin-bottom: 16px; }

.field input[aria-invalid="true"] { border-color: var(--clay); }
.field label {
  display: block;
  font-size: 14px;
  letter-spacing: .02em;
  color: var(--ink-faint);
  margin-bottom: 5px;
}
.field input {
  width: 100%;
  font-family: var(--hand);
  font-size: 19px;
  padding: 7px 12px;
  color: var(--ink);
  background: transparent;
  border: 1px solid var(--ink);
  /* PaperCSS's hand-drawn border shape. */
  border-radius: 255px 15px 225px 15px / 15px 225px 15px 255px;
  outline: none;
}
.field input { transition: none; }
.field input:focus { border-color: var(--green); box-shadow: 0 0 0 3px var(--green-soft); }
.field input:disabled { opacity: .5; }
.hint { font-size: 12px; color: var(--ink-faint); margin: 5px 0 0; }

/* The challenge only appears once the credentials pass, so it needs room but
   must not shift the card while hidden. */
/* Left-aligned with the inputs above it, not centred in the card. */
/* Top margin must exceed the field's own 16px, otherwise the two collapse and
   the block does not move. The 0.6px asymmetry compensates for the tilted
   input and button, so the two visible gaps come out equal. */
.captcha { margin: 20px 0 20.6px; min-height: 78px; display: flex; justify-content: flex-start; }

/* The widget itself is a cross-origin iframe, so its grey border cannot be
   restyled - it is clipped away instead, and this wrapper draws the same
   hand-drawn contour the inputs use. */
.captcha__frame {
  position: relative;
  width: 302px;
  height: 76px;
  overflow: hidden;
  background: var(--sheet);
  border: 1px solid var(--ink);
  border-radius: 205px 18px 235px 16px / 16px 225px 18px 210px;
  transform: rotate(-0.35deg);
}
/* Pulled in by a pixel on every side so the iframe's own frame falls outside. */
.captcha__frame > #captcha-widget {
  position: absolute;
  top: -1px;
  left: -1px;
}

/* Google's checkbox and label live inside the iframe and cannot be restyled, so
   they are covered and redrawn. Clicks pass through to the real control. */
/* Covers the whole widget, so nothing of Google's own chrome shows through -
   neither the spinner while it verifies nor the stock logo. Everything visible
   is drawn below. */
.captcha__cover {
  position: absolute;
  inset: 0;
  /* Pure white, not Google's #f9f9f9: the sticker carries an opaque white
     square, and on an off-white ground it showed as a visible box. */
  background: #fff;
  pointer-events: none;
}

.captcha__box {
  position: absolute;
  left: 15px;
  top: 22px;
  width: 31px;
  height: 31px;
  background: #fff;
  border: 1px solid var(--ink);
  border-radius: 12px 3px 10px 4px / 4px 10px 3px 12px;
  pointer-events: none;
  /* The tick deliberately runs past the square. */
  overflow: visible;
}

/* Drawn like a pen stroke: the line paints itself on, and rewinds the same way
   when the challenge is reset. */
.captcha__tick {
  position: absolute;
  left: 2px;
  top: 2px;
  width: 38px;
  height: 30px;
  overflow: visible;
  fill: none;
  stroke: var(--green);
  stroke-width: 2.4;
  stroke-linecap: round;
  stroke-linejoin: round;
  pointer-events: none;
}
/* The dash length is animated rather than the offset. Opacity is toggled too:
   a zero-length dash with a round cap still paints a dot, which showed up as a
   green speck in the empty box. */
.captcha__tick path {
  stroke-dasharray: 0 2;
  opacity: 0;
  transition: stroke-dasharray .5s ease-out, opacity .08s linear .42s;
}
.captcha__frame.is-solved .captcha__tick path {
  stroke-dasharray: 1 2;
  opacity: 1;
  transition: stroke-dasharray .5s ease-out, opacity .08s linear;
}

.captcha__label {
  position: absolute;
  left: 54px;
  top: 20px;
  width: 150px;
  height: 38px;
  display: flex;
  align-items: center;
  background: #fff;
  font-family: var(--hand);
  font-size: 20px;
  font-weight: 500;
  color: var(--ink-soft);
  letter-spacing: .01em;
  pointer-events: none;
}

/* Stowed rather than display:none - reCAPTCHA needs a real box to render into,
   so it is parked off-screen and pre-rendered before anyone needs it. */
.captcha.is-stowed {
  position: absolute;
  left: -10000px;
  top: 0;
  margin: 0;
}

.tabs { display: flex; gap: 10px; margin: 16px 0 14.8px; }
.tab {
  position: relative;
  font-size: 17px;
  letter-spacing: .02em;
  color: var(--ink-faint);
  background: none;
  border: 0;
  padding: 9px 15px;
  cursor: pointer;
  font-family: var(--hand);
  outline: none;
  -webkit-tap-highlight-color: transparent;
}
.tab[aria-selected="true"] { color: var(--ink); }
.tab__label { position: relative; }

/* Active tab is ringed by a hand-drawn ellipse that draws itself on select. */
.tab__circle {
  position: absolute;
  /* 12px of slack on every side: the UA clips an inline <svg> to its viewport,
     and the stroke plus the overlap drift both ride past the tab's box. */
  left: -12px;
  top: -12px;
  width: calc(100% + 24px);
  height: calc(100% + 24px);
  overflow: visible;
  pointer-events: none;
  fill: none;
  stroke: var(--ink);
  stroke-width: 1.6;
  stroke-linecap: round;
  opacity: 0;
}
.tab__circle path {
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
}
.tab[aria-selected="true"] .tab__circle { opacity: 1; }
.tab[aria-selected="true"] .tab__circle path {
  animation: tab-circle .55s ease-out forwards;
}
@keyframes tab-circle { to { stroke-dashoffset: 0; } }

/* --------------------------------------------------------------- buttons */

.btn {
  font-family: var(--hand);
  font-size: 18px;
  letter-spacing: .04em;
  padding: 9px 20px;
  color: var(--ink);
  background: var(--sheet);
  border: 1px solid var(--ink);
  border-radius: 255px 15px 225px 15px / 15px 225px 15px 255px;
  cursor: pointer;
}
.btn:disabled { opacity: .45; cursor: not-allowed; }

/* PaperCSS rewrites every <button> to `margin: 0 auto 1rem` below 520px, which
   silently changed the layout on phones (an extra 20px under the tab row, and
   auto side margins). Our buttons own their spacing at every width. */
.btn,
.tab,
.btn--link {
  margin: 0;
  text-align: center;
}
.btn--block { display: block; width: 100%; }
.tab { display: inline-block; }

/* PaperCSS animates every bare <button> on hover (translate3d + shadow) and
   swaps the border on focus. Both are cancelled here so buttons and tabs stay
   perfectly still under the cursor. */
.btn,
.btn:hover,
.btn:active,
.btn:focus,
.btn--link,
.btn--link:hover,
.btn--link:active,
.btn--link:focus,
.tab,
.tab:hover,
.tab:active,
.tab:focus,
.tab:focus-visible {
  /* rotate() carries each control's hand-drawn tilt; it is identical in every
     state, so hovering still moves nothing. */
  transform: rotate(var(--tilt, 0deg));
  transition: none;
  outline: none;
}
.btn, .btn:hover, .btn:active, .btn:focus,
.btn--link, .btn--link:hover, .btn--link:active, .btn--link:focus { box-shadow: none; }
.btn:focus { border: 1px solid var(--ink); }
.btn--primary:focus { border-color: var(--green-deep); }
.tab, .tab:hover, .tab:active, .tab:focus, .tab:focus-visible { box-shadow: none; border: 0; }
.btn--block { display: block; width: 100%; }
.btn--primary { background: var(--green); border-color: var(--green-deep); color: #fff; }
.btn--ghost { border-color: var(--rule); color: var(--ink-soft); }
.btn--ghost:hover:not(:disabled) { border-color: var(--ink-soft); }
.btn--link {
  border: 0; background: none; padding: 0; font-size: 16px;
  font-family: var(--hand);
  color: var(--ink-soft); text-decoration: underline; text-underline-offset: 1.5px; cursor: pointer;
}
.btn--danger { border-color: var(--clay); color: var(--clay); }
#relapse-yes { border-color: var(--miss); color: var(--miss); }

/* While the confirmation is open the trigger is inactive, but it must not take
   on the spent look of the marked-day button - it just steps back. */
#relapse:disabled {
  opacity: .55;
  cursor: default;
  border-color: var(--clay);
  color: var(--clay);
  background: var(--sheet);
}
.btn--danger:hover:not(:disabled) { background: #fbf3f1; }

/* ------------------------------------------------------------------ today */

.today { display: flex; align-items: flex-end; justify-content: space-between; gap: 24px; flex-wrap: wrap; }
.today__count { font-family: var(--hand); font-weight: 600; font-size: 38px; line-height: 1; }
.today__count small { font-size: 18px; color: var(--ink-faint); }
.today__date { font-family: var(--hand); font-size: 16px; color: var(--ink-soft); }
.today__actions { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }

.progress { height: 3px; background: var(--rule-soft); margin: 12px 0 4px; border: 0; border-radius: 2px; box-shadow: none; overflow: hidden; }
.progress__bar { height: 100%; width: calc(var(--progress, 0) * 1%); background: var(--green); transition: width .35s ease; }
.progress__label { font-size: 14px; color: var(--ink-faint); letter-spacing: .02em; }

/* ------------------------------------------------------------------ stats */

/* Fixed column counts per breakpoint (not auto-fit) so we know exactly which
   cells begin a row and therefore need no divider on their left. */
.stats {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: 0;
  background: var(--sheet);
  border: 1px solid var(--ink);
  border-radius: 2px;
  overflow: hidden;
}
.stat { position: relative; background: var(--sheet); padding: 6px 16px; }

/* Dividers are drawn as leaning hairlines rather than grid gaps, so they read
   as pen strokes like the rest of the page. */
.stat::before {
  content: "";
  position: absolute;
  left: -6px;
  /* Overshoots the cell so the panel clips it flush into the top and bottom
     borders instead of stopping short. */
  top: -4px;
  width: 12px;
  height: calc(100% + 8px);
  /* Each divider is an actual pen stroke: a gentle bow plus irregular tremor,
     drawn as SVG. A CSS border-radius arc is geometrically perfect and still
     reads as ruled, which is what gave the game away. */
  background-repeat: no-repeat;
  background-position: center;
  background-size: 100% 100%;
}
.stat:nth-child(1)::before { content: none; }
.stat:nth-child(2)::before { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 100' preserveAspectRatio='none'%3E%3Cpath d='M6.00 0.00C6.10 2.08 6.47 8.33 6.58 12.50C6.69 16.67 6.55 20.83 6.65 25.00C6.76 29.17 7.15 33.33 7.23 37.50C7.31 41.67 7.15 45.83 7.13 50.00C7.11 54.17 7.20 58.33 7.12 62.50C7.04 66.67 6.77 70.83 6.65 75.00C6.53 79.17 6.53 83.33 6.42 87.50C6.31 91.67 6.07 97.92 6.00 100.00' fill='none' stroke='%231c1b19' stroke-width='1' stroke-linecap='round' vector-effect='non-scaling-stroke'/%3E%3C/svg%3E"); }
.stat:nth-child(3)::before { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 100' preserveAspectRatio='none'%3E%3Cpath d='M6.00 0.00C6.08 2.08 6.39 8.33 6.51 12.50C6.63 16.67 6.63 20.83 6.71 25.00C6.78 29.17 6.87 33.33 6.95 37.50C7.04 41.67 7.23 45.83 7.22 50.00C7.21 54.17 6.93 58.33 6.88 62.50C6.83 66.67 6.99 70.83 6.92 75.00C6.84 79.17 6.57 83.33 6.41 87.50C6.26 91.67 6.07 97.92 6.00 100.00' fill='none' stroke='%231c1b19' stroke-width='1' stroke-linecap='round' vector-effect='non-scaling-stroke'/%3E%3C/svg%3E"); }
.stat:nth-child(4)::before { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 100' preserveAspectRatio='none'%3E%3Cpath d='M6.00 0.00C5.97 2.08 5.92 8.33 5.79 12.50C5.67 16.67 5.31 20.83 5.24 25.00C5.17 29.17 5.35 33.33 5.36 37.50C5.37 41.67 5.32 45.83 5.31 50.00C5.30 54.17 5.27 58.33 5.31 62.50C5.34 66.67 5.43 70.83 5.50 75.00C5.58 79.17 5.68 83.33 5.76 87.50C5.85 91.67 5.96 97.92 6.00 100.00' fill='none' stroke='%231c1b19' stroke-width='1' stroke-linecap='round' vector-effect='non-scaling-stroke'/%3E%3C/svg%3E"); }
.stat:nth-child(5)::before { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 100' preserveAspectRatio='none'%3E%3Cpath d='M6.00 0.00C5.95 2.08 5.81 8.33 5.72 12.50C5.63 16.67 5.52 20.83 5.44 25.00C5.36 29.17 5.23 33.33 5.25 37.50C5.27 41.67 5.49 45.83 5.56 50.00C5.63 54.17 5.64 58.33 5.66 62.50C5.68 66.67 5.68 70.83 5.69 75.00C5.70 79.17 5.65 83.33 5.71 87.50C5.76 91.67 5.95 97.92 6.00 100.00' fill='none' stroke='%231c1b19' stroke-width='1' stroke-linecap='round' vector-effect='non-scaling-stroke'/%3E%3C/svg%3E"); }
.stat:nth-child(6)::before { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 100' preserveAspectRatio='none'%3E%3Cpath d='M6.00 0.00C6.07 2.08 6.33 8.33 6.42 12.50C6.51 16.67 6.49 20.83 6.53 25.00C6.57 29.17 6.60 33.33 6.66 37.50C6.73 41.67 6.87 45.83 6.91 50.00C6.95 54.17 6.92 58.33 6.88 62.50C6.83 66.67 6.71 70.83 6.64 75.00C6.57 79.17 6.55 83.33 6.44 87.50C6.33 91.67 6.07 97.92 6.00 100.00' fill='none' stroke='%231c1b19' stroke-width='1' stroke-linecap='round' vector-effect='non-scaling-stroke'/%3E%3C/svg%3E"); }
.stat:nth-child(3)::after { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 12' preserveAspectRatio='none'%3E%3Cpath d='M0.00 6.00C2.08 5.96 8.33 5.82 12.50 5.75C16.67 5.68 20.83 5.72 25.00 5.60C29.17 5.47 33.33 5.05 37.50 5.01C41.67 4.97 45.83 5.28 50.00 5.34C54.17 5.39 58.33 5.30 62.50 5.33C66.67 5.36 70.83 5.47 75.00 5.51C79.17 5.54 83.33 5.46 87.50 5.54C91.67 5.62 97.92 5.92 100.00 6.00' fill='none' stroke='%231c1b19' stroke-width='1' stroke-linecap='round' vector-effect='non-scaling-stroke'/%3E%3C/svg%3E"); }
.stat:nth-child(4)::after { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 12' preserveAspectRatio='none'%3E%3Cpath d='M0.00 6.00C2.08 5.95 8.33 5.73 12.50 5.68C16.67 5.63 20.83 5.79 25.00 5.71C29.17 5.64 33.33 5.33 37.50 5.23C41.67 5.12 45.83 5.07 50.00 5.10C54.17 5.14 58.33 5.39 62.50 5.44C66.67 5.49 70.83 5.38 75.00 5.40C79.17 5.43 83.33 5.48 87.50 5.58C91.67 5.68 97.92 5.93 100.00 6.00' fill='none' stroke='%231c1b19' stroke-width='1' stroke-linecap='round' vector-effect='non-scaling-stroke'/%3E%3C/svg%3E"); }
.stat:nth-child(5)::after { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 12' preserveAspectRatio='none'%3E%3Cpath d='M0.00 6.00C2.08 5.97 8.33 5.93 12.50 5.82C16.67 5.71 20.83 5.42 25.00 5.32C29.17 5.22 33.33 5.26 37.50 5.22C41.67 5.18 45.83 5.05 50.00 5.08C54.17 5.10 58.33 5.34 62.50 5.38C66.67 5.41 70.83 5.19 75.00 5.26C79.17 5.33 83.33 5.67 87.50 5.79C91.67 5.92 97.92 5.97 100.00 6.00' fill='none' stroke='%231c1b19' stroke-width='1' stroke-linecap='round' vector-effect='non-scaling-stroke'/%3E%3C/svg%3E"); }
.stat:nth-child(6)::after { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 12' preserveAspectRatio='none'%3E%3Cpath d='M0.00 6.00C2.08 6.06 8.33 6.31 12.50 6.39C16.67 6.46 20.83 6.37 25.00 6.46C29.17 6.54 33.33 6.83 37.50 6.90C41.67 6.97 45.83 6.85 50.00 6.88C54.17 6.90 58.33 7.11 62.50 7.05C66.67 6.99 70.83 6.59 75.00 6.50C79.17 6.41 83.33 6.58 87.50 6.50C91.67 6.42 97.92 6.08 100.00 6.00' fill='none' stroke='%231c1b19' stroke-width='1' stroke-linecap='round' vector-effect='non-scaling-stroke'/%3E%3C/svg%3E"); }

/* Same treatment for the seam between wrapped rows. */
.stat::after {
  content: none;
  position: absolute;
  left: -4px;
  top: -6px;
  width: calc(100% + 8px);
  height: 12px;
  background-repeat: no-repeat;
  background-position: center;
  background-size: 100% 100%;
}
@media (max-width: 900px) {
  .stats { grid-template-columns: repeat(3, 1fr); }
  .stat:nth-child(4)::before { content: none; }
  .stat:nth-child(n+4)::after { content: ""; }
}
@media (max-width: 600px) {
  .stats { grid-template-columns: repeat(2, 1fr); }
  .stat:nth-child(3)::before { content: none; }
  .stat:nth-child(4)::before { content: ""; }
  .stat:nth-child(5)::before { content: none; }
  .stat:nth-child(n+3)::after { content: ""; }
}
.stat__value { font-family: var(--hand); font-weight: 600; font-size: 27px; line-height: 0.92; }
.stat__value--green { color: var(--green); }
.stat__label { font-size: 17px; letter-spacing: .02em; color: var(--ink-faint); margin-top: -3px; }

/* ------------------------------------------------------------------- grid */

.calendar {
  display: grid;
  grid-template-columns: repeat(var(--cols, 18), minmax(0, 1fr));
  gap: 5px;
}

.cell {
  aspect-ratio: 1 / 1;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--hand);
  font-size: 16px;
  font-weight: 500;
  color: var(--ink-soft);
  border: 1px solid var(--rule);
  border-radius: 2px;
  background: var(--sheet);
  user-select: none;
}
/* Every tenth cell is a little darker: a ruler along the cycle. */
.cell--decade { border-color: #d9d5c9; }
/* Hand-drawn squares. Four variants cycled across the grid so the 365 cells
   never fall into a visible repeating pattern. */
.cell--w0 { border-radius: 14px 3px 12px 4px / 4px 12px 3px 14px; }
.cell--w1 { border-radius: 4px 13px 3px 12px / 12px 3px 14px 4px; }
.cell--w2 { border-radius: 12px 4px 14px 3px / 3px 14px 4px 12px; }
.cell--w3 { border-radius: 3px 12px 4px 14px / 14px 4px 12px 3px; }
.cell--marked { background: var(--green); border-color: var(--green-deep); color: #fff; font-weight: 600; }
.cell--missed {
  color: var(--miss);
  border-color: var(--miss);
  background: var(--sheet);
}
.cell--today { border: 1px solid var(--ink); color: var(--ink); font-weight: 700; }
.cell--today.cell--marked { border-color: var(--ink); color: #fff; }
.cell--future { background: #fdfdfb; }

.legend { display: flex; gap: 20px; flex-wrap: wrap; font-size: 17px; color: var(--ink-faint); margin-top: 12px; letter-spacing: .02em; }
.legend span { display: inline-flex; align-items: center; gap: 8px; }
/* Same hand-drawn corners as the calendar cells, scaled to the swatch size so
   each legend key matches the squares it explains. */
.legend i { width: 15px; height: 15px; border: 1px solid var(--rule); display: inline-block; }
.legend i.is-marked { border-radius: 7px 2px 6px 2px / 2px 6px 2px 7px; }
.legend i.is-today  { border-radius: 2px 7px 2px 6px / 6px 2px 7px 2px; }
.legend i.is-missed { border-radius: 6px 2px 7px 2px / 2px 7px 2px 6px; }
.legend i.is-marked { background: var(--green); border-color: var(--green-deep); }
.legend i.is-today { border-color: var(--ink); }
.legend i.is-missed { border-color: var(--miss); background: none; }

/* ---------------------------------------------------------------- relapse */

.relapse { display: flex; align-items: center; justify-content: space-between; gap: 18px; flex-wrap: wrap; }
.relapse__text { font-family: var(--hand); font-size: 19px; color: var(--ink-soft); max-width: 54ch; margin: 0; }
/* Divider drawn like the panel's own edges: a pen stroke, not a dashed rule. */
.relapse__confirm {
  position: relative;
  margin-top: 16px;
  padding-top: 9px;
}
.relapse__confirm::before {
  content: "";
  position: absolute;
  left: 0;
  top: -6px;
  width: 100%;
  height: 12px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 12' preserveAspectRatio='none'%3E%3Cpath d='M0.00 6.00C1.85 6.06 7.41 6.30 11.11 6.38C14.81 6.46 18.52 6.38 22.22 6.48C25.93 6.58 29.63 6.90 33.33 6.95C37.04 7.01 40.74 6.82 44.44 6.82C48.15 6.82 51.85 7.01 55.56 6.98C59.26 6.95 62.96 6.73 66.67 6.65C70.37 6.56 74.07 6.49 77.78 6.45C81.48 6.41 85.19 6.48 88.89 6.41C92.59 6.33 98.15 6.07 100.00 6.00' fill='none' stroke='%231c1b19' stroke-width='1' stroke-linecap='round' vector-effect='non-scaling-stroke'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: center;
  background-size: 100% 100%;
}
.relapse__confirm[hidden] { display: none; }
.relapse__row { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; margin-top: 12px; }

.stack > * + * { margin-top: 20px; }

.foot { font-family: var(--hand); text-align: center; font-size: 17px; line-height: 1.15; color: var(--ink-faint); margin-top: 24px; margin-bottom: 0; letter-spacing: .02em; }

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

/* ------------------------------------------------------------ responsive */

@media (max-width: 860px) { .calendar { --cols: 16; } .sheet { padding: 22px 20px; } }
@media (max-width: 620px) {
  .calendar { --cols: 12; gap: 4px; }
  .today__count { font-size: 38px; }
  .wrap { padding-top: 22px; }
}
@media (max-width: 420px) { .calendar { --cols: 9; } .cell { font-size: 14px; } }

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; }
  /* The ring is drawn by an animation; without it, show the finished ring. */
  .tab[aria-selected="true"] .tab__circle path { stroke-dashoffset: 0; }
}

@media print {
  body { background: #fff; }
  .sheet { box-shadow: none; }
  .btn, .topbar__user, .relapse { display: none; }
}

/* The stock badge is hidden with the rest of the widget, so it is redrawn here.
   Google's terms require the branding to stay visible, hence the mark, the
   name and the policy links. */
.captcha__logo {
  position: absolute;
  right: 10px;
  /* Sits a little above centre in the 76px-tall widget. */
  top: 50%;
  transform: translateY(-72%);
  width: 64px;
  height: 64px;
  object-fit: contain;
  border: 0;
  border-radius: 0;
  background: none;
  /* Multiply drops the sticker's white backing entirely against the white
     ground, so no square shows even where alpha WebM is unsupported. */
  mix-blend-mode: multiply;
  pointer-events: none;
}


/* reCAPTCHA renders at a fixed 304px. Inside the card a phone leaves less room
   than that, so the whole frame is scaled down rather than clipped. */
@media (max-width: 620px) {
  .captcha { overflow: visible; }
  .captcha__frame {
    transform: rotate(-0.35deg) scale(0.88);
    transform-origin: left center;
  }
}
@media (max-width: 380px) {
  .captcha__frame {
    transform: rotate(-0.35deg) scale(0.8);
    transform-origin: left center;
  }
}
