/* Figtree (2.19): a friendly geometric sans by Erik Kennedy, under the SIL
   Open Font License (fonts/OFL.txt). Self-hosted and precached, so it works
   offline and in the APK; one variable file covers every weight, and only
   the Latin range the app writes in (Spanish and English). */
@font-face {
  font-family: 'Figtree';
  font-style: normal;
  font-weight: 300 900;
  font-display: swap;
  src: url('fonts/figtree-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;
}

/* ══ Hábitos — design tokens ══════════════════════════════════════════
   Dark is the default surface; light is a selected palette, not a flip.
   Chart series/ramp tokens come from a CVD-validated palette (both modes
   pass the adjacent-pair separation gates against these surfaces).      */

:root {
  color-scheme: dark;

  --bg: #0D1117;
  --surface: #161B22;
  --surface-2: #1C2330;
  --surface-3: #232B39;
  --ink: #F0F6FC;
  --ink-2: #9BA6B4;
  --ink-3: #6B7684;
  --border: rgba(240, 246, 252, 0.09);
  --border-strong: rgba(240, 246, 252, 0.16);

  --accent: #3987E5;
  --accent-ink: #FFFFFF;
  --accent-soft: rgba(57, 135, 229, 0.14);
  --good: #0CA30C;
  --danger: #E66767;
  --danger-soft: rgba(230, 103, 103, 0.13);

  /* Categorical series — validated dark steps */
  --s1: #3987E5;
  --s2: #D95926;
  --s3: #199E70;
  --s4: #C98500;
  --s5: #D55181;
  --s6: #008300;
  --s7: #9085E9;
  --s8: #E66767;

  /* Sequential blue ramp: dark → light as magnitude rises */
  --seq-0: #1B2330;
  --seq-1: #184F95;
  --seq-2: #256ABF;
  --seq-3: #3987E5;
  --seq-4: #6DA7EC;
  --seq-5: #9EC5F4;

  --grid: #2C2C2A;
  --axis: #383835;
  --muted-ink: #898781;

  --radius: 14px;
  --radius-lg: 20px;
  --radius-pill: 999px;
  --shadow: 0 8px 28px rgba(0, 0, 0, 0.42);
  /* Cards (2.19): on dark a hairline edge does the work; on light the edge
     nearly goes and a soft, low shadow lifts the card instead. */
  --edge: var(--border);
  --lift: none;
  --tap: 44px;
  --font: 'Figtree', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
  --safe-b: env(safe-area-inset-bottom, 0px);
}

:root[data-theme='light'] {
  color-scheme: light;

  --bg: #F4F5F7;
  --surface: #FFFFFF;
  --surface-2: #FFFFFF;
  --surface-3: #EFF1F5;
  --ink: #0B0B0B;
  --ink-2: #52514E;
  --ink-3: #898781;
  --border: rgba(11, 11, 11, 0.10);
  --border-strong: rgba(11, 11, 11, 0.20);

  --accent: #2A78D6;
  --accent-ink: #FFFFFF;
  --accent-soft: rgba(42, 120, 214, 0.12);
  --good: #006300;
  --danger: #D03B3B;
  --danger-soft: rgba(208, 59, 59, 0.10);

  --s1: #2A78D6;
  --s2: #EB6834;
  --s3: #1BAF7A;
  --s4: #EDA100;
  --s5: #E87BA4;
  --s6: #008300;
  --s7: #4A3AA7;
  --s8: #E34948;

  --seq-0: #EEF1F5;
  --seq-1: #CDE2FB;
  --seq-2: #9EC5F4;
  --seq-3: #5598E7;
  --seq-4: #2A78D6;
  --seq-5: #184F95;

  --grid: #E1E0D9;
  --axis: #C3C2B7;
  --muted-ink: #898781;

  --shadow: 0 8px 28px rgba(11, 11, 11, 0.10);
  --edge: color-mix(in srgb, var(--ink) 6%, transparent);
  --lift: 0 1px 2px rgba(16, 24, 40, 0.05), 0 4px 14px rgba(16, 24, 40, 0.05);
}

/* ── Palettes (2.13) ──────────────────────────────────────────────────
   Classic is the two blocks above. Every other palette restates each colour
   token for dark and for light (Ultra oscura and Halloween are dark only: the
   app resolves the theme to dark while one is chosen), and so does each card
   of the picker
   in Ajustes, which previews its palette with the very same tokens.
   The habit colours keep their family per slot in every palette — s1 blue,
   s2 orange, s3 teal, s4 amber, s5 pink, s6 green, s7 violet, s8 red — so a
   habit keeps its colour when the palette changes and the BMI bands keep
   their meaning. Each set passes the same checks as classic against its own
   surface: lightness band, chroma floor, adjacent-pair separation under
   protanopia and deuteranopia, and the normal-vision floor; text, accent and
   status colours hold at least classic's own contrast. */

.palette-card[data-palette='classic'] {
  --bg: #0D1117; --surface: #161B22; --surface-2: #1C2330; --surface-3: #232B39;
  --ink: #F0F6FC; --ink-2: #9BA6B4; --ink-3: #6B7684;
  --border: rgba(240, 246, 252, 0.09); --border-strong: rgba(240, 246, 252, 0.16);
  --accent: #3987E5; --accent-ink: #FFFFFF; --accent-soft: rgba(57, 135, 229, 0.14);
  --good: #0CA30C; --danger: #E66767; --danger-soft: rgba(230, 103, 103, 0.13);
  --s1: #3987E5; --s2: #D95926; --s3: #199E70; --s4: #C98500;
  --s5: #D55181; --s6: #008300; --s7: #9085E9; --s8: #E66767;
  --seq-0: #1B2330; --seq-1: #184F95; --seq-2: #256ABF;
  --seq-3: #3987E5; --seq-4: #6DA7EC; --seq-5: #9EC5F4;
  --grid: #2C2C2A; --axis: #383835; --muted-ink: #898781;
  --shadow: 0 8px 28px rgba(0, 0, 0, 0.42);
}

:root[data-theme='light'] .palette-card[data-palette='classic'] {
  --bg: #F4F5F7; --surface: #FFFFFF; --surface-2: #FFFFFF; --surface-3: #EFF1F5;
  --ink: #0B0B0B; --ink-2: #52514E; --ink-3: #898781;
  --border: rgba(11, 11, 11, 0.10); --border-strong: rgba(11, 11, 11, 0.20);
  --accent: #2A78D6; --accent-ink: #FFFFFF; --accent-soft: rgba(42, 120, 214, 0.12);
  --good: #006300; --danger: #D03B3B; --danger-soft: rgba(208, 59, 59, 0.10);
  --s1: #2A78D6; --s2: #EB6834; --s3: #1BAF7A; --s4: #EDA100;
  --s5: #E87BA4; --s6: #008300; --s7: #4A3AA7; --s8: #E34948;
  --seq-0: #EEF1F5; --seq-1: #CDE2FB; --seq-2: #9EC5F4;
  --seq-3: #5598E7; --seq-4: #2A78D6; --seq-5: #184F95;
  --grid: #E1E0D9; --axis: #C3C2B7; --muted-ink: #898781;
  --shadow: 0 8px 28px rgba(11, 11, 11, 0.10);
}

:root[data-palette='electric'],
.palette-card[data-palette='electric'] {
  --bg: #0A0816; --surface: #120F24; --surface-2: #191530; --surface-3: #231D3F;
  --ink: #F5F2FF; --ink-2: #ADA6D8; --ink-3: #8079B0;
  --border: rgba(170, 150, 255, 0.14); --border-strong: rgba(170, 150, 255, 0.26);
  --accent: #1FD5F0; --accent-ink: #06111B; --accent-soft: rgba(31, 213, 240, 0.14);
  --good: #0FA34E; --danger: #FF4F7B; --danger-soft: rgba(255, 79, 123, 0.14);
  --s1: #086EFF; --s2: #FB5000; --s3: #00A9A6; --s4: #B27F01;
  --s5: #F800CF; --s6: #009F32; --s7: #7200FE; --s8: #CE013B;
  --seq-0: #231D3F; --seq-1: #00515D; --seq-2: #04707F;
  --seq-3: #0290A4; --seq-4: #18B5CC; --seq-5: #84D3E2;
  --grid: #241F40; --axis: #342D57; --muted-ink: #8C86B5;
  --shadow: 0 8px 28px rgba(0, 0, 0, 0.55);
}

:root[data-palette='electric'][data-theme='light'],
:root[data-theme='light'] .palette-card[data-palette='electric'] {
  --bg: #F5F3FF; --surface: #FFFFFF; --surface-2: #FFFFFF; --surface-3: #EEEAFD;
  --ink: #0D0A1F; --ink-2: #4B4570; --ink-3: #78729E;
  --border: rgba(60, 30, 160, 0.12); --border-strong: rgba(60, 30, 160, 0.24);
  --accent: #6A1BFF; --accent-ink: #FFFFFF; --accent-soft: rgba(106, 27, 255, 0.10);
  --good: #00853A; --danger: #DB0049; --danger-soft: rgba(219, 0, 73, 0.09);
  --s1: #122EFF; --s2: #FE4801; --s3: #008F86; --s4: #F29E00;
  --s5: #FD01D4; --s6: #319D00; --s7: #7100CE; --s8: #C00331;
  --seq-0: #EEEAFD; --seq-1: #DEDEFB; --seq-2: #BFBDF6;
  --seq-3: #9893E5; --seq-4: #756BC8; --seq-5: #4F4591;
  --grid: #E6E2F5; --axis: #CBC5E6; --muted-ink: #78729E;
  --shadow: 0 8px 28px rgba(40, 20, 120, 0.12);
}

:root[data-palette='pastel'],
.palette-card[data-palette='pastel'] {
  --bg: #1C1A24; --surface: #25222F; --surface-2: #2C2938; --surface-3: #353144;
  --ink: #F4EFFA; --ink-2: #BDB5CC; --ink-3: #958DA4;
  --border: rgba(244, 239, 250, 0.09); --border-strong: rgba(244, 239, 250, 0.17);
  --accent: #B9AAF7; --accent-ink: #1C1A24; --accent-soft: rgba(185, 170, 247, 0.16);
  --good: #3F9A6E; --danger: #D87486; --danger-soft: rgba(216, 116, 134, 0.14);
  --s1: #6195CE; --s2: #B76935; --s3: #2FA7A1; --s4: #B48E23;
  --s5: #B06098; --s6: #71A252; --s7: #746FBC; --s8: #CD777E;
  --seq-0: #353144; --seq-1: #4B397D; --seq-2: #6752A6;
  --seq-3: #846ECC; --seq-4: #A493E6; --seq-5: #C5BBF4;
  --grid: #34303F; --axis: #433E52; --muted-ink: #9A93A8;
  --shadow: 0 8px 28px rgba(0, 0, 0, 0.38);
}

:root[data-palette='pastel'][data-theme='light'],
:root[data-theme='light'] .palette-card[data-palette='pastel'] {
  --bg: #FBF7F3; --surface: #FFFFFF; --surface-2: #FFFFFF; --surface-3: #F4EFF7;
  --ink: #2F2A3B; --ink-2: #5E586E; --ink-3: #857E94;
  --border: rgba(47, 42, 59, 0.10); --border-strong: rgba(47, 42, 59, 0.18);
  --accent: #7563CF; --accent-ink: #FFFFFF; --accent-soft: rgba(117, 99, 207, 0.13);
  --good: #2F8A5C; --danger: #C64560; --danger-soft: rgba(198, 69, 96, 0.10);
  --s1: #8AB4F5; --s2: #D98753; --s3: #57C7C1; --s4: #D4AD49;
  --s5: #D07FB6; --s6: #8EC270; --s7: #918DDD; --s8: #ED979C;
  --seq-0: #F4EFF7; --seq-1: #DFDEFB; --seq-2: #C1BDF6;
  --seq-3: #9B92E5; --seq-4: #776AC8; --seq-5: #514490;
  --grid: #EFE8EE; --axis: #D9D0DC; --muted-ink: #857E94;
  --shadow: 0 8px 28px rgba(80, 60, 100, 0.10);
}

:root[data-palette='ultra'],
.palette-card[data-palette='ultra'] {
  --bg: #000000; --surface: #0A0A0A; --surface-2: #111111; --surface-3: #1A1A1A;
  --ink: #F2F2F2; --ink-2: #A6A6A6; --ink-3: #737373;
  --border: rgba(255, 255, 255, 0.08); --border-strong: rgba(255, 255, 255, 0.15);
  --accent: #3987E5; --accent-ink: #FFFFFF; --accent-soft: rgba(57, 135, 229, 0.16);
  --good: #0CA30C; --danger: #E66767; --danger-soft: rgba(230, 103, 103, 0.14);
  --s1: #3987E5; --s2: #D95926; --s3: #199E70; --s4: #C98500;
  --s5: #D55181; --s6: #008300; --s7: #9085E9; --s8: #E66767;
  --seq-0: #141414; --seq-1: #184F95; --seq-2: #256ABF;
  --seq-3: #3987E5; --seq-4: #6DA7EC; --seq-5: #9EC5F4;
  --grid: #1F1F1F; --axis: #2B2B2B; --muted-ink: #7D7D7D;
  --shadow: 0 8px 28px rgba(0, 0, 0, 0.8);
}

:root[data-palette='forest'],
.palette-card[data-palette='forest'] {
  --bg: #0E1611; --surface: #15211B; --surface-2: #1B2922; --surface-3: #23332A;
  --ink: #ECF3EE; --ink-2: #A5B6AB; --ink-3: #77897D;
  --border: rgba(236, 243, 238, 0.09); --border-strong: rgba(236, 243, 238, 0.16);
  --accent: #6CC18F; --accent-ink: #0E1611; --accent-soft: rgba(108, 193, 143, 0.15);
  --good: #3E9B43; --danger: #E27265; --danger-soft: rgba(226, 114, 101, 0.13);
  --s1: #338DDF; --s2: #DE6F46; --s3: #00A89D; --s4: #997D00;
  --s5: #B569AB; --s6: #2A7612; --s7: #7B46A4; --s8: #B0423F;
  --seq-0: #23332A; --seq-1: #005631; --seq-2: #007746;
  --seq-3: #11985C; --seq-4: #5AB882; --seq-5: #99D4AF;
  --grid: #22302A; --axis: #2F3E36; --muted-ink: #84958A;
  --shadow: 0 8px 28px rgba(0, 0, 0, 0.45);
}

:root[data-palette='forest'][data-theme='light'],
:root[data-theme='light'] .palette-card[data-palette='forest'] {
  --bg: #F2F4EE; --surface: #FFFFFF; --surface-2: #FFFFFF; --surface-3: #EAEFE5;
  --ink: #14211A; --ink-2: #4A5A50; --ink-3: #74837A;
  --border: rgba(20, 33, 26, 0.11); --border-strong: rgba(20, 33, 26, 0.20);
  --accent: #2C7A4F; --accent-ink: #FFFFFF; --accent-soft: rgba(44, 122, 79, 0.12);
  --good: #3B7F12; --danger: #B73E2D; --danger-soft: rgba(183, 62, 45, 0.10);
  --s1: #3A85CC; --s2: #D46E2B; --s3: #01A48F; --s4: #E4A623;
  --s5: #AB53A0; --s6: #266800; --s7: #6A3491; --s8: #AE3B3B;
  --seq-0: #EAEFE5; --seq-1: #CDEAD6; --seq-2: #9AD4AE;
  --seq-3: #58B47E; --seq-4: #059255; --seq-5: #036338;
  --grid: #E3E8DE; --axis: #C7CFC0; --muted-ink: #74837A;
  --shadow: 0 8px 28px rgba(20, 40, 25, 0.10);
}

:root[data-palette='sunset'],
.palette-card[data-palette='sunset'] {
  --bg: #1A0F12; --surface: #25171B; --surface-2: #2D1C21; --surface-3: #38242A;
  --ink: #FFF1EA; --ink-2: #D1AFA3; --ink-3: #A2827A;
  --border: rgba(255, 241, 234, 0.09); --border-strong: rgba(255, 241, 234, 0.17);
  --accent: #FF8C52; --accent-ink: #1A0F12; --accent-soft: rgba(255, 140, 82, 0.15);
  --good: #3C9E58; --danger: #EF6582; --danger-soft: rgba(239, 101, 130, 0.14);
  --s1: #6C8FE8; --s2: #FB5000; --s3: #00AB99; --s4: #B77D07;
  --s5: #C2127C; --s6: #009D1A; --s7: #7C3DB6; --s8: #A7473A;
  --seq-0: #38242A; --seq-1: #753003; --seq-2: #9D4613;
  --seq-3: #C2612D; --seq-4: #DF885F; --seq-5: #F1B599;
  --grid: #33222A; --axis: #442E36; --muted-ink: #A88A82;
  --shadow: 0 8px 28px rgba(0, 0, 0, 0.45);
}

:root[data-palette='sunset'][data-theme='light'],
:root[data-theme='light'] .palette-card[data-palette='sunset'] {
  --bg: #FFF5EF; --surface: #FFFFFF; --surface-2: #FFFFFF; --surface-3: #FCEBE2;
  --ink: #2B1710; --ink-2: #6E4C42; --ink-3: #977469;
  --border: rgba(43, 23, 16, 0.10); --border-strong: rgba(43, 23, 16, 0.19);
  --accent: #C23F0C; --accent-ink: #FFFFFF; --accent-soft: rgba(194, 63, 12, 0.11);
  --good: #2B8040; --danger: #BE1858; --danger-soft: rgba(190, 24, 88, 0.09);
  --s1: #6B8EDE; --s2: #F94F00; --s3: #009283; --s4: #EEA000;
  --s5: #EC449F; --s6: #139E02; --s7: #7539D3; --s8: #BB002C;
  --seq-0: #FCEBE2; --seq-1: #FAD9CF; --seq-2: #F3B39F;
  --seq-3: #DE8267; --seq-4: #BE5738; --seq-5: #87351A;
  --grid: #F2E3DA; --axis: #DCC6BA; --muted-ink: #977469;
  --shadow: 0 8px 28px rgba(90, 40, 20, 0.12);
}

:root[data-palette='ocean'],
.palette-card[data-palette='ocean'] {
  --bg: #071419; --surface: #0E2028; --surface-2: #132830; --surface-3: #1A323B;
  --ink: #E6F6FA; --ink-2: #9EBCC6; --ink-3: #6F8D98;
  --border: rgba(230, 246, 250, 0.09); --border-strong: rgba(230, 246, 250, 0.16);
  --accent: #36C9DC; --accent-ink: #04161C; --accent-soft: rgba(54, 201, 220, 0.14);
  --good: #2B9C5E; --danger: #E26F70; --danger-soft: rgba(226, 111, 112, 0.13);
  --s1: #328DF7; --s2: #E86357; --s3: #02A7B1; --s4: #AF7B00;
  --s5: #AA3E91; --s6: #029C4B; --s7: #564DC5; --s8: #BA2B2B;
  --seq-0: #1A323B; --seq-1: #02525B; --seq-2: #00707D;
  --seq-3: #0791A0; --seq-4: #11B6C8; --seq-5: #83D3DF;
  --grid: #1A2E36; --axis: #263D46; --muted-ink: #7896A0;
  --shadow: 0 8px 28px rgba(0, 0, 0, 0.45);
}

:root[data-palette='ocean'][data-theme='light'],
:root[data-theme='light'] .palette-card[data-palette='ocean'] {
  --bg: #EEF6F8; --surface: #FFFFFF; --surface-2: #FFFFFF; --surface-3: #E2EFF3;
  --ink: #08202A; --ink-2: #41606C; --ink-3: #6B8893;
  --border: rgba(8, 32, 42, 0.10); --border-strong: rgba(8, 32, 42, 0.19);
  --accent: #0B6C88; --accent-ink: #FFFFFF; --accent-soft: rgba(11, 108, 136, 0.11);
  --good: #15804A; --danger: #C9364B; --danger-soft: rgba(201, 54, 75, 0.09);
  --s1: #188DF3; --s2: #EF6538; --s3: #01929B; --s4: #EDA100;
  --s5: #8F437C; --s6: #06A247; --s7: #4F44B8; --s8: #BD2F28;
  --seq-0: #E2EFF3; --seq-1: #C6E8F5; --seq-2: #8AD0EB;
  --seq-3: #2FAED6; --seq-4: #0887AA; --seq-5: #035B74;
  --grid: #DCE9EE; --axis: #BCD0D8; --muted-ink: #6B8893;
  --shadow: 0 8px 28px rgba(8, 40, 60, 0.12);
}

:root[data-palette='contrast'],
.palette-card[data-palette='contrast'] {
  --bg: #000000; --surface: #0B0B0B; --surface-2: #121212; --surface-3: #1E1E1E;
  --ink: #FFFFFF; --ink-2: #E8E8E8; --ink-3: #BDBDBD;
  --border: rgba(255, 255, 255, 0.40); --border-strong: rgba(255, 255, 255, 0.70);
  --accent: #6FB3FF; --accent-ink: #000000; --accent-soft: rgba(111, 179, 255, 0.18);
  --good: #2CA54A; --danger: #F46162; --danger-soft: rgba(244, 97, 98, 0.16);
  --s1: #3D81FF; --s2: #EF6102; --s3: #00AA9D; --s4: #B08300;
  --s5: #E903A8; --s6: #06B23A; --s7: #955EE1; --s8: #E3013B;
  --seq-0: #1E1E1E; --seq-1: #0E4880; --seq-2: #1F65AA;
  --seq-3: #3983D1; --seq-4: #68A5EA; --seq-5: #9FC8F7;
  --grid: #333333; --axis: #6B6B6B; --muted-ink: #BDBDBD;
  --shadow: 0 8px 28px rgba(0, 0, 0, 0.9);
}

:root[data-palette='contrast'] { --edge: var(--border); --lift: none; }

:root[data-palette='contrast'][data-theme='light'],
:root[data-theme='light'] .palette-card[data-palette='contrast'] {
  --bg: #FFFFFF; --surface: #FFFFFF; --surface-2: #FFFFFF; --surface-3: #EDEDED;
  --ink: #000000; --ink-2: #222222; --ink-3: #4D4D4D;
  --border: rgba(0, 0, 0, 0.42); --border-strong: rgba(0, 0, 0, 0.72);
  --accent: #0047CC; --accent-ink: #FFFFFF; --accent-soft: rgba(0, 71, 204, 0.12);
  --good: #006E1F; --danger: #B0001E; --danger-soft: rgba(176, 0, 30, 0.08);
  --s1: #406BEB; --s2: #E54901; --s3: #009485; --s4: #A17400;
  --s5: #B3088A; --s6: #326700; --s7: #6C25C3; --s8: #B60027;
  --seq-0: #EDEDED; --seq-1: #D3E2FD; --seq-2: #A8C5F9;
  --seq-3: #759EE9; --seq-4: #4B77CC; --seq-5: #2C4F94;
  --grid: #D6D6D6; --axis: #8C8C8C; --muted-ink: #4D4D4D;
  --shadow: 0 8px 28px rgba(0, 0, 0, 0.18);
}

/* Halloween (2.23), dark only like Ultra oscura: a moonless night with a
   violet cast, candle-white text and a pumpkin accent (dark ink on it); the
   heat map ripens in pumpkin. Pico keeps his own violet, which stands out on
   it. Same checks as every other palette. */
:root[data-palette='halloween'],
.palette-card[data-palette='halloween'] {
  --bg: #0E0A14; --surface: #18111F; --surface-2: #1F1628; --surface-3: #291D34;
  --ink: #FBF1E6; --ink-2: #C4B2C6; --ink-3: #95839C;
  --border: rgba(251, 241, 230, 0.09); --border-strong: rgba(251, 241, 230, 0.17);
  --accent: #FF8A1E; --accent-ink: #170C02; --accent-soft: rgba(255, 138, 30, 0.15);
  --good: #4E9A22; --danger: #F0656F; --danger-soft: rgba(240, 101, 111, 0.14);
  --s1: #3184E0; --s2: #F75600; --s3: #04AA9D; --s4: #B28004;
  --s5: #D837A0; --s6: #357A3A; --s7: #874FCB; --s8: #B14F43;
  --seq-0: #291D34; --seq-1: #6E3701; --seq-2: #964D03;
  --seq-3: #BE6616; --seq-4: #DA8C53; --seq-5: #EDB792;
  --grid: #271C30; --axis: #382A43; --muted-ink: #9C8AA2;
  --shadow: 0 8px 28px rgba(0, 0, 0, 0.55);
}

/* ── Size scale ───────────────────────────────────────────────────────
   Text is in rem throughout, and the paddings that shape the layout are
   too, so moving the root size rescales the whole interface in one step.
   Tap targets stay pinned in px: Small may look tighter but must never
   become harder to hit. This replaces pinch-zoom, which is turned off. */
/* Large was 18.5px until 2.21, too close to Normal to be worth choosing:
   now it is clearly large (about a third more), everywhere, the charts too. */
:root { font-size: 16px; }
:root[data-density='small'] { font-size: 14px; }
:root[data-density='large'] { font-size: 21px; }

/* ── Reset & base ── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

[hidden] { display: none !important; }

html { -webkit-text-size-adjust: 100%; -webkit-tap-highlight-color: transparent; }
/* An app, not a page (2.21): a long press on a habit, an icon or a button
   selects nothing and drags nothing; what is typed into stays selectable. */
body { -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; }
input, textarea, [contenteditable='true'] { -webkit-user-select: text; user-select: text; }
img, svg { -webkit-user-drag: none; }

body {
  font-family: var(--font);
  background: var(--bg);
  color: var(--ink);
  line-height: 1.5;
  min-height: 100dvh;
  padding-bottom: calc(64px + var(--safe-b));
  overflow-x: hidden;
}

h1 { font-size: 1.125rem; font-weight: 750; letter-spacing: -0.01em; }
h2 { font-size: 1.55rem; font-weight: 800; letter-spacing: -0.025em; }
h3 { font-size: 0.98rem; font-weight: 700; letter-spacing: -0.01em; }

button, input, select, textarea { font: inherit; color: inherit; }
button { cursor: pointer; background: none; border: none; }

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

.skip-link {
  position: absolute; left: 8px; top: -60px; z-index: 200;
  background: var(--accent); color: var(--accent-ink);
  padding: 10px 14px; border-radius: var(--radius); text-decoration: none;
  transition: top 0.15s;
}
.skip-link:focus { top: 8px; }

a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
summary:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.muted { color: var(--ink-2); }
.small { font-size: 0.8rem; }
.spacer { flex: 1; }

/* ── App bar & tab bar ── */
.app-bar {
  position: sticky; top: 0; z-index: 50;
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; height: 56px; padding: 0 16px;
  background: color-mix(in srgb, var(--bg) 88%, transparent);
  backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
  border-bottom: 1px solid transparent;
  transition: border-color 0.2s;
}
body.is-scrolled .app-bar { border-bottom-color: var(--border); }
.app-bar-title { display: flex; align-items: center; gap: 10px; min-width: 0; }
/* Where the view has its own big heading, the bar's title waits for it to
   scroll away (2.19), rather than saying the same word twice. */
#viewTitle { transition: opacity 0.2s, transform 0.2s; }
body[data-view]:not([data-view='today']):not(.is-scrolled) #viewTitle { opacity: 0; transform: translateY(5px); }
.app-mark {
  width: 22px; height: 22px; flex: none; border-radius: 7px;
  background: linear-gradient(140deg, var(--s1), var(--s3));
}
.app-bar-actions { display: flex; align-items: center; gap: 4px; }

.icon-btn {
  display: grid; place-items: center;
  min-width: 40px; height: 40px; padding: 0 9px;
  border-radius: var(--radius-pill); color: var(--ink-2);
  font-size: 0.8rem; font-weight: 700;
  transition: background 0.15s, color 0.15s, transform 0.15s;
}
.icon-btn:hover { background: var(--surface-2); color: var(--ink); }

.tab-bar {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 60;
  display: grid; grid-template-columns: repeat(4, 1fr);
  background: color-mix(in srgb, var(--surface) 94%, transparent);
  backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
  border-top: 1px solid var(--border);
  padding-bottom: var(--safe-b);
}
.tab {
  position: relative;
  display: flex; flex-direction: column; align-items: center; gap: 4px;
  padding: 9px 4px 8px; color: var(--ink-3);
  font-size: 0.68rem; font-weight: 600; letter-spacing: 0.01em;
  transition: color 0.2s;
}
.tab svg { position: relative; width: 22px; height: 22px; transition: transform 0.15s; }
.tab::before {
  content: ''; position: absolute; top: 4px; left: 50%;
  width: 56px; height: 32px; margin-left: -28px;
  border-radius: var(--radius-pill); background: var(--accent-soft);
  opacity: 0; transform: scaleX(0.4);
  transition: opacity 0.2s, transform var(--spring-time) var(--spring);
}
.tab[aria-current='page'] { color: var(--accent); font-weight: 750; }
.tab[aria-current='page']::before { opacity: 1; transform: none; }

/* ── Layout ── */
.view-inner {
  max-width: 680px; margin: 0 auto;
  padding: 1rem 1rem 1.75rem;
  display: flex; flex-direction: column; gap: 1.125rem;
}
.section-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; margin-bottom: 10px;
}
.card {
  background: var(--surface); border: 1px solid var(--edge);
  border-radius: var(--radius-lg); padding: 1rem;
  box-shadow: var(--lift);
}
.card-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.card-hint { color: var(--ink-3); font-size: 0.78rem; }

/* ── Buttons ── */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  min-height: 44px; padding: 0 18px;
  background: var(--surface-3); color: var(--ink);
  border: 1px solid var(--edge); border-radius: var(--radius-pill);
  font-size: 0.88rem; font-weight: 650;
  transition: filter 0.12s, background 0.12s, transform 0.15s;
}
.btn:hover { filter: brightness(1.06); }
.btn-sm { min-height: 36px; padding: 0 14px; font-size: 0.82rem; }
.btn-primary { background: var(--accent); color: var(--accent-ink); border-color: transparent; }
.btn-danger { color: var(--danger); border-color: color-mix(in srgb, var(--danger) 40%, transparent); background: var(--danger-soft); }
.btn-danger.ghost { background: none; }
.button-row { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
.btn-ghost { background: none; border-color: transparent; color: var(--ink-2); }

/* Things give a little under the finger (2.19). */
@media (prefers-reduced-motion: no-preference) {
  .btn:active, .icon-btn:active { transform: scale(0.96); }
  .tab:active svg { transform: scale(0.88); }
  .check-btn:active { transform: scale(0.9); }
  .day-chip:active, .segmented button:active { transform: scale(0.95); }
}

/* ── Day strip ── */
/* Horizontally scrollable so earlier weeks stay reachable. Sized so roughly a
   week fills the width at the default size, which keeps the familiar look. */
.day-strip {
  display: flex; gap: 6px;
  overflow-x: auto; overscroll-behavior-x: contain;
  scroll-snap-type: x proximity;
  scrollbar-width: none;
  margin: 0 -1rem;            /* bleed to the screen edges */
  padding: 0 1rem 2px;
}
.day-strip::-webkit-scrollbar { display: none; }
.day-chip {
  flex: 0 0 auto;
  width: calc((100% - 6 * 6px) / 7);
  min-width: 2.6rem;
  scroll-snap-align: center;
  display: flex; flex-direction: column; align-items: center; gap: 3px;
  padding: 0.5rem 0.125rem; border-radius: var(--radius-pill);
  border: 1px solid transparent; background: transparent;
  color: var(--ink-2); font-size: 0.7rem; font-weight: 650;
  transition: background 0.2s, color 0.2s;
}
.day-chip .dnum { font-size: 0.95rem; font-weight: 700; color: var(--ink); }
.day-chip .ddot { width: 5px; height: 5px; border-radius: 50%; background: var(--border-strong); }
.day-chip .ddot.filled { background: var(--good); }
/* A quiet marker where a new month begins, for long scrolls back. */
.day-chip.is-month-start { box-shadow: inset 2px 0 0 var(--border-strong); }
.day-chip[aria-selected='true'] { background: var(--accent); color: var(--accent-ink); }
.day-chip[aria-selected='true'] .dnum { color: var(--accent-ink); }
.day-chip[aria-selected='true'] .ddot { background: color-mix(in srgb, var(--accent-ink) 40%, transparent); }
.day-chip[aria-selected='true'] .ddot.filled { background: var(--accent-ink); }
.day-chip[disabled] { opacity: 0.38; }

/* ── Summary card ── */
.summary-card {
  display: flex; align-items: center; gap: 1.125rem;
  background: var(--surface); border: 1px solid var(--edge);
  border-radius: var(--radius-lg); padding: 1rem;
  box-shadow: var(--lift);
}
.summary-ring { position: relative; flex: none; display: grid; place-items: center; }
/* Overrides the SVG's own width/height so the ring scales with the size setting. */
.summary-ring svg { transform: rotate(-90deg); width: 6.5rem; height: 6.5rem; }
.ring-track { fill: none; stroke: var(--surface-3); stroke-width: 10; }
.ring-value {
  fill: none; stroke: var(--accent); stroke-width: 10; stroke-linecap: round;
  transition: stroke-dashoffset 0.45s ease;
}
.summary-ring-label {
  position: absolute; inset: 0; display: grid; place-content: center;
  text-align: center; line-height: 1.15;
}
.summary-ring-label strong { font-size: 1.55rem; font-weight: 800; letter-spacing: -0.02em; }
.summary-ring-label span { font-size: 0.75rem; color: var(--ink-2); font-variant-numeric: tabular-nums; }
.summary-stats { min-width: 0; flex: 1; }
/* Too narrow for the ring and the figures side by side — Grande on a phone
   (2.21) — the figures go under the ring, as wide as the card. In rem, so it
   follows the size setting, not only the screen. */
.summary-card { flex-wrap: wrap; justify-content: center; container-type: inline-size; }
@container (max-width: 17rem) {
  .summary-stats { flex-basis: 100%; }
}
.summary-date { font-size: 0.82rem; color: var(--ink-2); margin-bottom: 10px; }
.stat-row { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
.stat-tile {
  background: var(--surface-3); border-radius: var(--radius);
  padding: 0.5625rem 0.6875rem; display: flex; flex-direction: column; gap: 1px;
}
.stat-value { font-size: 1.15rem; font-weight: 750; line-height: 1.15; letter-spacing: -0.01em; }
.stat-row .stat-value { font-size: 1.02rem; }
.stat-label { font-size: 0.68rem; color: var(--ink-2); line-height: 1.25; }

/* ── Mood ── */
.mood-scale { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 7px; margin-top: 12px; }
.mood-btn {
  display: flex; flex-direction: column; align-items: center; gap: 4px;
  padding: 0.625rem 0.125rem; border-radius: var(--radius);
  border: 1px solid var(--border); background: var(--surface-3);
  font-size: 0.62rem; font-weight: 600; color: var(--ink-2);
  transition: transform 0.12s, border-color 0.12s;
}
.mood-btn .emoji { font-size: 1.45rem; line-height: 1; filter: saturate(0.85); }
.mood-btn:hover { transform: translateY(-2px); }
.mood-btn[aria-checked='true'] {
  border-color: var(--accent); background: var(--accent-soft); color: var(--ink);
}
.mood-btn[aria-checked='true'] .emoji { filter: none; }
.mood-extra { margin-top: 14px; display: flex; flex-direction: column; gap: 12px; }

/* ── Fields ── */
.field { display: flex; flex-direction: column; gap: 6px; }
.field.inline { flex-direction: row; align-items: center; gap: 8px; }
.field-label { font-size: 0.78rem; font-weight: 600; color: var(--ink-2); }
.field-hint { font-size: 0.75rem; color: var(--ink-3); }
.field-pair { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }

input[type='text'], input[type='search'], input[type='number'], input[type='time'], select, textarea {
  width: 100%; min-height: 44px; padding: 10px 12px;
  background: var(--surface-3); border: 1px solid var(--border);
  border-radius: var(--radius); color: var(--ink);
}
textarea { min-height: 62px; resize: vertical; line-height: 1.45; }
input[type='range'] { accent-color: var(--accent); width: 100%; min-height: 34px; }

/* Energy (2.20): a slider a point at a time, its track filled up to the
   value, a thumb big enough for a thumb, and a button each side for one
   point more or less. */
.energy-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.energy-out { font-size: 0.82rem; font-weight: 650; color: var(--ink); font-variant-numeric: tabular-nums; }
.energy-control { display: flex; align-items: center; gap: 8px; }
.energy-step {
  flex: none; width: 36px; height: 36px; border-radius: 50%;
  display: grid; place-items: center; font-size: 1.15rem; font-weight: 650; line-height: 1;
  color: var(--ink-2); background: var(--surface-3); border: 1px solid var(--edge);
  touch-action: none; user-select: none; -webkit-user-select: none;
}
.energy-step:disabled { opacity: 0.35; }
.energy-range {
  --pct: 50%;
  --thumb: 26px;                       /* app.js reads it to follow a finger */
  -webkit-appearance: none; appearance: none; flex: 1; min-width: 0;
  height: var(--tap); min-height: var(--tap); background: transparent; cursor: pointer;
  touch-action: pan-y;
}
.energy-range::-webkit-slider-runnable-track {
  height: 8px; border-radius: var(--radius-pill);
  background: linear-gradient(to right, var(--accent) var(--pct), var(--surface-3) var(--pct));
}
.energy-range::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none; width: var(--thumb); height: var(--thumb); margin-top: calc((8px - var(--thumb)) / 2);
  border-radius: 50%; background: var(--surface); border: 3px solid var(--accent);
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.25);
}
.energy-range::-moz-range-track { height: 8px; border-radius: var(--radius-pill); background: var(--surface-3); }
.energy-range::-moz-range-progress { height: 8px; border-radius: var(--radius-pill); background: var(--accent); }
.energy-range::-moz-range-thumb {
  width: 20px; height: 20px; border-radius: 50%; background: var(--surface); border: 3px solid var(--accent);
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.25);
}
.energy-range:focus-visible { outline: none; }
.energy-range:focus-visible::-webkit-slider-thumb { box-shadow: 0 0 0 4px var(--accent-soft), 0 1px 4px rgba(0, 0, 0, 0.25); }
select { appearance: none; padding-right: 32px;
  background-image: linear-gradient(45deg, transparent 50%, var(--ink-2) 50%),
                    linear-gradient(135deg, var(--ink-2) 50%, transparent 50%);
  background-position: calc(100% - 17px) 20px, calc(100% - 12px) 20px;
  background-size: 5px 5px, 5px 5px; background-repeat: no-repeat;
}

/* ── Dropdowns (2.18) ──
   select.js keeps each <select> for its value and events but hides it, and
   draws a button like the app's fields; the list opens in the app's own
   colours, anchored to the button, instead of Android's plain dialog. */
.gs-native {
  position: absolute !important; width: 1px !important; height: 1px !important; min-height: 0 !important;
  padding: 0 !important; margin: 0 !important; border: 0 !important;
  opacity: 0; pointer-events: none; clip-path: inset(50%); overflow: hidden;
}
.gs-trigger {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  width: 100%; min-height: var(--tap); padding: 10px 12px;
  background: var(--surface-3); border: 1px solid var(--border); border-radius: var(--radius);
  color: var(--ink); text-align: left; cursor: pointer;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.gs-trigger:hover { border-color: var(--border-strong); }
.gs-trigger[aria-expanded='true'] { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.gs-trigger:disabled { opacity: 0.55; cursor: default; }
.gs-value { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.gs-chevron {
  width: 18px; height: 18px; flex: none; fill: none; stroke: var(--ink-2);
  stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; transition: transform 0.2s ease;
}
.gs-trigger[aria-expanded='true'] .gs-chevron { transform: rotate(180deg); stroke: var(--accent); }
.gs-popup {
  position: fixed; inset: auto; margin: 0; z-index: 1000; box-sizing: border-box;
  display: flex; flex-direction: column; gap: 2px; padding: 6px;
  overflow-y: auto; overscroll-behavior: contain;
  background: var(--surface); color: var(--ink);
  border: 1px solid var(--border-strong); border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
  opacity: 0; transform: translateY(-6px) scale(0.97); transform-origin: 50% 0;
  transition: opacity 0.14s ease, transform 0.22s var(--spring);
}
.gs-popup[data-side='up'] { transform: translateY(6px) scale(0.97); transform-origin: 50% 100%; }
.gs-popup.is-open { opacity: 1; transform: none; }
.gs-popup.is-closing { opacity: 0; transition: opacity 0.12s ease; }
.gs-popup:focus { outline: none; }
.gs-popup:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.gs-option {
  display: flex; align-items: center; gap: 10px; min-height: var(--tap); padding: 8px 12px;
  border-radius: calc(var(--radius) - 2px); cursor: pointer; font-size: 0.92rem;
}
.gs-option[data-active] { background: var(--surface-2); }
.gs-option[aria-selected='true'] { background: var(--accent-soft); color: var(--accent); font-weight: 650; }
.gs-option[aria-disabled='true'] { opacity: 0.45; cursor: default; }
.gs-check {
  width: 18px; height: 18px; flex: none; fill: none; stroke: currentColor;
  stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round; visibility: hidden;
}
.gs-option[aria-selected='true'] .gs-check { visibility: visible; }
.gs-text { min-width: 0; overflow-wrap: anywhere; }
.gs-measure .gs-text { white-space: nowrap; }
.gs-group { padding: 8px 12px 4px; font-size: 0.72rem; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; color: var(--ink-3); }
@media (prefers-reduced-motion: reduce) {
  .gs-popup, .gs-chevron, .gs-trigger { transition: none; }
}

.switch-inline {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: 0.8rem; color: var(--ink-2); cursor: pointer;
}
/* The words first and the switch at the row's edge, where switches live. */
.switch-inline { min-height: var(--tap); flex-direction: row-reverse; }
.switch-inline input {
  appearance: none; -webkit-appearance: none; flex: none; position: relative;
  width: 42px; height: 26px; border-radius: var(--radius-pill); cursor: pointer;
  background: var(--surface-3); border: 1px solid var(--border-strong);
  transition: background 0.2s, border-color 0.2s;
}
.switch-inline input::after {
  content: ''; position: absolute; top: 2px; left: 2px;
  width: 20px; height: 20px; border-radius: 50%;
  background: var(--ink-2); box-shadow: 0 1px 2px rgba(0, 0, 0, 0.25);
  transition: transform 0.25s var(--spring), background 0.2s;
}
.switch-inline input:checked { background: var(--accent); border-color: var(--accent); }
.switch-inline input:checked::after { transform: translateX(16px); background: var(--accent-ink); }
.switch-inline input:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.segmented {
  display: inline-flex; padding: 3px; gap: 3px;
  background: var(--surface-3); border: 1px solid var(--edge);
  border-radius: var(--radius-pill); width: 100%;
}
.segmented button {
  flex: 1; min-width: 0; min-height: 36px; padding: 0 6px; border-radius: var(--radius-pill);
  font-size: 0.82rem; font-weight: 600; color: var(--ink-2); white-space: nowrap;
}
.segmented button { transition: background 0.2s, color 0.2s; }
.segmented button[aria-checked='true'], .segmented button[aria-pressed='true'] {
  background: var(--accent); color: var(--accent-ink);
}

/* The emoji picker (2.20): what is chosen, a search and the skin tone; the
   groups as tabs; a grid that scrolls on its own. GlowApp's own emojis are
   drawings in the accent here, in the habit's colour on its badge. */
.ep { display: flex; flex-direction: column; gap: 8px; }
.ep-top { display: flex; align-items: center; gap: 8px; }
.ep-current {
  flex: none; width: var(--tap); height: var(--tap); display: grid; place-items: center;
  font-size: 1.55rem; border-radius: var(--radius); background: var(--accent-soft); color: var(--accent);
}
.ep-current .glyph { width: 1.7rem; height: 1.7rem; }
.ep-search { flex: 1; min-width: 0; min-height: var(--tap); }
.ep-tone {
  flex: none; width: var(--tap); height: var(--tap); border-radius: var(--radius);
  font-size: 1.3rem; background: var(--surface-3); border: 1px solid var(--edge);
}
.ep-tone[aria-expanded='true'] { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.ep-tones { display: grid; grid-template-columns: repeat(6, 1fr); gap: 4px; padding: 4px; border-radius: var(--radius); background: var(--surface-3); }
.ep-tone-option { min-height: 40px; font-size: 1.3rem; border-radius: 10px; }
.ep-tone-option[aria-checked='true'] { background: var(--accent-soft); box-shadow: inset 0 0 0 1.5px var(--accent); }
/* All eleven always in view: in one row where they fit, in two rows of six on
   a phone (one row there left the last ones off the edge, or too narrow for
   a thumb). */
.ep-tabs {
  display: grid; grid-template-columns: repeat(11, minmax(0, 1fr)); gap: 2px;
  border-bottom: 1px solid var(--border); padding-bottom: 2px;
}
@media (max-width: 460px) {
  .ep-tabs { grid-template-columns: repeat(6, minmax(0, 1fr)); }
}
.ep-tab {
  min-width: 0; height: 38px; display: grid; place-items: center; font-size: 1.2rem;
  border-radius: 10px; color: var(--accent); opacity: 0.55; transition: opacity 0.15s, background 0.15s;
}
.ep-tab .glyph { width: 1.25rem; height: 1.25rem; }
.ep-tab[aria-selected='true'] { opacity: 1; background: var(--accent-soft); }
.ep-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(42px, 1fr)); gap: 2px;
  height: 236px; overflow-y: auto; overscroll-behavior: contain; align-content: start;
  padding: 2px; border-radius: var(--radius); background: var(--surface-3);
}
.ep-cell {
  aspect-ratio: 1; min-height: 42px; display: grid; place-items: center;
  font-size: 1.45rem; line-height: 1; border-radius: 10px; color: var(--accent);
}
.ep-cell .glyph { width: 1.5rem; height: 1.5rem; }
.ep-cell:hover { background: var(--surface); }
.ep-cell[aria-checked='true'] { background: var(--accent-soft); box-shadow: inset 0 0 0 1.5px var(--accent); }
.ep-note { font-size: 0.82rem; color: var(--ink-2); text-align: center; padding: 6px 0; }
/* A GlowApp emoji on a habit's badge: drawn in the habit's colour. */
.habit-badge.is-glyph { color: var(--habit-color); }
.habit-badge .glyph { width: 1.45rem; height: 1.45rem; }

.swatch-row { display: flex; flex-wrap: wrap; gap: 8px; }
.swatch {
  width: 34px; height: 34px; border-radius: 50%;
  border: 2px solid transparent;
}
.swatch[aria-checked='true'] {
  border-color: var(--ink);
  box-shadow: inset 0 0 0 2px var(--surface);
}

.dow-row { display: grid; grid-template-columns: repeat(7, 1fr); gap: 5px; }
.dow-btn {
  min-height: 40px; border-radius: 10px; font-size: 0.75rem; font-weight: 650;
  border: 1px solid var(--border); background: var(--surface-3); color: var(--ink-2);
}
.dow-btn[aria-pressed='true'] { background: var(--accent); color: var(--accent-ink); border-color: transparent; }

/* ── Habit rows ── */
.habit-list, .manage-list { list-style: none; display: flex; flex-direction: column; gap: 8px; }

.habit-row {
  display: flex; align-items: center; gap: 0.75rem;
  background: var(--surface); border: 1px solid var(--edge);
  border-radius: var(--radius-lg); padding: 0.75rem 0.875rem 0.75rem 1.05rem;
  box-shadow: var(--lift);
  transition: border-color 0.15s, opacity 0.15s, background 0.2s;
}
.habit-row {
  position: relative; overflow: hidden;
}
.habit-row::before {
  content: '';
  position: absolute; left: 0; top: 0; bottom: 0; width: 3px;
  background: var(--habit-color);
  opacity: 0.55;
}
.habit-row.is-off::before { opacity: 0.2; }

/* Done is stated by the edge going solid and a whisper of tint, rather than by
   the whole row shouting. */
.habit-row.is-done {
  border-color: color-mix(in srgb, var(--good) 35%, transparent);
  background: color-mix(in srgb, var(--good) 5%, var(--surface));
}
.habit-row.is-done::before { background: var(--good); opacity: 1; }
.habit-row.is-off { opacity: 0.5; }
.habit-badge {
  width: 2.5rem; height: 2.5rem; flex: none; display: grid; place-items: center;
  border-radius: var(--radius); font-size: 1.2rem;
  background: color-mix(in srgb, var(--habit-color) 18%, transparent);
}
.habit-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.habit-name { font-size: 0.94rem; font-weight: 650; }

/* A quiet mark that the row opens. It turns rather than swapping, so the
   change reads as the same object moving. */
.habit-chevron {
  display: inline-flex; align-items: center;
  margin-left: 0.3rem; color: var(--ink-3);
  transition: transform 0.2s ease, color 0.2s;
  vertical-align: middle;
}
.habit-row.is-expanded .habit-chevron { transform: rotate(180deg); color: var(--accent); }
button.habit-main:hover .habit-chevron { color: var(--accent); }
/* The name and the mark belong on one line together. */
button.habit-main .habit-name { display: inline; }

/* The row body is a button when it can expand; strip the button chrome so it
   still reads as part of the row. */
button.habit-main { text-align: left; font: inherit; color: inherit; cursor: pointer; }
button.habit-main:hover .habit-name { color: var(--accent); }

.habit-desc {
  flex-basis: 100%;
  margin-top: 0.6rem;
  padding-top: 0.6rem;
  border-top: 1px solid var(--border);
  font-size: 0.82rem; line-height: 1.5; color: var(--ink-2);
  animation: desc-in 0.18s ease-out;
}
@keyframes desc-in { from { opacity: 0; transform: translateY(-3px); } }
.habit-row.is-expanded { flex-wrap: wrap; }
.habit-meta {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  font-size: 0.73rem; color: var(--ink-2); font-variant-numeric: tabular-nums;
}
.streak { display: inline-flex; align-items: center; gap: 3px; color: var(--s2); font-weight: 650; }
.streak svg { width: 13px; height: 13px; }

.check-btn {
  width: var(--tap); height: var(--tap); flex: none; border-radius: 50%;
  border: 2px solid var(--border-strong); display: grid; place-items: center;
  color: transparent; transition: all 0.15s, transform 0.2s var(--spring);
}
.check-btn::after {
  content: ''; width: 15px; height: 9px; margin-top: -4px;
  border-left: 2.5px solid currentColor; border-bottom: 2.5px solid currentColor;
  transform: rotate(-45deg);
}
.check-btn[aria-pressed='true'] {
  background: color-mix(in srgb, var(--good) 88%, transparent);
  border-color: var(--good); color: #fff;
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--good) 16%, transparent);
}

.qty-control { display: flex; align-items: center; gap: 6px; flex: none; }
.qty-btn {
  width: 34px; height: 34px; border-radius: 50%; font-size: 1.1rem; font-weight: 600;
  background: var(--surface-3); border: 1px solid var(--border); color: var(--ink-2);
  display: grid; place-items: center; line-height: 1;
}
.qty-btn:disabled { opacity: 0.35; cursor: not-allowed; }
/* The button owns the gesture: holding it must not scroll the page or start
   a text selection. */
.qty-btn { touch-action: none; user-select: none; -webkit-user-select: none; }
.qty-btn:active { background: var(--accent-soft); border-color: var(--accent); }
.qty-value { min-width: 58px; text-align: center; font-size: 0.8rem; font-variant-numeric: tabular-nums; }
.qty-value strong { font-size: 1rem; }

.progress-track {
  height: 4px; border-radius: 999px; background: var(--surface-3); overflow: hidden; margin-top: 5px;
}
.progress-fill { height: 100%; border-radius: 999px; background: var(--habit-color); transition: width 0.3s ease; }

/* ── Manage list ── */
.manage-row {
  display: flex; align-items: center; gap: 0.75rem;
  background: var(--surface); border: 1px solid var(--edge);
  border-radius: var(--radius-lg); padding: 0.75rem 0.875rem;
  box-shadow: var(--lift);
  touch-action: pan-y;                      /* lets a vertical drag start a reorder */
  transition: transform 0.12s, opacity 0.12s, box-shadow 0.12s;
}

/* ── Drag to reorder ── */
.manage-row.is-dragging {
  opacity: 0.9; box-shadow: var(--shadow); border-color: var(--accent);
  position: relative; z-index: 5;
}
.manage-row.is-shifted { transform: translateY(var(--shift, 0)); }
.drag-handle {
  flex: none; width: 1.75rem; align-self: stretch; cursor: grab;
  display: grid; place-items: center; color: var(--ink-3);
  touch-action: none;                       /* the handle owns the gesture */
}
.drag-handle:active { cursor: grabbing; }
.drag-handle svg { width: 16px; height: 16px; }
/* A row in Hábitos is its name (2.21); the rest is behind its "more" button. */
.manage-row .habit-name { font-size: 1.02rem; }
.manage-more { flex: none; min-width: var(--tap); height: var(--tap); color: var(--ink-2); }

/* A habit's actions (2.21): a short sheet of large rows. */
.action-sheet .sheet-head { gap: 12px; }
.action-sheet .sheet-head h2 { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.action-list { display: flex; flex-direction: column; gap: 2px; padding: 6px 12px calc(14px + var(--safe-b)); }
.action-item {
  display: flex; align-items: center; gap: 14px; width: 100%; min-height: 52px; padding: 0 14px;
  border-radius: var(--radius); font-size: 1rem; font-weight: 600; color: var(--ink); text-align: left;
}
.action-item svg { flex: none; color: var(--ink-2); }
.action-item:hover, .action-item:focus-visible { background: var(--surface-3); }
.action-item:disabled { opacity: 0.4; }
.action-item.is-danger, .action-item.is-danger svg { color: var(--danger); }
.archive summary {
  cursor: pointer; padding: 10px 2px; font-size: 0.85rem;
  font-weight: 600; color: var(--ink-2);
}
.archive .manage-list { margin-top: 8px; }
.archive .manage-row { opacity: 0.7; }

.empty-state {
  text-align: center; padding: 26px 16px;
  background: var(--surface); border: 1px dashed var(--border-strong);
  border-radius: var(--radius-lg);
  display: flex; flex-direction: column; align-items: center; gap: 10px;
}
.preset-grid { display: flex; flex-wrap: wrap; gap: 8px; justify-content: center; margin-top: 6px; }
.preset-chip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 8px 13px; border-radius: var(--radius-pill);
  background: var(--surface-3); border: 1px solid var(--border);
  font-size: 0.82rem; font-weight: 600;
}
.preset-chip:hover { border-color: var(--accent); }

/* ── Progress view ── */
.filter-row { display: flex; gap: 10px; align-items: center; }
.stat-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px; }
@media (min-width: 520px) { .stat-grid { grid-template-columns: repeat(4, 1fr); } }
.stat-grid .stat-tile {
  background: var(--surface); border: 1px solid var(--edge); padding: 13px 14px; gap: 3px;
  border-radius: var(--radius-lg); box-shadow: var(--lift);
}
.stat-grid .stat-value { font-size: 1.55rem; font-weight: 800; letter-spacing: -0.02em; }
.stat-grid .stat-label { font-size: 0.72rem; }

.chart-card { display: flex; flex-direction: column; gap: 12px; }
.chart-card figcaption { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.chart-card figcaption .field { flex: none; }
.chart-card select { min-height: 36px; padding: 6px 30px 6px 10px; font-size: 0.82rem; background-position: calc(100% - 17px) 16px, calc(100% - 12px) 16px; }
.chart-card .gs-trigger { min-height: 36px; padding: 6px 10px; gap: 6px; font-size: 0.82rem; }
.chart-card .gs-chevron { width: 16px; height: 16px; }
.chart-sub { font-size: 0.75rem; color: var(--ink-2); }
.chart-empty { font-size: 0.85rem; color: var(--ink-2); padding: 18px 0; text-align: center; }
.chart-host { position: relative; }
.chart-host svg { display: block; width: 100%; height: auto; overflow: visible; }

.viz-grid { stroke: var(--grid); stroke-width: 1; }
.viz-axis { stroke: var(--axis); stroke-width: 1; }
.viz-tick { fill: var(--muted-ink); font-size: 10px; font-variant-numeric: tabular-nums; }
.viz-label { fill: var(--ink); font-size: 11px; font-weight: 600; }
.viz-value { fill: var(--ink-2); font-size: 11px; font-variant-numeric: tabular-nums; }
.viz-line { fill: none; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.viz-area { fill-opacity: 0.1; stroke: none; }
.viz-dot { stroke: var(--surface); stroke-width: 2; }
.viz-bar { rx: 4; }
.viz-cell { rx: 3; stroke: var(--surface); stroke-width: 1.5; }
.viz-cell.is-hit { cursor: pointer; }
.viz-crosshair { stroke: var(--border-strong); stroke-width: 1; stroke-dasharray: 3 3; }
.viz-ref { stroke: var(--good); stroke-width: 1.5; stroke-dasharray: 6 4; opacity: 0.85; }

.viz-legend {
  display: flex; flex-wrap: wrap; gap: 6px 16px; align-items: center;
  font-size: 0.75rem; color: var(--ink-2);
}
.viz-legend span { display: inline-flex; align-items: center; gap: 6px; }
.viz-legend i { width: 10px; height: 10px; border-radius: 3px; display: block; }
.viz-scale { display: flex; align-items: center; gap: 4px; font-size: 0.7rem; color: var(--ink-3); }
.viz-scale i { width: 12px; height: 12px; border-radius: 3px; display: block; }

.viz-tip {
  position: absolute; z-index: 10; pointer-events: none;
  background: var(--surface-2); border: 1px solid var(--border-strong);
  border-radius: 10px; box-shadow: var(--shadow);
  padding: 7px 10px; font-size: 0.76rem; line-height: 1.35;
  white-space: nowrap; transform: translate(-50%, -110%); opacity: 0;
  transition: opacity 0.1s;
}
.viz-tip.is-on { opacity: 1; }
.viz-tip b { font-weight: 650; }
.viz-tip .tip-sub { color: var(--ink-2); }

/* ══ Excellence (2.20) ══════════════════════════════════════════════
   The habit nobody ticks. Its colour is each palette's amber (s4, already
   validated against every palette's surfaces), its emblem a laurel around
   a spark; lit, it glows, and more as its light (its grade) grows. Text
   never wears the amber: the laurel and the marks carry it. */
:root {
  --virtue: var(--s4);
  --virtue-soft: color-mix(in srgb, var(--s4) 26%, var(--surface-3));
  --virtue-glow: color-mix(in srgb, var(--s4) 45%, transparent);
  --virtue-ink: color-mix(in srgb, var(--s4) 22%, #000000);
}

.excellence-row {
  display: flex; align-items: center; gap: 0.75rem; width: 100%;
  margin-bottom: 8px; padding: 0.75rem 0.875rem 0.75rem 1.05rem;
  background: var(--surface); color: var(--ink); text-align: left;
  border: 1px solid var(--edge); border-radius: var(--radius-lg); box-shadow: var(--lift);
  transition: border-color 0.3s, box-shadow 0.3s, background 0.3s;
}
.excellence-emblem {
  width: 2.5rem; height: 2.5rem; flex: none; display: grid; place-items: center;
  border-radius: var(--radius); color: var(--ink-3); background: var(--surface-3);
  transition: color 0.3s, background 0.3s;
}
.excellence-emblem svg { width: 1.65rem; height: 1.65rem; }
.excellence-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.excellence-name { display: flex; align-items: center; gap: 7px; font-size: 0.94rem; font-weight: 700; }
.excellence-status { font-size: 0.75rem; color: var(--ink-2); }
.excellence-new {
  font-size: 0.62rem; font-weight: 750; letter-spacing: 0.02em; text-transform: uppercase;
  padding: 2px 7px; border-radius: var(--radius-pill); background: var(--virtue-soft); color: var(--ink);
}
.excellence-medal { flex: none; width: var(--tap); height: var(--tap); display: grid; place-items: center; }
.excellence-medal svg { width: 40px; height: 40px; overflow: visible; }
.vm-track { fill: none; stroke: var(--surface-3); stroke-width: 3.5; }
.vm-fill { fill: none; stroke: var(--virtue); stroke-width: 3.5; stroke-linecap: round; transition: stroke-dashoffset 0.5s ease; }
.vm-lit { fill: var(--virtue); }
.vm-check { fill: none; stroke: var(--virtue-ink); stroke-width: 3.4; stroke-linecap: round; stroke-linejoin: round; }

.excellence-row.is-lit {
  border-color: color-mix(in srgb, var(--virtue) 55%, transparent);
  background: linear-gradient(105deg, color-mix(in srgb, var(--virtue) 11%, var(--surface)), var(--surface) 62%);
  box-shadow: var(--lift), 0 8px 24px -12px var(--virtue-glow);
}
.excellence-row.is-lit .excellence-emblem,
.excellence-sheet .sheet-title .excellence-emblem {
  color: var(--virtue); background: color-mix(in srgb, var(--virtue) 15%, transparent);
}
.excellence-row.is-lit .excellence-medal svg { filter: drop-shadow(0 0 6px var(--virtue-glow)); }

/* The app's own mark glows on a day of excellence: GlowApp, living up to its name. */
body.is-excellent .app-mark {
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--virtue) 70%, transparent), 0 0 14px var(--virtue-glow);
}
/* And a day of excellence wears a golden dot in the week strip. */
.day-chip .ddot.virtue,
.day-chip[aria-selected='true'] .ddot.virtue { background: var(--virtue); box-shadow: 0 0 5px var(--virtue-glow); }

@media (prefers-reduced-motion: no-preference) {
  .excellence-row.is-lit .excellence-emblem svg { animation: virtue-breathe 3.4s ease-in-out infinite; }
  .excellence-row.just-lit { animation: virtue-lit 1.3s ease-out; }
  body.is-excellent .app-mark { animation: virtue-mark 3.4s ease-in-out infinite; }
}
@keyframes virtue-breathe { 50% { transform: scale(1.06); filter: drop-shadow(0 0 4px var(--virtue-glow)); } }
@keyframes virtue-lit {
  0% { box-shadow: var(--lift), 0 0 0 0 var(--virtue-glow); transform: scale(1); }
  30% { box-shadow: var(--lift), 0 0 0 8px transparent; transform: scale(1.015); }
  100% { box-shadow: var(--lift), 0 8px 24px -12px var(--virtue-glow); transform: scale(1); }
}
@keyframes virtue-mark { 50% { box-shadow: 0 0 0 2px color-mix(in srgb, var(--virtue) 70%, transparent), 0 0 20px var(--virtue-glow); } }

/* The whole screen's one soft glow when the day reaches excellence (2.21):
   under Pico and the tab bar, never taking a touch. */
.virtue-glow {
  position: fixed; inset: 0; z-index: 58; pointer-events: none; opacity: 0;
  background: radial-gradient(ellipse at 50% 38%, color-mix(in srgb, var(--virtue) 34%, transparent),
    color-mix(in srgb, var(--virtue) 12%, transparent) 55%, transparent 82%);
}
.virtue-glow.is-on { animation: virtue-glow 1.5s ease-out both; }
@keyframes virtue-glow { 0% { opacity: 0; } 22% { opacity: 1; } 100% { opacity: 0; } }

/* The sheet: the medal, more light as the grade rises. */
.virtue-hero { display: flex; flex-direction: column; align-items: center; text-align: center; gap: 3px; padding: 4px 0 2px; }
.virtue-medal {
  width: 5.6rem; height: 5.6rem; margin-bottom: 8px; display: grid; place-items: center;
  border-radius: 50%; color: var(--ink-3); background: var(--surface-3);
  transition: box-shadow 0.4s, background 0.4s;
}
.virtue-medal svg { width: 3.4rem; height: 3.4rem; }
.excellence-sheet:not([data-grade='none']) .virtue-medal {
  color: var(--virtue);
  background: radial-gradient(circle, color-mix(in srgb, var(--virtue) 20%, var(--surface)) 0%, var(--surface-3) 72%);
}
.excellence-sheet[data-grade='spark'] .virtue-medal svg { filter: drop-shadow(0 0 2px var(--virtue-glow)); }
.excellence-sheet[data-grade='flame'] .virtue-medal svg { filter: drop-shadow(0 0 5px var(--virtue-glow)); }
.excellence-sheet[data-grade='light'] .virtue-medal { box-shadow: 0 0 22px -4px var(--virtue-glow); }
.excellence-sheet[data-grade='light'] .virtue-medal svg { filter: drop-shadow(0 0 8px var(--virtue-glow)); }
.excellence-sheet[data-grade='radiance'] .virtue-medal { box-shadow: 0 0 0 2px color-mix(in srgb, var(--virtue) 55%, transparent), 0 0 34px var(--virtue-glow); }
.excellence-sheet[data-grade='radiance'] .virtue-medal svg { filter: drop-shadow(0 0 12px var(--virtue-glow)); }
.virtue-grade { font-size: 1.4rem; font-weight: 800; letter-spacing: -0.015em; }
.virtue-streak { font-size: 0.86rem; color: var(--ink-2); }
.virtue-today {
  margin-top: 8px; padding: 6px 14px; border-radius: var(--radius-pill);
  background: var(--surface-3); font-size: 0.82rem; font-weight: 600;
}
.virtue-week { display: flex; flex-direction: column; gap: 8px; margin: 0; }
.virtue-stats { grid-template-columns: repeat(3, 1fr); }
.virtue-maxim {
  margin: 0; padding: 12px 14px; border-left: 3px solid var(--virtue);
  background: color-mix(in srgb, var(--virtue) 7%, transparent); border-radius: 0 var(--radius) var(--radius) 0;
}
.virtue-maxim p { font-size: 0.92rem; font-style: italic; line-height: 1.45; }
.virtue-maxim cite { display: block; margin-top: 6px; font-size: 0.75rem; font-style: normal; color: var(--ink-2); }
.virtue-rule { display: flex; flex-direction: column; gap: 6px; }
.virtue-rule p { font-size: 0.82rem; line-height: 1.5; color: var(--ink-2); }
.virtue-grades { list-style: none; display: grid; grid-template-columns: repeat(4, 1fr); gap: 6px; margin: 8px 0 6px; }
.virtue-step {
  display: flex; flex-direction: column; align-items: center; gap: 2px; padding: 8px 4px;
  border-radius: var(--radius); background: var(--surface-3); text-align: center; opacity: 0.62;
}
.virtue-step strong { font-size: 0.8rem; font-weight: 700; }
.virtue-step span { font-size: 0.66rem; color: var(--ink-2); }
.virtue-step.is-reached { opacity: 1; }
.virtue-step.is-now { opacity: 1; background: var(--virtue-soft); box-shadow: inset 0 0 0 1.5px var(--virtue); }
.viz-goal { stroke: var(--ink-3); stroke-width: 1.2; stroke-dasharray: 4 4; }

/* Level and achievements (2.19): a number, a thin meter, and the badges a
   tap away. The meter's track is a lighter step of its own fill. */
.level-card { display: flex; flex-direction: column; gap: 10px; }
.level-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.level-head h3 { font-size: 1.2rem; font-weight: 800; letter-spacing: -0.015em; }
.level-points { font-size: 0.8rem; color: var(--ink-2); }
.level-track { height: 8px; border-radius: var(--radius-pill); background: var(--accent-soft); overflow: hidden; }
.level-track span {
  display: block; height: 100%; width: 0; border-radius: inherit; background: var(--accent);
  transition: width 0.7s var(--spring);
}
.level-foot { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: -6px; }
.level-next { font-size: 0.78rem; color: var(--ink-2); }
.level-badges { margin-right: -10px; color: var(--accent); }
.level-badges svg { transform: rotate(-90deg); }

.achievement-list { list-style: none; display: flex; flex-direction: column; gap: 6px; }
.achievement {
  display: flex; align-items: center; gap: 12px;
  padding: 10px 12px; border-radius: var(--radius); background: var(--surface-3);
}
.achievement-icon {
  width: 2.4rem; height: 2.4rem; flex: none; display: grid; place-items: center;
  border-radius: 50%; background: var(--surface); font-size: 1.2rem;
  filter: grayscale(1); opacity: 0.45;
}
.achievement.is-got .achievement-icon { filter: none; opacity: 1; background: var(--accent-soft); }
.achievement-text { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.achievement-text strong { font-size: 0.9rem; font-weight: 700; }
.achievement-text span { font-size: 0.78rem; color: var(--ink-2); }
.achievement:not(.is-got) .achievement-text strong { color: var(--ink-2); }
.achievement-state { flex: none; font-size: 0.78rem; color: var(--ink-3); font-variant-numeric: tabular-nums; }
.achievement.is-got .achievement-state { color: var(--good); display: grid; }

/* More charts (2.19): one quiet button, and the charts it opens below it. */
.more-charts-btn { width: 100%; justify-content: space-between; scroll-margin-top: 72px; }
.more-charts-btn svg { transition: transform 0.25s var(--spring); }
.more-charts-btn[aria-expanded='true'] svg { transform: rotate(180deg); }
.more-charts { display: flex; flex-direction: column; gap: 1.125rem; }
.more-charts:not([hidden]) { animation: view-in 0.24s ease-out both; }

.table-card summary { cursor: pointer; font-size: 0.85rem; font-weight: 600; color: var(--ink-2); }
.table-scroll { overflow-x: auto; margin-top: 12px; }
table { border-collapse: collapse; width: 100%; font-size: 0.8rem; }
th, td { text-align: left; padding: 7px 10px; border-bottom: 1px solid var(--border); white-space: nowrap; }
th { color: var(--ink-2); font-weight: 600; }
td { font-variant-numeric: tabular-nums; }

/* ── Settings ── */
.setting-group { display: flex; flex-direction: column; gap: 12px; }
.data-block { display: flex; flex-direction: column; gap: 8px; padding-top: 12px; border-top: 1px solid var(--border); }
.data-block h4 { font-size: 0.88rem; font-weight: 650; }
/* A control too wide to sit beside its label (Grande on a narrow phone,
   2.21) goes under it, at the full width. */
.setting-row { display: flex; align-items: center; justify-content: space-between; gap: 8px 14px; flex-wrap: wrap; }
.setting-row:not(.setting-row-stack) > :last-child { margin-left: auto; }
.setting-row label { font-size: 0.88rem; }
.setting-row select { width: auto; min-width: 140px; }
.setting-row .gs-trigger { width: auto; min-width: 140px; font-size: 0.9rem; }

/* ── Dialogs ── */
.sheet {
  width: min(520px, 100%); max-height: 92dvh; padding: 0; border: none;
  background: var(--surface); color: var(--ink);
  border-radius: 24px 24px 0 0;
  margin: auto auto 0; box-shadow: var(--shadow);
}
@media (min-width: 560px) { .sheet { margin: auto; border-radius: 24px; } }
.sheet::backdrop { background: rgba(0, 0, 0, 0.55); backdrop-filter: blur(2px); }
.sheet form { display: flex; flex-direction: column; max-height: 92dvh; }
.sheet-head {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 16px; border-bottom: 1px solid var(--border);
}
.sheet-head h2 { font-size: 1.05rem; }
/* A sheet without a form scrolls as a whole: its head stays put (2.20). */
dialog.sheet > .sheet-head { position: sticky; top: 0; z-index: 2; background: var(--surface); }
.sheet-title { display: flex; align-items: center; gap: 10px; min-width: 0; }
/* Pico beside "Nuevo hábito" (2.16), standing on the header's lower edge. */
.sheet-pico { width: 2.6rem; height: 2.6rem; flex: none; margin: -8px 0 -10px -4px; }
.sheet-body { padding: 16px; overflow-y: auto; display: flex; flex-direction: column; gap: 14px; }
.sheet-foot {
  display: flex; align-items: center; gap: 8px;
  padding: 12px 16px calc(12px + var(--safe-b));
  border-top: 1px solid var(--border);
}
.confirm .sheet-body h2 { font-size: 1.05rem; }
.form-error { color: var(--danger); font-size: 0.82rem; }

.toast {
  position: fixed; left: 50%; bottom: calc(78px + var(--safe-b)); z-index: 90;
  transform: translateX(-50%);
  background: var(--surface-2); color: var(--ink);
  border: 1px solid var(--border-strong); border-radius: var(--radius-pill);
  padding: 10px 18px; font-size: 0.84rem; font-weight: 600;
  box-shadow: var(--shadow); animation: toast-in 0.18s ease;
  /* As wide as its words, up to the screen: at left 50% the browser would
     otherwise wrap it at half the screen's width. */
  width: max-content; max-width: calc(100vw - 32px); text-align: center;
}
@keyframes toast-in { from { opacity: 0; transform: translate(-50%, 8px); } }

/* ══ Launch screen ══════════════════════════════════════════════════
   Quick by design: the mark springs in, the check draws itself, the phrase
   lands, and the whole thing is gone in well under two seconds. Uses the
   same palette as the app so the handover is invisible. */
.splash {
  position: fixed; inset: 0; z-index: 999;
  display: grid; place-items: center;
  background: var(--bg);
  transition: opacity 0.32s ease;
}
.splash.is-leaving { opacity: 0; pointer-events: none; }

/* The app behind the splash is taller than the window, so the scroll bar was
   drawing down the right-hand edge of the launch screen. Lock the page while
   it plays: the bar goes, and the app cannot be scrolled underneath either. */
:root.is-splashing,
:root.is-splashing body {
  overflow: hidden;
  scrollbar-width: none;
}
:root.is-splashing::-webkit-scrollbar,
:root.is-splashing body::-webkit-scrollbar { display: none; }

/* The mark is the screen's centre, as in Android's launch screen, which shows
   the same mark first (2.29); the name and the phrase hang under it. */
.splash-inner { position: relative; display: flex; flex-direction: column; align-items: center; }
.splash-words {
  position: absolute; top: calc(100% + 14px); left: 50%; width: 100vw; margin-left: -50vw;
  display: flex; flex-direction: column; align-items: center; gap: 14px;
}

.splash-mark {
  width: 96px; height: 96px;
  animation: splash-pop 0.5s cubic-bezier(0.34, 1.56, 0.64, 1) both;
  filter: drop-shadow(0 10px 24px rgba(22, 169, 123, 0.28));
}
@keyframes splash-pop {
  0%   { transform: scale(0.55) rotate(-8deg); opacity: 0; }
  100% { transform: scale(1) rotate(0deg); opacity: 1; }
}

/* The check is drawn on rather than simply appearing. */
.splash-check {
  stroke-dasharray: 78;
  stroke-dashoffset: 78;
  animation: splash-draw 0.42s ease-out 0.26s both;
}
@keyframes splash-draw { to { stroke-dashoffset: 0; } }

.splash-name {
  font-size: 1.35rem; font-weight: 700; letter-spacing: -0.02em; color: var(--ink);
  animation: splash-rise 0.42s ease-out 0.34s both;
}
.splash-phrase {
  max-width: 20rem; padding: 0 1.5rem; text-align: center;
  font-size: 0.92rem; line-height: 1.45; color: var(--ink-2);
  animation: splash-rise 0.46s ease-out 0.6s both;
}
@keyframes splash-rise {
  from { opacity: 0; transform: translateY(9px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* The check's drawing runs on the main thread, which the app's start keeps
   busy for a moment: it waits for the start (.splash-go, set by app.js), so
   it plays smoothly instead of stalling halfway (2.29). The rest of the
   splash is transform and opacity, which the compositor runs regardless. */
.splash-check { animation-play-state: paused; }
:root.splash-go .splash-check { animation-play-state: running; }

/* In the Android app (2.29) Android's launch screen has already shown the
   mark, drawn: it stays as it is, and the words come in once the app has
   started, as Android's screen fades out over it. */
:root[data-shell] .splash-inner { transform: translateY(calc(-1 * var(--launch-shift, 0px))); }
:root[data-shell] .splash-mark { filter: none; }   /* Android's mark has no shadow */
:root[data-shell] .splash-mark,
:root[data-shell] .splash-check { animation: none; }
:root[data-shell] .splash-check { stroke-dashoffset: 0; }
:root[data-shell] .splash-name,
:root[data-shell] .splash-phrase { animation-play-state: paused; animation-delay: 0.08s; }
:root[data-shell] .splash-phrase { animation-delay: 0.3s; }
:root[data-shell].splash-go .splash-name,
:root[data-shell].splash-go .splash-phrase { animation-play-state: running; }

/* Reduced motion keeps the screen but drops the movement. */
@media (prefers-reduced-motion: reduce) {
  .splash-mark, .splash-name, .splash-phrase { animation: none; opacity: 1; }
  .splash-check { stroke-dashoffset: 0; animation: none; }
}

/* ── Settings rows that need a full-width control ── */
.setting-row-stack { flex-direction: column; align-items: stretch; gap: 8px; }
.setting-row-stack label { color: var(--ink-2); font-size: 0.82rem; font-weight: 600; }
.segmented-wrap { flex-wrap: wrap; border-radius: 20px; }
.segmented-wrap button { flex: 1 1 40%; border-radius: 16px; }

/* ══ Starting test ══════════════════════════════════════════════════
   Laid out as a full-height column rather than a centred card: the header
   sits near the top, the options take the room that is left, and the
   buttons stay pinned at the bottom where a thumb can reach them. That is
   what removes the big empty band the centred version left above. */
.onboarding {
  position: fixed; inset: 0; z-index: 900;
  display: flex; flex-direction: column;
  background: var(--bg);
}
.ob-panel {
  flex: 1; min-height: 0;                    /* lets the body scroll, not the panel */
  width: 100%; max-width: 30rem; margin: 0 auto;
  display: flex; flex-direction: column;
  padding: calc(1.25rem + env(safe-area-inset-top, 0px)) 1.25rem
           calc(1rem + var(--safe-b));
  animation: ob-in 0.28s ease-out both;
}
@keyframes ob-in { from { opacity: 0; transform: translateY(8px); } }

/* One pip per step, filled as you advance. */
.ob-progress { display: flex; gap: 5px; flex: none; }
.ob-pip {
  height: 3px; flex: 1; border-radius: 999px; background: var(--surface-3);
  transition: background 0.25s;
}
.ob-pip.is-done { background: var(--accent); }

.ob-body {
  flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain;
  display: flex; flex-direction: column; gap: 0.6rem;
  padding-top: 1.5rem;
  /* Space so the last option never hides under the buttons. */
  padding-bottom: 0.5rem;
  scrollbar-width: none;
}
.ob-body::-webkit-scrollbar { display: none; }

.ob-step {
  font-size: 0.72rem; font-weight: 650; color: var(--accent);
  letter-spacing: 0.06em; text-transform: uppercase;
}
.ob-question {
  font-size: 1.45rem; font-weight: 700; letter-spacing: -0.025em; line-height: 1.2;
  text-wrap: balance;
}
.ob-hint { font-size: 0.86rem; line-height: 1.45; color: var(--ink-2); }

.ob-options { display: flex; flex-direction: column; gap: 7px; margin-top: 0.4rem; }
.ob-option {
  display: flex; align-items: center; gap: 0.75rem; width: 100%;
  min-height: var(--tap); padding: 0.7rem 0.9rem; text-align: left;
  background: var(--surface); color: var(--ink);
  border: 1px solid var(--border); border-radius: var(--radius);
  font-size: 0.92rem; font-weight: 550;
  transition: border-color 0.14s, background 0.14s, transform 0.1s;
}
.ob-option:hover { border-color: var(--border-strong); }
.ob-option:active { transform: scale(0.99); }
.ob-option[aria-pressed='true'], .ob-option[aria-checked='true'] {
  border-color: var(--accent); background: var(--accent-soft);
}
.ob-option .ob-emoji { font-size: 1.15rem; flex: none; }
.ob-option .ob-label { flex: 1; min-width: 0; }
.ob-option .ob-meta { font-size: 0.76rem; color: var(--ink-2); }
/* The tick keeps its slot at all times, so selecting never shifts the text. */
.ob-option .ob-tick {
  flex: none; width: 1.25rem; text-align: center; color: var(--accent);
  font-weight: 700; opacity: 0; transition: opacity 0.14s;
}
.ob-option[aria-pressed='true'] .ob-tick,
.ob-option[aria-checked='true'] .ob-tick { opacity: 1; }

.ob-foot {
  flex: none; display: flex; align-items: center; gap: 8px;
  padding-top: 0.9rem;
  border-top: 1px solid var(--border);
}
.ob-foot .btn { flex: 1; }
.ob-foot .btn-ghost { flex: 0 0 auto; background: none; border-color: transparent; color: var(--ink-2); }
.ob-error { color: var(--danger); font-size: 0.82rem; }

/* Results */
.ob-group-title {
  font-size: 0.72rem; font-weight: 650; color: var(--ink-3);
  letter-spacing: 0.04em; text-transform: uppercase;
  margin-top: 0.6rem;
}
.ob-suggestions { display: flex; flex-direction: column; gap: 7px; }

/* Short screens: tighten the rhythm rather than let the footer be pushed off. */
@media (max-height: 680px) {
  .ob-panel { padding-top: calc(0.9rem + env(safe-area-inset-top, 0px)); }
  .ob-body { padding-top: 1rem; gap: 0.5rem; }
  .ob-question { font-size: 1.25rem; }
}

/* ══ Today layouts ══════════════════════════════════════════════════
   Each block restyles only the Today view. Comfortable is the default
   and needs no block of its own. */

/* ── Compact: one line per habit, mood condensed ── */
[data-layout='compact'] #view-today .view-inner { gap: 0.75rem; }
[data-layout='compact'] .summary-card { padding: 0.75rem; gap: 0.75rem; }
[data-layout='compact'] .summary-ring svg { width: 4.25rem; height: 4.25rem; }
[data-layout='compact'] .summary-ring-label strong { font-size: 1.05rem; }
[data-layout='compact'] .summary-ring-label span { display: none; }
[data-layout='compact'] .summary-date { margin-bottom: 6px; font-size: 0.75rem; }
[data-layout='compact'] .mood-card .card-head h3 { font-size: 0.85rem; }
[data-layout='compact'] .mood-btn {
  flex-direction: row; justify-content: center; gap: 0; padding: 0.4rem 0.125rem;
}
[data-layout='compact'] .mood-btn span:not(.emoji) { display: none; }
[data-layout='compact'] .mood-btn .emoji { font-size: 1.25rem; }
[data-layout='compact'] .habit-list { gap: 5px; }
[data-layout='compact'] .habit-row { padding: 0.4rem 0.625rem; gap: 0.5rem; border-radius: var(--radius); }
[data-layout='compact'] .habit-badge {
  width: 1.75rem; height: 1.75rem; font-size: 0.95rem; border-radius: 9px;
}
[data-layout='compact'] .habit-main { flex-direction: row; align-items: center; gap: 0.5rem; }
[data-layout='compact'] .habit-name { flex: 1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
[data-layout='compact'] .habit-meta { flex: none; }
[data-layout='compact'] .habit-meta .sched { display: none; }   /* schedule is implied by the day */
[data-layout='compact'] .progress-track { display: none; }
[data-layout='compact'] .check-btn { width: 2rem; height: 2rem; border-width: 2px; }
[data-layout='compact'] .check-btn::after { width: 11px; height: 6px; }
[data-layout='compact'] .qty-btn { width: 1.9rem; height: 1.9rem; }
[data-layout='compact'] .qty-value { min-width: 3.1rem; font-size: 0.72rem; }

/* ── Grid: two columns of tiles ── */
[data-layout='grid'] .habit-list {
  display: grid; grid-template-columns: repeat(2, 1fr); gap: 0.625rem;
}
[data-layout='grid'] .habit-row {
  flex-direction: column; align-items: center; text-align: center;
  gap: 0.5rem; padding: 0.875rem 0.625rem;
}
[data-layout='grid'] .habit-badge { width: 3rem; height: 3rem; font-size: 1.5rem; }
[data-layout='grid'] .habit-main { align-items: center; width: 100%; }
[data-layout='grid'] .habit-name { text-align: center; }
[data-layout='grid'] .habit-meta { justify-content: center; }
[data-layout='grid'] .habit-meta .sched { display: none; }
[data-layout='grid'] .qty-control { width: 100%; justify-content: center; }
@media (min-width: 560px) {
  [data-layout='grid'] .habit-list { grid-template-columns: repeat(3, 1fr); }
}

/* ── Focus: one roomy card per habit, chrome tucked away ── */
[data-layout='focus'] .summary-card { flex-direction: column; text-align: center; gap: 0.5rem; }
[data-layout='focus'] .summary-ring svg { width: 5rem; height: 5rem; }
[data-layout='focus'] .summary-stats { width: 100%; }
[data-layout='focus'] .summary-date { text-align: center; }
[data-layout='focus'] .stat-row { max-width: 320px; margin: 0 auto; }
[data-layout='focus'] .mood-card { padding: 0.75rem 1rem; }
[data-layout='focus'] .mood-card .card-head h3 { font-size: 0.85rem; }
[data-layout='focus'] .mood-scale { margin-top: 8px; }
[data-layout='focus'] .mood-btn {
  flex-direction: row; justify-content: center; gap: 0; padding: 0.4rem 0.125rem;
}
[data-layout='focus'] .mood-btn span:not(.emoji) { display: none; }
[data-layout='focus'] .habit-list { gap: 0.75rem; }
[data-layout='focus'] .habit-row { padding: 1.25rem 1.125rem; gap: 1rem; }
[data-layout='focus'] .habit-badge { width: 3rem; height: 3rem; font-size: 1.45rem; }
[data-layout='focus'] .habit-name { font-size: 1.05rem; }
[data-layout='focus'] .check-btn { width: 3rem; height: 3rem; }
[data-layout='focus'] .check-btn::after { width: 18px; height: 11px; }

/* ── Completion feedback ── */
@keyframes check-pop {
  0% { transform: scale(1); }
  45% { transform: scale(1.22); }
  100% { transform: scale(1); }
}
.check-btn.just-done { animation: check-pop 0.32s ease-out; }

@keyframes row-flash {
  0% { background: var(--surface); }
  35% { background: color-mix(in srgb, var(--good) 16%, var(--surface)); }
  100% { background: var(--surface); }
}
.habit-row.just-done { animation: row-flash 0.6s ease-out; }

@keyframes ring-celebrate {
  0% { transform: rotate(-90deg) scale(1); }
  40% { transform: rotate(-90deg) scale(1.06); }
  100% { transform: rotate(-90deg) scale(1); }
}
.summary-ring.celebrate svg { animation: ring-celebrate 0.7s ease-out; }
.summary-ring.celebrate .ring-value { stroke: var(--good); }

/* Sparks from a ticked circle — the shiny things Pico collects. Small
   diamonds in the palette's good and accent colours, flung out and gone in
   well under a second. */
.spark-burst { position: fixed; z-index: 96; width: 0; height: 0; pointer-events: none; }
.spark-burst i {
  position: absolute; left: -3.5px; top: -3.5px; width: 7px; height: 7px; border-radius: 1.5px;
  background: var(--good); opacity: 0;
  animation: spark-fly 0.66s cubic-bezier(0.2, 0.75, 0.3, 1) both;
}
.spark-burst i:nth-child(even) { left: -2.5px; top: -2.5px; width: 5px; height: 5px; background: var(--accent); }
/* Born at the circle's edge, full size, and fading as they slow. */
@keyframes spark-fly {
  0% { opacity: 0; transform: rotate(var(--a)) translateX(var(--r0, 20px)) rotate(45deg) scale(0.7); }
  14% { opacity: 1; }
  70% { opacity: 1; transform: rotate(var(--a)) translateX(calc(var(--d) * 0.86)) rotate(45deg) scale(1); }
  100% { opacity: 0; transform: rotate(var(--a)) translateX(var(--d)) rotate(45deg) scale(0.35); }
}

/* A tab eases in rather than snapping (opacity only: a transform here would
   become the containing block of anything fixed inside the view). */
.view.view-enter { animation: view-in 0.24s ease-out both; }
@keyframes view-in { from { opacity: 0; } }

/* Pico keeps an empty list company. */
.empty-pico { width: 4.2rem; height: 4.2rem; margin: 0 auto -2px; }

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

/* ══ Reminder cast ══════════════════════════════════════════════════
   Characters who send the reminders as chat messages. Each one brings an
   accent colour (--cast) that tints their bubbles, buttons and card. */

/* ── App-bar button with the unread count ── */
.chat-btn { position: relative; }
.chat-badge {
  position: absolute; top: 2px; right: 1px;
  min-width: 17px; height: 17px; padding: 0 4px; border-radius: 999px;
  background: var(--danger); color: #fff;
  font-size: 0.62rem; font-weight: 700; line-height: 17px; text-align: center;
  box-shadow: 0 0 0 2px var(--bg);
}

/* ── Today's one-time introduction ── */
.cast-promo {
  display: flex; align-items: center; gap: 0.9rem;
  background: linear-gradient(135deg, color-mix(in srgb, var(--s7) 15%, var(--surface)), var(--surface) 72%);
}
.cast-promo-faces { display: flex; flex: none; }
.cast-promo-faces img {
  width: 2.4rem; height: 2.4rem; border-radius: 50%;
  border: 2px solid var(--surface); background: var(--surface);
}
.cast-promo-faces img + img { margin-left: -0.85rem; }
.cast-promo-text { min-width: 0; }
.cast-promo h3 { margin-bottom: 3px; }
.cast-promo p { font-size: 0.82rem; line-height: 1.45; color: var(--ink-2); }
.cast-promo .button-row { margin-top: 10px; }
@media (max-width: 380px) {
  .cast-promo { flex-direction: column; align-items: flex-start; }
}

/* ── Picker ── */
.cast-list { display: flex; flex-direction: column; gap: 8px; }
.cast-card {
  display: flex; align-items: center; gap: 4px;
  padding: 4px 10px 4px 4px;
  background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--radius-lg);
  transition: border-color 0.15s, background 0.15s;
}
.cast-card.is-selected {
  border-color: var(--cast, var(--accent));
  background: color-mix(in srgb, var(--cast, var(--accent)) 12%, var(--surface-2));
}
.cast-pick {
  flex: 1; min-width: 0; display: flex; align-items: center; gap: 0.8rem;
  padding: 8px; text-align: left; border-radius: var(--radius);
}
.cast-avatar { width: 3.3rem; height: 3.3rem; flex: none; border-radius: 50%; }
.cast-avatar-none { display: grid; place-items: center; background: var(--surface-3); color: var(--ink-2); }
.cast-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.cast-text strong { font-size: 0.95rem; }
.cast-text span { font-size: 0.78rem; line-height: 1.35; color: var(--ink-2); }
.cast-pick[aria-checked='true'] .cast-text strong::after {
  content: ' ✓'; color: var(--cast, var(--accent));
}
.cast-listen {
  width: var(--tap); height: var(--tap); flex: none; border-radius: 50%;
  display: grid; place-items: center;
  color: var(--cast, var(--accent));
  background: color-mix(in srgb, var(--cast, var(--accent)) 15%, transparent);
  transition: background 0.15s, color 0.15s;
}
.cast-listen.is-playing { background: var(--cast, var(--accent)); color: #fff; }
/* Your own bot's card: its studio button sits under the words. */
.cast-card-bot { flex-direction: column; align-items: stretch; gap: 0; }
.cast-row { display: flex; align-items: center; gap: 4px; }
.cast-studio { align-self: flex-start; margin: 0 0 8px calc(3.3rem + 0.8rem + 8px); }

/* ── Your own bot: the studio ── */
.studio {
  --cast: #E0663A;
  width: 100%; max-width: 42rem; height: 100dvh; max-height: 100dvh;
  margin: 0 auto; padding: 0; border: none;
  background: var(--bg); color: var(--ink);
}
.studio[open] { display: flex; flex-direction: column; }
.studio::backdrop { background: var(--bg); }
.studio-head {
  flex: none; display: flex; align-items: center; gap: 8px;
  padding: calc(8px + env(safe-area-inset-top, 0px)) 12px 8px 4px;
  background: var(--surface); border-bottom: 1px solid var(--border);
}
.studio-head h2 { font-size: 1.05rem; }
.studio-body {
  flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain;
  display: flex; flex-direction: column; gap: 14px; padding: 14px 14px 24px;
}
.studio-body.is-reading { justify-content: center; }
.studio-foot {
  flex: none; display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  padding: 10px 14px calc(10px + var(--safe-b));
  background: var(--surface); border-top: 1px solid var(--border);
}
.studio-message {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 10px 12px; border-radius: var(--radius);
  background: var(--surface); border: 1px solid var(--border); border-left: 4px solid var(--cast);
  font-size: 0.84rem; font-weight: 600; line-height: 1.4;
}
.studio-message.is-error { background: var(--danger-soft); border-left-color: var(--danger); font-weight: 400; }
.studio-message .btn { flex: none; }
.studio-wait { text-align: center; color: var(--ink-2); font-size: 0.95rem; }
.script-section { display: flex; flex-direction: column; gap: 6px; }
.script-section h3 { font-size: 0.82rem; font-weight: 700; color: var(--ink-2); }
.script-line {
  display: flex; flex-direction: column; gap: 6px; padding: 8px;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
}
.script-line.is-recorded { border-color: color-mix(in srgb, var(--cast) 45%, var(--border)); }
.script-text { min-height: 44px; resize: none; field-sizing: content; }
.script-tools { display: flex; align-items: center; gap: 4px; min-height: 40px; }
.script-tools .vn { flex: 1; min-width: 0; }
.script-missing { flex: 1; padding-left: 4px; font-size: 0.78rem; color: var(--ink-3); }
.script-mic { color: var(--cast); }
.script-add { align-self: flex-start; }

/* Reading: the line to say, big, with the next one under it. */
.prompter { display: flex; flex-direction: column; align-items: center; gap: 16px; text-align: center; }
.prompter-step { font-size: 0.8rem; color: var(--ink-2); }
.prompter-line { font-size: 1.55rem; line-height: 1.35; font-weight: 700; max-width: 30rem; }
.prompter-next { font-size: 0.92rem; color: var(--ink-3); max-width: 30rem; min-height: 1.3em; }
.prompter .rec-wave { width: min(18rem, 80%); height: 46px; flex: none; }
.prompter-status { font-size: 0.86rem; font-weight: 600; color: var(--ink-2); min-height: 1.3em; }
.prompter[data-state='hearing'] .prompter-status { color: var(--danger); }
.prompter[data-state='got'] .prompter-status,
.prompter[data-state='got'] .prompter-line { color: var(--cast); }
.prompter[data-state='got'] .prompter-line { transition: color 0.15s; }
.prompter[data-state='silent'] .prompter-status { color: var(--danger); }
.prompter-go { width: min(20rem, 100%); min-height: 54px; font-size: 1rem; }
.prompter-auto { font-size: 0.82rem; color: var(--ink-2); }

/* ── Editor: your bot's lines for this habit ── */
.bot-picks {
  --cast: #E0663A;
  display: flex; flex-direction: column; gap: 8px;
  margin-top: 8px; padding-top: 12px; border-top: 1px solid var(--border);
}
.bot-pick-list { display: flex; flex-direction: column; gap: 4px; }
.bot-pick-list:empty { display: none; }
.bot-pick { display: flex; align-items: center; gap: 6px; }
.bot-pick label { flex: 1; min-width: 0; display: flex; align-items: center; gap: 10px; font-size: 0.86rem; line-height: 1.35; }
.bot-pick input { width: 20px; height: 20px; flex: none; accent-color: var(--cast); }
.bot-pick-play { flex: none; color: var(--cast); }
#btnBotStudio { align-self: flex-start; }

/* ── Settings ── */
.setting-label { font-size: 0.88rem; }
.cast-current {
  display: inline-flex; align-items: center; gap: 8px;
  min-height: 40px; padding: 4px 10px 4px 4px; max-width: 60%;
  background: var(--surface-3); border: 1px solid var(--border); border-radius: var(--radius-pill);
  font-size: 0.86rem; font-weight: 600; color: var(--ink);
}
.cast-current img { width: 32px; height: 32px; border-radius: 50%; flex: none; }
.cast-current span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cast-current svg { flex: none; color: var(--ink-3); transform: rotate(-90deg); }
.cast-current:not(:has(img:not([hidden]))) { padding-left: 12px; }
.setting-warning {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 10px 12px; border-radius: var(--radius);
  background: color-mix(in srgb, var(--s4) 14%, transparent);
  border: 1px solid color-mix(in srgb, var(--s4) 35%, transparent);
  font-size: 0.82rem; line-height: 1.4;
}
.setting-warning .btn { flex: none; }

/* ── Weight and BMI ── */
.body-card { display: flex; flex-direction: column; gap: 10px; }
.body-top { display: flex; align-items: center; flex-wrap: wrap; gap: 8px 12px; }
.body-value { font-size: 1.6rem; font-weight: 700; font-variant-numeric: tabular-nums; letter-spacing: -0.01em; }
.body-notes { font-size: 0.82rem; color: var(--ink-2); }
.bmi-chip {
  --band: var(--s3);
  display: inline-flex; align-items: center; padding: 4px 10px;
  border-radius: var(--radius-pill); font-size: 0.78rem; font-weight: 600;
  color: var(--ink);
  background: color-mix(in srgb, var(--band) 18%, transparent);
  border: 1px solid color-mix(in srgb, var(--band) 45%, transparent);
}
.bmi-chip[data-band='Under'], .bmi-band[data-band='Under'] { --band: var(--s1); }
.bmi-chip[data-band='Normal'], .bmi-band[data-band='Normal'] { --band: var(--s3); }
.bmi-chip[data-band='Over'], .bmi-band[data-band='Over'] { --band: var(--s4); }
.bmi-chip[data-band='Obese'], .bmi-band[data-band='Obese'] { --band: var(--s8); }
.body-preview:empty { display: none; }
.height-inputs { display: flex; gap: 8px; }
.height-input { flex: 1; display: flex; align-items: center; gap: 6px; font-size: 0.85rem; color: var(--ink-2); }
.height-input input { flex: 1; min-width: 0; }
/* As specific as the generic number field it overrides (input[type='number']
   is 100 % wide): until 2.14 that rule won, the box took the whole row, the
   label broke over three lines and the box ran out of the card. */
.setting-row input.setting-number { width: 7.5rem; flex: none; }
.setting-row > label, .setting-row > .setting-label { flex: 1 1 auto; min-width: 0; }
.bmi-scale { display: flex; flex-direction: column; gap: 6px; }
.bmi-scale .bmi-chip { align-self: flex-start; }
.bmi-track { position: relative; display: flex; height: 10px; border-radius: var(--radius-pill); overflow: visible; }
.bmi-band { height: 100%; background: color-mix(in srgb, var(--band) 70%, transparent); }
.bmi-band:first-child { border-radius: var(--radius-pill) 0 0 var(--radius-pill); }
.bmi-band:last-of-type { border-radius: 0 var(--radius-pill) var(--radius-pill) 0; }
.bmi-mark {
  position: absolute; top: -4px; width: 4px; height: 18px; margin-left: -2px;
  border-radius: 2px; background: var(--ink); box-shadow: 0 0 0 2px var(--surface);
}
.bmi-labels { display: flex; font-size: 0.66rem; color: var(--ink-2); }
.bmi-labels span { text-align: center; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ── Editor: quick ideas (2.13) ──
   One row that scrolls sideways and runs to the sheet's edges, so it reads
   as a shelf of options rather than part of the form. */
.idea-row {
  display: flex; gap: 6px; overflow-x: auto; overscroll-behavior-x: contain;
  margin: 0 -16px; padding: 2px 16px 4px; scrollbar-width: none;
}
.idea-row::-webkit-scrollbar { display: none; }
.idea-chip {
  flex: none; display: inline-flex; align-items: center; gap: 6px;
  min-height: var(--tap); padding: 0 14px; border-radius: var(--radius-pill);
  background: var(--surface-3); border: 1px solid var(--border);
  font-size: 0.82rem; font-weight: 600; white-space: nowrap;
}
.idea-chip[aria-pressed='true'] { border-color: var(--accent); background: var(--accent-soft); }

/* ── Editor: reminder times ── */
.reminder-list { display: flex; flex-direction: column; gap: 6px; }
.reminder-list:empty { display: none; }
.reminder-row { display: flex; align-items: center; gap: 6px; }
.reminder-row input { flex: 1; }
.reminder-add { align-self: flex-start; }

/* ── Editor: your own voice note ── */
.own-voice {
  --cast: var(--accent);
  display: flex; flex-direction: column; gap: 8px;
  margin-top: 8px; padding-top: 12px; border-top: 1px solid var(--border);
}
.own-voice-body { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.own-voice-body:empty { display: none; }
.own-voice-body .vn { flex: 1 1 13rem; }
.own-voice-actions { display: flex; flex-wrap: wrap; gap: 6px; }
.own-voice-record { display: inline-flex; align-items: center; gap: 6px; }
.rec-row { flex: 1; display: flex; align-items: center; gap: 10px; min-width: 0; }
.rec-dot {
  width: 12px; height: 12px; flex: none; border-radius: 50%;
  background: var(--danger);
  animation: rec-pulse 1.1s ease-in-out infinite;
}
@keyframes rec-pulse { 50% { opacity: 0.35; transform: scale(0.8); } }
.rec-time {
  flex: none; font-size: 0.78rem; color: var(--ink-2);
  font-variant-numeric: tabular-nums;
}
.rec-wave { min-width: 0; }
/* Two classes, so it outranks the .vn-wave rule further down. */
.vn-wave.rec-wave i { height: 12%; background: var(--danger); transition: height 0.08s linear; }
@media (prefers-reduced-motion: reduce) {
  .rec-dot { animation: none; }
  .vn-wave.rec-wave i { transition: none; }
}
/* Save waits for a take to finish. */
#btnSaveHabit:disabled { opacity: 0.45; cursor: not-allowed; }

/* ── The conversation ── */
.chat {
  --cast: var(--accent);
  position: fixed; inset: 0; z-index: 800;
  display: flex; flex-direction: column;
  background: var(--bg);
}
.chat-panel {
  flex: 1; min-height: 0; width: 100%; max-width: 42rem; margin: 0 auto;
  display: flex; flex-direction: column;
  animation: ob-in 0.22s ease-out both;
}
.chat-head {
  flex: none; display: flex; align-items: center; gap: 10px;
  padding: calc(8px + env(safe-area-inset-top, 0px)) 10px 8px 4px;
  background: var(--surface); border-bottom: 1px solid var(--border);
}
.chat-avatar {
  width: 42px; height: 42px; flex: none; border-radius: 50%;
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--cast) 55%, transparent);
}
.chat-who { flex: 1; min-width: 0; display: flex; flex-direction: column; line-height: 1.25; }
.chat-who strong { font-size: 1rem; }
.chat-who span {
  font-size: 0.74rem; color: var(--ink-2);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.chat-log {
  flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain;
  display: flex; flex-direction: column; gap: 6px;
  padding: 14px 12px 20px;
  background:
    radial-gradient(120% 60% at 0% 0%, color-mix(in srgb, var(--cast) 9%, transparent), transparent 60%),
    var(--bg);
}
.chat-day {
  align-self: center; margin: 10px 0 4px; padding: 3px 11px;
  border-radius: 999px; background: var(--surface-2);
  font-size: 0.7rem; font-weight: 600; color: var(--ink-2);
}
.chat-row { display: flex; }
.chat-row.is-me { justify-content: flex-end; }
.bubble {
  max-width: min(84%, 28rem);
  display: flex; flex-direction: column; gap: 7px;
  padding: 8px 11px 6px; border-radius: 16px;
  background: var(--surface-2); border: 1px solid var(--border);
  animation: bubble-in 0.2s ease-out both;
}
@keyframes bubble-in { from { opacity: 0; transform: translateY(4px); } }
.is-them .bubble { border-top-left-radius: 5px; box-shadow: inset 3px 0 0 var(--cast); }
.is-me .bubble {
  border-top-right-radius: 5px;
  background: color-mix(in srgb, var(--cast) 24%, var(--surface-2));
  border-color: color-mix(in srgb, var(--cast) 35%, transparent);
}
.bubble-text { font-size: 0.9rem; line-height: 1.45; white-space: pre-wrap; overflow-wrap: anywhere; }
.bubble-time {
  align-self: flex-end; margin-top: -3px;
  font-size: 0.66rem; color: var(--ink-3); font-variant-numeric: tabular-nums;
}

/* Voice note: play, waveform, length */
.vn { display: flex; align-items: center; gap: 10px; min-width: min(14rem, 62vw); }
.vn-play {
  width: 40px; height: 40px; flex: none; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--cast); color: #fff;
  box-shadow: 0 3px 10px color-mix(in srgb, var(--cast) 35%, transparent);
}
.vn-play svg { margin-left: 2px; }
.vn.is-playing .vn-play svg { margin-left: 0; }
.vn-wave { flex: 1; height: 30px; display: flex; align-items: center; gap: 2px; }
.vn-wave i {
  flex: 1; min-width: 2px; border-radius: 2px;
  background: color-mix(in srgb, var(--ink-2) 42%, transparent);
  transition: background 0.12s;
}
.vn-wave i.is-played { background: var(--cast); }
.vn-time {
  min-width: 2.3rem; text-align: right;
  font-size: 0.72rem; color: var(--ink-2); font-variant-numeric: tabular-nums;
}

.chat-foot {
  flex: none; display: flex; flex-wrap: wrap; justify-content: center; gap: 8px;
  padding: 10px 12px calc(10px + var(--safe-b));
  background: var(--surface); border-top: 1px solid var(--border);
}
.chat-chip {
  min-height: 42px; padding: 0 16px; max-width: 100%;
  border-radius: 999px; font-size: 0.85rem; font-weight: 600; color: var(--ink);
  background: color-mix(in srgb, var(--cast) 16%, var(--surface-2));
  border: 1px solid color-mix(in srgb, var(--cast) 45%, transparent);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.chat-chip:active { transform: scale(0.98); }
.chat-hint { padding: 6px 0; font-size: 0.8rem; color: var(--ink-2); text-align: center; }

/* ── Palette picker (2.13) ────────────────────────────────────────────
   Each card carries data-palette, so the palette blocks at the top of this
   file paint it with that palette's own tokens: what you see is what you
   get, in the current light or dark. The ring around the chosen one is in
   its own accent, which is the app's accent once it is chosen. */
.palette-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
/* Two columns: a last card alone on its row takes the whole row (2.23). */
.palette-grid > .palette-card:last-child:nth-child(odd) { grid-column: 1 / -1; }
@media (min-width: 560px) {
  .palette-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .palette-grid > .palette-card:last-child:nth-child(odd) { grid-column: auto; }
}
.palette-card {
  display: flex; flex-direction: column; gap: 8px; min-width: 0;
  padding: 9px; text-align: left;
  border-radius: var(--radius); border: 1px solid var(--border-strong);
  background: var(--bg); color: var(--ink);
  transition: transform 0.12s ease, box-shadow 0.15s ease;
}
.palette-card:active { transform: scale(0.98); }
.palette-card[aria-checked='true'] { border-color: transparent; box-shadow: 0 0 0 2px var(--accent); }
.pc-preview {
  display: flex; align-items: center; gap: 8px; padding: 8px;
  border-radius: 9px; background: var(--surface); border: 1px solid var(--border);
}
.pc-ring {
  width: 1.4rem; height: 1.4rem; flex: none; border-radius: 50%;
  background: conic-gradient(var(--accent) 0 72%, var(--surface-3) 72% 100%);
  -webkit-mask: radial-gradient(circle, transparent 50%, #000 53%);
  mask: radial-gradient(circle, transparent 50%, #000 53%);
}
.pc-lines { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.pc-lines i { display: block; height: 5px; border-radius: 999px; }
.pc-lines i:nth-child(1) { width: 92%; background: var(--s1); }
.pc-lines i:nth-child(2) { width: 70%; background: var(--s5); }
.pc-lines i:nth-child(3) { width: 48%; background: var(--s3); }
.pc-name {
  display: flex; align-items: center; justify-content: space-between; gap: 6px;
  font-size: 0.82rem; font-weight: 650; line-height: 1.2;
}
.palette-card[aria-checked='true'] .pc-name::after { content: '✓'; color: var(--accent); font-weight: 800; }
.pc-note { margin-top: -5px; font-size: 0.68rem; font-weight: 600; color: var(--ink-2); }
.pc-note:empty { display: none; }
/* Clásica's "Recomendada": a small pill tinted with the card's own accent;
   the text stays in ink, as small accent text would not read in light. */
.pc-tag {
  align-self: flex-start; margin-top: -3px; padding: 1px 7px;
  border-radius: var(--radius-pill); background: var(--accent-soft); color: var(--ink);
  box-shadow: inset 0 0 0 1px var(--accent);
  font-size: 0.66rem; font-weight: 700; line-height: 1.5;
}
/* The picker's heading reads like the other stacked rows' labels. */
.setting-row-stack .setting-label { color: var(--ink-2); font-size: 0.82rem; font-weight: 600; }

/* ── Pico, the guide ─────────────────────────────────────────────────
   One solid colour of his own, the same in every palette: purple (2.17;
   through 2.16 he took the palette's ink, near black or slate grey, and
   looked dull). Deep on light themes; on dark ones a brighter violet of the
   same hue, or he would sink into the background. Measured against every
   palette's background and card: on light themes 9.9:1 and up, on dark ones
   3.4:1 and up (WCAG asks 3:1 of a shape), eye whites 4.1:1 on him or more.
   The negative-space lines (a folded wing's crease, the chest feather) are
   in the surface he stands on. pico.js moves him; nothing here animates. */
:root {
  --pico-body: #8A55F0;
  --pico-eye: #F5F3FF;
  --pico-pupil: #2E1065;
  --pico-cut: var(--surface);
}
:root[data-theme='light'] {
  --pico-body: #4C1D95;
  --pico-eye: #FFFFFF;
  --pico-pupil: #2E1065;
}
.pico { display: block; width: 100%; height: 100%; overflow: visible; color: var(--pico-body); }
.pico .pk-fill { fill: currentColor; }
.pico .pk-legs { stroke: currentColor; }
.pico .pk-cut { fill: none; stroke: var(--pico-cut); stroke-width: 1.4; stroke-linecap: round; }
.pico .pk-crease { fill: none; stroke: var(--pico-cut); stroke-width: 1.4; stroke-linecap: round; }
.pico .pk-white { fill: var(--pico-eye); }
.pico .pk-pupil { fill: var(--pico-pupil); }
.pico .pk-glint { fill: var(--pico-eye); }
.pico .pk-glad { fill: none; stroke: var(--pico-eye); stroke-width: 2; stroke-linecap: round; }
.pico .pk-shadow { fill: currentColor; opacity: 0.14; }
.pico .pk-spark { fill: var(--accent); }
/* The beak is his one warm accent, the same in every palette. */
.pico .pk-beak-up { fill: #E3A33A; }
.pico .pk-beak-low { fill: #B87A1E; }

/* His hats (2.24): flat like him, their own colours, set for dark themes
   first and light ones after (as his purple is). --hat-a is the main
   colour, -b and -c the second and the detail, --hat-ink the fine lines. */
.pk-hat-a { fill: var(--hat-a); }
.pk-hat-b { fill: var(--hat-b); }
.pk-hat-c { fill: var(--hat-c); }
.pk-hat-ink { fill: none; stroke: var(--hat-ink); stroke-width: 0.9; stroke-linecap: round; stroke-linejoin: round; }
.pk-hat[data-hat='beanie'] { --hat-a: #34C3B5; --hat-b: #23968C; --hat-c: #A8EDE6; --hat-ink: #17766D; }
.pk-hat[data-hat='birthday'] { --hat-a: #FF6F8E; --hat-c: #FFD166; }
.pk-hat[data-hat='explorer'] { --hat-a: #D9C28C; --hat-b: #7A6443; --hat-c: #C4A971; }
.pk-hat[data-hat='vueltiao'] { --hat-a: #EFE3C6; --hat-b: #241E17; --hat-ink: #241E17; }
.pk-hat[data-hat='witch'] { --hat-a: #66568A; --hat-b: #FF8A1E; --hat-c: #54467A; }
.pk-hat[data-hat='santa'] { --hat-a: #EF5466; --hat-c: #F7F2EA; }
:root[data-theme='light'] .pk-hat[data-hat='beanie'] { --hat-a: #1E9E92; --hat-b: #157A71; --hat-c: #7FD3CA; --hat-ink: #0E5A53; }
:root[data-theme='light'] .pk-hat[data-hat='birthday'] { --hat-a: #E8476B; --hat-c: #F0B429; }
:root[data-theme='light'] .pk-hat[data-hat='explorer'] { --hat-a: #C2A56B; --hat-b: #5E4A2E; --hat-c: #A88C55; }
:root[data-theme='light'] .pk-hat[data-hat='vueltiao'] { --hat-a: #E2D2A8; --hat-b: #1E1912; --hat-ink: #1E1912; }
:root[data-theme='light'] .pk-hat[data-hat='witch'] { --hat-a: #2E2540; --hat-b: #F07A12; --hat-c: #3D3352; }
:root[data-theme='light'] .pk-hat[data-hat='santa'] { --hat-a: #D7263D; --hat-c: #F3ECE2; }
/* On a light page the white fur would melt into it: a soft edge keeps it. */
:root[data-theme='light'] .pk-hat[data-hat='santa'] .pk-hat-c { stroke: #DCCFBD; stroke-width: 0.8; }
/* 2.25's hats. */
.pk-hat[data-hat='cap'] { --hat-a: #3B82F6; --hat-b: #1D4ED8; --hat-c: #F8FAFC; }
.pk-hat[data-hat='flowers'] { --hat-a: #F472B6; --hat-b: #FCD34D; --hat-c: #FFF7ED; --hat-ink: #4ADE80; }
.pk-hat[data-hat='beret'] { --hat-a: #3B5BDB; --hat-b: #2B44B0; --hat-ink: #3B5BDB; }
.pk-hat[data-hat='graduation'] { --hat-a: #64748B; --hat-b: #475569; --hat-c: #FBBF24; --hat-ink: #FBBF24; }
.pk-hat[data-hat='crown'] { --hat-a: #FBBF24; --hat-b: #D97706; --hat-c: #EF4444; }
.pk-hat[data-hat='tophat'] { --hat-a: #52525B; --hat-b: #E11D48; --hat-c: #3F3F46; }
.pk-hat[data-hat='chef'] { --hat-a: #FFFFFF; --hat-b: #E4E4E7; --hat-ink: #A1A1AA; }
:root[data-theme='light'] .pk-hat[data-hat='cap'] { --hat-a: #2563EB; --hat-b: #1E40AF; --hat-c: #FFFFFF; }
:root[data-theme='light'] .pk-hat[data-hat='flowers'] { --hat-a: #EC4899; --hat-b: #F59E0B; --hat-c: #FFFFFF; --hat-ink: #16A34A; }
:root[data-theme='light'] .pk-hat[data-hat='beret'] { --hat-a: #1E3A8A; --hat-b: #172C6B; --hat-ink: #1E3A8A; }
:root[data-theme='light'] .pk-hat[data-hat='graduation'] { --hat-a: #1F2937; --hat-b: #111827; --hat-c: #D97706; --hat-ink: #D97706; }
:root[data-theme='light'] .pk-hat[data-hat='crown'] { --hat-a: #F59E0B; --hat-b: #B45309; --hat-c: #DC2626; }
:root[data-theme='light'] .pk-hat[data-hat='tophat'] { --hat-a: #18181B; --hat-b: #BE123C; --hat-c: #27272A; }
:root[data-theme='light'] .pk-hat[data-hat='chef'] { --hat-a: #FFFFFF; --hat-b: #F4F4F5; --hat-ink: #A1A1AA; }
/* White on a light page: a soft edge, as the Christmas hat's fur has. */
:root[data-theme='light'] .pk-hat[data-hat='chef'] .pk-hat-a,
:root[data-theme='light'] .pk-hat[data-hat='chef'] .pk-hat-b { stroke: #D4D4D8; stroke-width: 0.8; }

/* The wardrobe (2.24): Pico large on a little stage, what he has on, and
   the hats to try, each tile drawn with the hat itself. Since 2.25 the top
   (Pico, his hat's name, the button) holds still and only the gestures and
   tiles scroll beneath it, so a hat tried on from far down is seen. */
#wardrobeDialog[open] { display: flex; flex-direction: column; overflow: hidden; }
.wardrobe-top {
  flex: none; display: grid; gap: 8px; padding: 10px 16px 12px;
  border-bottom: 1px solid var(--border);
}
.wardrobe-scroll { flex: 1 1 auto; min-height: 0; overflow-y: auto; }
.wardrobe-stage {
  display: flex; justify-content: center; padding: 6px 0 0;
  border-radius: var(--radius);
  background: radial-gradient(ellipse at 50% 85%, var(--accent-soft), transparent 70%);
}
.wardrobe-pico { width: 7rem; height: 7rem; }
.wardrobe-moves { display: flex; flex-wrap: wrap; justify-content: center; gap: 6px; }
.wardrobe-info { text-align: center; display: grid; gap: 4px; }
.wardrobe-name { font-weight: 700; font-size: 1.05rem; }
.wardrobe-wear { align-self: center; justify-self: center; min-width: 11rem; }
.wardrobe-wear:disabled { opacity: 0.45; cursor: not-allowed; filter: none; }
.wardrobe-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }
@media (min-width: 560px) { .wardrobe-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
.hat-tile {
  display: flex; flex-direction: column; align-items: center; gap: 3px; min-width: 0;
  padding: 8px 6px; border-radius: var(--radius);
  border: 1px solid var(--border-strong); background: var(--surface-2); color: var(--ink);
  transition: transform 0.12s ease, box-shadow 0.15s ease;
}
.hat-tile:active { transform: scale(0.97); }
.hat-tile[aria-pressed='true'] { border-color: transparent; box-shadow: 0 0 0 2px var(--accent); }
.hat-tile-art { display: block; width: 100%; max-width: 4.6rem; }
.hat-icon { display: block; width: 100%; height: auto; aspect-ratio: 70 / 36; }
.hat-none path { fill: var(--pico-body); }
.hat-tile-name { font-size: 0.76rem; font-weight: 600; line-height: 1.2; text-align: center; overflow-wrap: anywhere; }
.hat-tile-tier { font-size: 0.68rem; color: var(--ink-2); }
.hat-tile.is-worn .hat-tile-tier { color: var(--accent); font-weight: 700; }
.hat-tile.is-locked .hat-tile-art { opacity: 0.7; }

/* Guided routines (2.25, a Plus preview): a card in Hábitos, an editor, and
   a player that goes step by step. */
.routines-card { margin-bottom: 12px; display: grid; gap: 8px; }
.routines-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.routines-card .btn { justify-self: start; }
.routine-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.routine-item {
  display: flex; align-items: center; gap: 10px; padding: 10px 12px;
  border-radius: var(--radius); background: var(--surface-2); border: 1px solid var(--border);
}
.routine-item-text { flex: 1 1 auto; min-width: 0; display: grid; gap: 2px; }
.routine-item-name { font-weight: 650; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.routine-item-meta { font-size: 0.75rem; color: var(--ink-2); }
.routine-steps { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
.routine-step {
  display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 6px 10px; align-items: center;
  padding: 8px 10px; border-radius: var(--radius); background: var(--surface-2); border: 1px solid var(--border);
}
.routine-step-name { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.routine-step-tools { display: flex; gap: 4px; align-items: center; }
.routine-step-time { grid-column: 1 / -1; display: flex; align-items: center; gap: 8px; font-size: 0.8rem; color: var(--ink-2); }
.routine-step-time output { min-width: 4.6rem; text-align: center; font-weight: 600; color: var(--ink); }
.routine-step .icon-btn { width: 34px; height: 34px; }
.player-body { align-items: center; text-align: center; }
.player-pico { display: block; width: 6rem; height: 6rem; }
.player-habit { font-size: 1.25rem; font-weight: 700; }
.player-timer { font-size: 2.6rem; font-weight: 700; font-variant-numeric: tabular-nums; letter-spacing: 0.02em; }
.player-note { min-height: 1.2em; }
.player-actions { justify-content: center; }

/* Sick days (2.26): a quiet button in the mood card; while it lasts, a card
   on Today saying what still counts. */
.sick-chip {
  display: inline-flex; align-items: center; gap: 6px; margin-top: 10px;
  min-height: 34px; padding: 4px 12px; border-radius: var(--radius-pill);
  font: inherit; font-size: 0.82rem; font-weight: 600; color: var(--ink-2);
  background: var(--surface-2); border: 1px solid var(--border); cursor: pointer;
}
.sick-chip:hover { border-color: var(--accent); color: var(--ink); }
.sick-card { display: grid; gap: 8px; border-color: color-mix(in srgb, var(--accent) 35%, var(--edge)); }
.sick-head { display: flex; align-items: center; gap: 10px; }
.sick-emoji { font-size: 1.7rem; line-height: 1; }
.sick-head h3 { margin-bottom: 1px; }
.sick-text { font-size: 0.86rem; line-height: 1.45; }
.sick-card .button-row { margin-top: 2px; }
.sick-keep { display: grid; gap: 10px; }
.essential-row .essential-text { display: grid; gap: 2px; }
.essential-row .field-hint { font-weight: 400; }

/* The guided program (2.25, a Plus preview): its step on Today, its card in
   Hábitos, and the sheet with the day's step. */
.program-today {
  display: flex; align-items: center; gap: 10px; width: 100%;
  font: inherit; color: inherit; text-align: start; cursor: pointer;
  background: linear-gradient(135deg, color-mix(in srgb, var(--accent) 12%, var(--surface)), var(--surface) 70%);
}
.program-today-text { flex: 1 1 auto; min-width: 0; display: grid; gap: 2px; }
.program-today-day { font-size: 0.75rem; font-weight: 600; color: var(--accent); }
.program-today-title { font-size: 0.95rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.program-today-go { flex: none; color: var(--ink-2); }
.program-name { font-weight: 650; }
.program-card .button-row { margin-top: 0; }
.program-step-day { font-size: 0.85rem; font-weight: 600; color: var(--accent); }
.program-body { align-items: center; text-align: center; }
.program-pico { display: block; width: 5.5rem; height: 5.5rem; }
.program-body h2 { font-size: 1.2rem; }
.program-step-text { line-height: 1.5; max-width: 30rem; }
.program-step-action:empty { display: none; }
.preset-chip:disabled { opacity: 0.55; cursor: default; }

/* The month's report (2.25, a Plus preview): what it holds, then the report
   on a sheet of paper, the same that prints. */
.insights-report { margin-top: 4px; }
.report-holds { border: 0; margin: 0; padding: 0; display: grid; gap: 8px; }
.report-holds legend { padding: 0; margin-bottom: 4px; }
.check-line { display: flex; align-items: flex-start; gap: 8px; font-size: 0.86rem; line-height: 1.4; }
.check-line input { margin-top: 2px; flex: none; width: 1.05rem; height: 1.05rem; accent-color: var(--accent); }
.report-paper {
  border-radius: 12px; padding: 16px; overflow-x: auto;
  background: #FFFFFF; color: #1A1A1A; border: 1px solid var(--border);
}
.report { font-size: 0.8rem; line-height: 1.45; color: #1A1A1A; }
.report-top { display: flex; align-items: center; gap: 12px; margin-bottom: 10px; }
.report-pico { width: 3rem; height: 3rem; flex: none; }
.report-top h1 { font-size: 1.15rem; margin: 0 0 2px; color: #1A1A1A; }
.report-top p, .report-holds-line, .report-foot { margin: 0; color: #55524D; font-size: 0.74rem; }
.report-holds-line { margin-bottom: 12px; }
.report h2 { font-size: 0.92rem; margin: 14px 0 6px; color: #1A1A1A; }
.report-facts { margin: 0; display: grid; grid-template-columns: max-content 1fr; gap: 3px 14px; }
.report-facts dt { color: #55524D; }
.report-facts dd { margin: 0; font-weight: 600; }
.report table { width: 100%; border-collapse: collapse; font-variant-numeric: tabular-nums; }
.report th, .report td { text-align: start; padding: 4px 6px; border-bottom: 1px solid #E2DFDA; vertical-align: top; }
.report th { font-weight: 600; color: #55524D; }
.report td.num, .report th.num { text-align: end; white-space: nowrap; }
.report ul { margin: 0; padding-inline-start: 1.1rem; display: grid; gap: 4px; }
.report-foot { margin-top: 14px; padding-top: 8px; border-top: 1px solid #E2DFDA; }
.print-area { display: none; }

/* His invitation on Today, for anyone who had the app before he arrived. */
.pico-promo {
  display: flex; align-items: center; gap: 0.9rem;
  background: linear-gradient(135deg, color-mix(in srgb, var(--accent) 14%, var(--surface)), var(--surface) 72%);
}
.pico-promo-art { width: 4.4rem; height: 4.4rem; flex: none; }
.pico-promo-text { min-width: 0; }
.pico-promo h3 { margin-bottom: 3px; }
.pico-promo p { font-size: 0.82rem; line-height: 1.45; color: var(--ink-2); }
.pico-promo .button-row { margin-top: 10px; }

/* Pico's discoveries in Progress (2.24, a Plus preview): plain sentences,
   one per finding, under a small thinking Pico. */
.insights-head { display: flex; align-items: center; gap: 0.75rem; margin-bottom: 6px; }
.insights-pico { width: 3.2rem; height: 3.2rem; flex: none; }
.insights-head h3 { margin-bottom: 2px; }
.insights-tag {
  display: inline-block; padding: 1px 8px; border-radius: var(--radius-pill);
  font-size: 0.7rem; font-weight: 600; color: var(--accent); background: var(--accent-soft);
}
.insights-list { list-style: none; margin: 8px 0 6px; padding: 0; display: grid; gap: 8px; }
.insights-list li {
  font-size: 0.86rem; line-height: 1.45; padding: 8px 10px;
  border-radius: 10px; background: var(--surface-2);
}

/* ── The tour (2.13) ──────────────────────────────────────────────────
   The spotlight is a box over the target whose enormous shadow dims the
   rest of the screen, so it can glide from one stop to the next. The coach
   sits above or below it, wherever there is room; stops with nothing to
   point at centre the coach and let Pico stand on top of it. The overlay
   takes every touch, so the app underneath cannot change mid-tour. */
.tour { position: fixed; inset: 0; z-index: 850; touch-action: none; overscroll-behavior: contain; }
/* A damped spring (about 8 % of overshoot), sampled for linear(); browsers
   without linear() keep the cubic curve before it. */
:root { --spring: cubic-bezier(0.2, 0.9, 0.25, 1.06); --spring-time: 0.55s; }
@supports (transition-timing-function: linear(0, 1)) {
  :root {
    --spring: linear(0, 0.0686 4%, 0.228 8%, 0.4224 12%, 0.6133 15%, 0.7779 19%, 0.9058 23%, 0.9952 27%,
      1.05 31%, 1.0769 35%, 1.0835 38%, 1.0769 42%, 1.0632 46%, 1.0468 50%, 1.031 54%, 1.0175 58%,
      1.0071 62%, 0.9999 65%, 0.9955 69%, 0.9935 73%, 0.993 77%, 0.9937 81%, 0.9948 85%, 0.9962 88%,
      0.9975 92%, 0.9986 96%, 1);
  }
}
/* Since 2.22 nothing here animates its place or size, which made the
   browser lay out and repaint the whole screen on every frame: the
   highlight fades (opacity), the card and Pico glide (translate, and scale
   for Pico's size; transform where a browser lacks those). */
.tour-dim {
  position: fixed; inset: 0; pointer-events: none; background: rgba(4, 6, 12, 0.68);
  opacity: 0; transition: opacity 0.18s ease-out; will-change: opacity;
}
.tour-dim.is-on { opacity: 1; }
.tour-spot {
  position: fixed; left: 50%; top: 50%; width: 0; height: 0;
  border-radius: 16px; pointer-events: none;
  box-shadow: 0 0 0 120vmax rgba(4, 6, 12, 0.68);
  opacity: 0; transition: opacity 0.26s ease-out; will-change: opacity;
}
.tour-spot.is-open { opacity: 1; }
.tour-spot.is-target::after {
  content: ''; position: absolute; inset: -3px; border-radius: inherit;
  border: 2px solid var(--accent);
  animation: tour-pulse 1.8s ease-in-out infinite;
}
@keyframes tour-pulse { 50% { opacity: 0.35; } }
.tour-coach {
  position: fixed; left: 16px; right: 16px; max-width: 26rem; margin: 0 auto;
  display: grid; grid-template-columns: minmax(0, 1fr); gap: 6px 12px; z-index: 2;
  will-change: transform;
  padding: 14px 14px 12px;
  border-radius: var(--radius-lg); border: 1px solid var(--border-strong);
  background: var(--surface); color: var(--ink); box-shadow: var(--shadow);
  transition: translate var(--spring-time) var(--spring), transform var(--spring-time) var(--spring), opacity 0.16s ease-out;
}
.tour-coach.is-entering { animation: tour-in 0.26s ease-out both; }
/* A change of view (2.22): the card and Pico step out while it is drawn. */
.tour.is-changing .tour-coach, .tour.is-changing .tour-pico { opacity: 0; }
@keyframes tour-in { from { opacity: 0; transform: translateY(6px) scale(0.98); } }
/* Pico (2.21): large, behind the card (which hides his lower half), placed
   by app.js at its top edge on the side of the target; he runs along it,
   and rises and sinks with the card as it moves. */
.tour-pico {
  position: fixed; left: 0; top: 0; z-index: 1; width: 7rem; height: 7rem;
  transform-origin: 0 0;
  transition: translate var(--spring-time) var(--spring), scale var(--spring-time) var(--spring),
    transform var(--spring-time) var(--spring), opacity 0.2s ease-out;
  will-change: transform;
}
/* While the tour runs the page has room at its end, so a target near the
   bottom of a short page can still be lifted under the app bar, with the
   card and Pico below it (2.21: Pico grew, and a short page left no room). */
html.is-touring body { padding-bottom: calc(64px + var(--safe-b) + 70vh); }
.tour-text { min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.tour-step { font-size: 0.68rem; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; color: var(--accent); }
.tour-text h2 { font-size: 1.05rem; font-weight: 700; letter-spacing: -0.01em; }
.tour-text p:last-child { font-size: 0.88rem; line-height: 1.45; color: var(--ink-2); }
/* Pico's words, appearing as he says them (pico.js times his beak to them). */
.tour-text .tw { animation: tw-in 0.34s ease-out both; }
/* Held while the card is away in a change of scene (2.22): they come with it. */
.tour-text .is-held .tw { animation-play-state: paused; }
@keyframes tw-in { from { opacity: 0; } }
.tour-dots { grid-column: 1 / -1; display: flex; justify-content: center; gap: 5px; margin-top: 4px; }
.tour-dots i { width: 6px; height: 6px; border-radius: 999px; background: var(--border-strong); transition: width 0.2s, background 0.2s; }
.tour-dots i.is-on { width: 16px; background: var(--accent); }
.tour-foot { grid-column: 1 / -1; display: flex; align-items: center; gap: 6px; }
.tour-foot .btn { min-height: 40px; }
.tour[data-mode='center'] .tour-coach { grid-template-columns: minmax(0, 1fr); text-align: center; }
.tour-pico.is-big { width: 9.5rem; height: 9.5rem; }   /* on his own: the first and last stops */
.tour[data-mode='center'] .tour-text { align-items: center; }

/* ── Pico peeking over a ledge (2.15; over a ledge since 2.18) ──
   The box is a window whose bottom edge is a ledge: the tab bar's top, or
   the top of the card he came for when it sits right above the bar. He
   rises inside it, so his lower body stays behind the ledge and only his
   head, shoulders and wings come into view, wings resting on the edge,
   and he ducks back down when he is done. Through 2.17 the whole bird slid
   in from the side, stiff as a sticker. app.js places the window and sets
   his tilt towards what he looks at. */
.pico-peek {
  position: fixed; left: 6px; bottom: 0; z-index: 59;
  width: 6.4rem; height: 4.1rem; overflow: hidden; pointer-events: none;
}
.pico-peek[data-side='right'] { left: auto; right: 6px; }
.pico-peek-art {
  position: absolute; left: 0; top: 0; width: 6.4rem; height: 6.4rem;
  transform: translateY(100%) rotate(var(--peek-tilt, 0deg));
  transform-origin: 50% 80%;
  transition: transform 0.6s var(--spring);
}
.pico-peek.is-in .pico-peek-art { transform: translateY(0) rotate(var(--peek-tilt, 0deg)); }
.pico-peek.is-out .pico-peek-art {
  transform: translateY(100%) rotate(var(--peek-tilt, 0deg));
  transition: transform 0.34s cubic-bezier(0.55, 0, 0.8, 0.2);
}

/* ── Pico at 100 % ────────────────────────────────────────────────────
   When the day completes he hops up over the tab bar for a moment. Tapping
   him sends him off sooner. */
.pico-cheer {
  position: fixed; left: 50%; bottom: calc(70px + var(--safe-b)); z-index: 95;
  display: flex; align-items: flex-end; gap: 4px;
  width: max-content; max-width: calc(100vw - 32px);
  transform: translateX(-50%);
  animation: cheer-in 0.32s cubic-bezier(0.2, 1.4, 0.4, 1) both;
}
.pico-cheer.is-leaving { animation: cheer-out 0.24s ease-in both; }
@keyframes cheer-in { from { opacity: 0; transform: translate(-50%, 24px) scale(0.9); } }
@keyframes cheer-out { to { opacity: 0; transform: translate(-50%, 16px) scale(0.95); } }
.pico-cheer-art { width: 4.2rem; height: 4.2rem; flex: none; }
.pico-cheer-text {
  margin-bottom: 1.6rem; padding: 9px 14px;
  border-radius: 16px 16px 16px 5px;
  background: var(--surface-2); color: var(--ink);
  border: 1px solid var(--border-strong); box-shadow: var(--shadow);
  font-size: 0.86rem; font-weight: 650; line-height: 1.35;
}

@media (prefers-reduced-motion: reduce) {
  .tour-spot, .tour-dim, .tour-coach, .tour-pico, .palette-card { transition: none; }
  .tour-spot.is-target::after, .tour-coach.is-entering,
  .pico-cheer, .pico-cheer.is-leaving { animation: none; }
}

/* Printing (2.25): only the month's report, black on white whatever the
   theme. Anything else printed (a browser's own print, with no report
   open) comes out as before. */
@media print {
  html.is-printing { color-scheme: light; }
  html.is-printing, html.is-printing body { background: #FFFFFF !important; color: #1A1A1A !important; }
  html.is-printing body { margin: 0 !important; padding: 0 !important; }
  html.is-printing body > :not(.print-area) { display: none !important; }
  html.is-printing .print-area { display: block; page: report; }
  html.is-printing .report { font-size: 10.5pt; }
  .report tr, .report li, .report-facts { break-inside: avoid; }
  .report h2 { break-after: avoid; }
  /* A named page: its margins are the report's alone. */
  @page report { margin: 14mm; }
}
