  :root{
    --bg-deep:#0A0E14;
    --bg-deep-2:#0D1220;
    --glow-1:rgba(245,166,35,0.16);
    --glow-2:rgba(34,211,184,0.13);
    --glow-3:rgba(31,158,219,0.08);
    --glass:rgba(255,255,255,0.045);
    --glass-strong:rgba(255,255,255,0.08);
    --glass-border:rgba(255,255,255,0.10);
    --glass-border-strong:rgba(255,255,255,0.16);
    --ink:#F3F5F7;
    --ink-dim:#9BA5B0;
    --ink-faint:#6B7480;
    --amber:#F5A623;
    --amber-2:#FF6B4A;
    --teal:#22D3B8;
    --teal-2:#1F9EDB;
    --red:#FF5C7A;
    --red-2:#FF3D6E;
    --olive:#9BC04A;
    --olive-2:#6FA045;
    --amber-soft:rgba(245,166,35,0.16);
    --teal-soft:rgba(34,211,184,0.14);
    --red-soft:rgba(255,92,122,0.14);
    --olive-soft:rgba(155,192,74,0.15);
    --grad-amber:linear-gradient(135deg,#F5A623,#FF6B4A);
    --grad-teal:linear-gradient(135deg,#22D3B8,#1F9EDB);
    --grad-red:linear-gradient(135deg,#FF5C7A,#FF3D6E);
    --grad-olive:linear-gradient(135deg,#9BC04A,#6FA045);
    --radius:16px;
    --radius-sm:11px;
    --nav-bg:rgba(14,18,26,0.72);
    --input-bg:rgba(255,255,255,0.05);
    --input-bg-focus:rgba(255,255,255,0.08);
    --select-bg:#141922;
    --toast-bg:rgba(14,18,26,0.9);
    --panel-strong-bg:rgba(0,0,0,0.3);
    --chart-grid:rgba(255,255,255,0.08);
    --chart-tick:#9BA5B0;
    --header-title-grad:linear-gradient(100deg, var(--ink) 40%, var(--amber) 100%);
    --card-shadow:0 8px 24px rgba(0,0,0,0.25);
    --card-shadow-lg:0 14px 40px rgba(0,0,0,0.35), inset 0 1px 0 rgba(255,255,255,0.06);
    --hero-num-grad:linear-gradient(135deg,#FFFFFF 25%,var(--amber) 120%);

    /* legacy aliases still referenced in a few places */
    --graphite:#0A0E14;
    --line:var(--glass-border);
    --line-soft:var(--glass-border);
    --ink-soft:var(--ink-dim);
    --panel:var(--glass);
    --panel-alt:var(--glass-strong);
    --green:var(--olive);
    --green-soft:var(--olive-soft);
  }

  /* ---- Light theme override (toggled via html[data-theme=light]) ---- */
  html[data-theme="light"]{
    --bg-deep:#F7F5F2;
    --bg-deep-2:#FFFFFF;
    --glow-1:rgba(214,138,28,0.10);
    --glow-2:rgba(20,150,130,0.09);
    --glow-3:rgba(31,120,180,0.06);
    --glass:#FFFFFF;
    --glass-strong:#FFFFFF;
    --glass-border:rgba(23,32,43,0.09);
    --glass-border-strong:rgba(23,32,43,0.16);
    --ink:#141A21;
    --ink-dim:#59626D;
    --ink-faint:#8A929C;
    --amber:#C77A12;
    --teal:#0E9B84;
    --red:#D24A63;
    --amber-soft:rgba(199,122,18,0.12);
    --teal-soft:rgba(14,155,132,0.12);
    --red-soft:rgba(210,74,99,0.11);
    --grad-amber:linear-gradient(135deg,#E08C1A,#D0632F);
    --grad-teal:linear-gradient(135deg,#12A88F,#1885B8);
    --nav-bg:rgba(255,255,255,0.9);
    --input-bg:#FFFFFF;
    --input-bg-focus:#FFFFFF;
    --select-bg:#FFFFFF;
    --toast-bg:rgba(255,255,255,0.97);
    --panel-strong-bg:#F1EEE9;
    --chart-grid:rgba(23,32,43,0.07);
    --chart-tick:#59626D;
    --graphite:#F7F5F2;
    --card-shadow:0 1px 2px rgba(23,32,43,0.05), 0 6px 18px rgba(23,32,43,0.07);
    --card-shadow-lg:0 2px 4px rgba(23,32,43,0.05), 0 14px 36px rgba(23,32,43,0.10);
    --hero-num-grad:linear-gradient(135deg,#141A21 30%,#C77A12 130%);
    --header-title-grad:linear-gradient(100deg,#141A21 45%,#C77A12 110%);
  }
  html[data-theme="light"] body{ box-shadow:none; }
  html[data-theme="light"] .navbtn.active svg{ stroke:#fff; }
  html[data-theme="light"] .theme-toggle .sun{ display:inline; }
  html[data-theme="light"] .theme-toggle .moon{ display:none; }
  .theme-toggle .moon{ display:inline; }
  .theme-toggle .sun{ display:none; }
  *{box-sizing:border-box;}
  html{background:var(--bg-deep);}
  body{
    margin:0;
    min-height:100vh;
    background:
      radial-gradient(560px 420px at 12% 0%, rgba(245,166,35,0.16), transparent 60%),
      radial-gradient(620px 480px at 92% 18%, rgba(34,211,184,0.13), transparent 60%),
      radial-gradient(700px 600px at 50% 100%, rgba(31,158,219,0.08), transparent 60%),
      var(--bg-deep);
    background-attachment:fixed;
    color:var(--ink);
    font-family:'Public Sans',sans-serif;
    padding-bottom:calc(96px + env(safe-area-inset-bottom, 0px));
    animation:bgDrift 22s ease-in-out infinite alternate;
  }
  @keyframes bgDrift{
    from{ background-position:0% 0%, 100% 0%, 50% 100%, 0 0; }
    to{ background-position:6% 4%, 92% 10%, 46% 96%, 0 0; }
  }
  @media (prefers-reduced-motion: reduce){ body{ animation:none; } }

  header{
    padding:22px 18px 8px;
    position:relative;
  }
  /* Header icon cluster. The CONTAINER is absolutely positioned top-right; the buttons
     are flex items inside it, so they lay out with a fixed gap and can never overlap or
     drop onto each other regardless of how many are shown or which stylesheet loads.
     (Replaces three separately absolute-positioned buttons - see index.html header note.) */
  .header-actions{
    position:absolute; top:16px; right:14px;
    display:flex; align-items:center; gap:8px;
    z-index:5;
  }
  .theme-toggle{
    width:38px; height:38px; flex:none;
    display:flex; align-items:center; justify-content:center;
    background:var(--glass); backdrop-filter:blur(14px);
    border:1px solid var(--glass-border-strong);
    border-radius:12px; cursor:pointer;
    color:var(--amber);
  }
  .theme-toggle svg{ width:18px; height:18px; stroke:currentColor; fill:none; stroke-width:1.8; stroke-linecap:round; stroke-linejoin:round; }
  .theme-toggle:active{ transform:scale(0.92); }
  .help-toggle{ color:var(--teal); }
  header .eyebrow{
    font-family:'JetBrains Mono',monospace;
    font-size:10.5px;
    letter-spacing:0.16em;
    text-transform:uppercase;
    color:var(--amber);
    margin-bottom:8px;
    display:flex; align-items:center; gap:6px;
  }
  header .eyebrow .brand-mark{ width:16px; height:16px; object-fit:contain; flex-shrink:0; }
  header .eyebrow .slash{color:var(--ink-faint);margin:0 6px;}
  header h1{
    font-family:'Big Shoulders Display',sans-serif;
    font-weight:800;
    font-size:36px;
    letter-spacing:0.005em;
    text-transform:uppercase;
    margin:0 0 4px;
    line-height:0.95;
    background:linear-gradient(100deg, var(--ink) 40%, var(--amber) 100%);
    -webkit-background-clip:text; background-clip:text; color:transparent;
  }
  header .sub{
    font-size:12px;
    font-family:'JetBrains Mono',monospace;
    color:var(--ink-dim);
  }
  /* Header account icon: findable entry to Settings' Account card / sign-out on every
     screen (auth, dev-only). Leftmost of the three; hidden until signed in. */
  .acct-toggle{ color:var(--ink-dim); }

  /* ---- Floating glass bottom navigation ---- */
  .bottomnav{
    position:fixed;
    left:14px; right:14px; bottom:calc(14px + env(safe-area-inset-bottom, 0px));
    z-index:40;
    display:flex;
    max-width:492px;
    margin:0 auto;
    background:var(--nav-bg);
    backdrop-filter:blur(22px) saturate(150%);
    -webkit-backdrop-filter:blur(22px) saturate(150%);
    border:1px solid var(--glass-border-strong);
    border-radius:20px;
    padding:6px;
    box-shadow:0 12px 32px rgba(0,0,0,0.45), inset 0 1px 0 rgba(255,255,255,0.06);
  }
  .navbtn{
    flex:1;
    display:flex;
    flex-direction:column;
    align-items:center;
    justify-content:center;
    gap:3px;
    background:none;
    border:none;
    border-radius:14px;
    padding:9px 4px 7px;
    color:var(--ink-faint);
    font-family:'JetBrains Mono',monospace;
    font-weight:600;
    font-size:9px;
    letter-spacing:0.03em;
    text-transform:uppercase;
    cursor:pointer;
    position:relative;
    transition:color .2s, background .2s;
  }
  .navbtn svg{ width:20px; height:20px; stroke:currentColor; fill:none; stroke-width:1.7; transition:transform .25s cubic-bezier(.34,1.56,.64,1); }
  .navbtn.active{ color:var(--bg-deep); background:var(--grad-amber); box-shadow:0 4px 14px rgba(245,166,35,0.35); }
  .navbtn.active svg{ transform:translateY(-1px) scale(1.08); stroke:var(--bg-deep); }
  .navbtn:active{ transform:scale(0.93); }

  /* Sub-tab bar: secondary navigation within a top-level page (Expenses/Daily,
     Savings/Timebank/.../Pay Calc). Hidden until a multi-tab page shows it. It WRAPS
     rather than scrolls: a horizontal scroll cue never reads reliably on a real phone
     (a soft fade over the exact tab that's clipped just hid the "there's more" hint),
     so instead every tab is simply visible - My Money's five wrap to a second row on a
     narrow screen. `white-space:nowrap` + `flex:1 1 auto` means a tab wraps whole; it is
     never split mid-letter. Rows that don't fill stretch their tabs to the full width. */
  .subtabs{ display:none; }
  .subtabs.show{
    display:flex; flex-wrap:wrap; gap:5px; margin-bottom:16px; padding:5px;
    background:var(--glass); border:1px solid var(--glass-border); border-radius:14px;
  }
  .subtab{
    flex:1 1 auto; min-height:44px; display:flex; align-items:center; justify-content:center;
    padding:0 14px; background:none; border:none; border-radius:10px;
    color:var(--ink-dim); font-family:'JetBrains Mono',monospace; font-weight:600;
    font-size:11px; letter-spacing:0.02em; text-transform:uppercase;
    cursor:pointer; white-space:nowrap; transition:color .2s, background .2s;
  }
  .subtab.active{ color:var(--bg-deep); background:var(--grad-amber); box-shadow:0 3px 10px rgba(245,166,35,0.3); }
  .subtab:active{ transform:scale(0.96); }

  .wrap{
    max-width:520px;
    margin:0 auto;
    padding:10px 14px 0;
    position:relative;
  }
  .tabpanel{display:none;}
  .tabpanel.active{display:block;}
  .tabpanel.entering{ animation: panelIn .28s cubic-bezier(.22,1,.36,1) both; }
  @keyframes panelIn{
    from{ opacity:0; transform:translateY(14px) scale(.985); }
    to{ opacity:1; transform:translateY(0) scale(1); }
  }
  .tabpanel.entering > *{ animation: itemIn .42s cubic-bezier(.22,1,.36,1) both; }
  .tabpanel.entering > *:nth-child(1){ animation-delay:.02s; }
  .tabpanel.entering > *:nth-child(2){ animation-delay:.07s; }
  .tabpanel.entering > *:nth-child(3){ animation-delay:.12s; }
  .tabpanel.entering > *:nth-child(4){ animation-delay:.17s; }
  .tabpanel.entering > *:nth-child(5){ animation-delay:.21s; }
  .tabpanel.entering > *:nth-child(n+6){ animation-delay:.25s; }
  @keyframes itemIn{
    from{ opacity:0; transform:translateY(10px); }
    to{ opacity:1; transform:translateY(0); }
  }
  @media (prefers-reduced-motion: reduce){
    .tabpanel.entering, .tabpanel.entering > *{ animation:none; }
  }

  /* Tap feedback */
  button{ -webkit-tap-highlight-color:transparent; }
  button:active, .item-row .del:active{ transform:scale(0.96); }
  .add-row-btn:active, .quick-btn:active, .save-day-btn:active, .clear-calc-btn:active{ transform:scale(0.97); }
  .log-add button:active{ transform:scale(0.92); }

  .item-row.row-leaving{ animation: rowLeave .22s ease forwards; }
  @keyframes rowLeave{
    to{ opacity:0; transform:translateX(24px); max-height:0; padding-top:0; padding-bottom:0; margin:0; }
  }
  .log-entry.row-leaving{ animation: rowLeave .22s ease forwards; }

  .grain::before{
    content:'';
    position:absolute; inset:0; border-radius:inherit;
    background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.5'/%3E%3C/svg%3E");
    opacity:0.045;
    mix-blend-mode:overlay;
    pointer-events:none;
  }

  /* ---- Bento grid (Dashboard quick stats) ---- */
  .page-intro{ margin:2px 0 16px; }
  .page-title{
    font-family:'Big Shoulders Display',sans-serif; font-weight:800; font-size:30px;
    text-transform:uppercase; letter-spacing:0.01em; margin:0 0 4px; color:var(--ink);
  }
  .page-sub{ font-size:12.5px; color:var(--ink-dim); margin:0; line-height:1.5; max-width:60ch; }
  .exp-summary{ margin-top:0; }
  .jump-link{
    background:none; border:none; cursor:pointer; padding:0;
    font-family:'JetBrains Mono',monospace; font-size:10.5px; font-weight:600;
    color:var(--amber); text-transform:uppercase; letter-spacing:0.04em;
    display:inline-flex; align-items:center; gap:4px;
  }
  .jump-link:hover{ text-decoration:underline; }
  .expense-grid{ display:contents; }
  /* Overview cards: display:contents on mobile so cards stack in DOM order exactly as a
     pair-grid did (no wrapper box) - mobile stays byte-identical. Becomes a 2-column flow
     at >=860px (see the media block), mirroring .expense-grid. */
  .dashboard-cards{ display:contents; }
  .pair-grid{ display:contents; }
  /* Groups two cards into one column of a pair-grid on desktop. Transparent on
     mobile (display:contents), so cards simply stack in DOM order. */
  .stack-col{ display:contents; }

  /* ---- Dashboard greeting ---- */
  .dash-greeting{
    font-family:'Big Shoulders Display',sans-serif; font-weight:700;
    font-size:22px; line-height:1.1; letter-spacing:0.01em;
    color:var(--ink); margin:2px 0 14px;
  }
  .dash-greeting:empty{ display:none; }

  /* ---- Dashboard hero: oversized leftover number + sprout mascot ---- */
  .dash-hero{
    display:flex; align-items:center; gap:10px;
    background:var(--glass);
    backdrop-filter:blur(20px) saturate(150%);
    -webkit-backdrop-filter:blur(20px) saturate(150%);
    color:var(--ink);
    border:1px solid var(--glass-border);
    border-radius:var(--radius);
    padding:22px 18px;
    position:relative;
    overflow:hidden;
    box-shadow:var(--card-shadow-lg);
  }
  .dash-hero::before{
    content:'';
    position:absolute; inset:-40%;
    background:conic-gradient(from 0deg, transparent, rgba(245,166,35,0.10), transparent 30%);
    animation:heroSpin 9s linear infinite;
    pointer-events:none;
  }
  @media (prefers-reduced-motion: reduce){ .dash-hero::before{ animation:none; } }
  @keyframes heroSpin{ to{ transform:rotate(360deg); } }
  .dash-hero-main{ flex:1 1 auto; min-width:0; position:relative; z-index:1; }
  .hero-label-row{ display:flex; align-items:center; justify-content:space-between; gap:8px; }
  .dash-hero .hero-label{
    font-size:11px;text-transform:uppercase;letter-spacing:0.14em;
    color:var(--amber);font-family:'JetBrains Mono',monospace;
  }
  /* Eye toggle that hides every on-screen figure (privacy mask). */
  .fig-toggle{
    flex:0 0 auto; display:inline-flex; align-items:center; justify-content:center;
    width:30px; height:30px; padding:0; border-radius:9px; cursor:pointer;
    background:var(--glass); border:1px solid var(--glass-border);
    color:var(--ink-dim); transition:color .15s, border-color .15s, background .15s;
  }
  .fig-toggle:hover{ color:var(--ink); border-color:var(--glass-border-strong); }
  .fig-toggle:focus-visible{ outline:2px solid var(--amber); outline-offset:2px; }
  .fig-toggle svg{ width:17px; height:17px; }
  body.figures-hidden .fig-toggle{ color:var(--amber); border-color:rgba(245,166,35,0.45); }
  .hero-flap{
    font-family:'Big Shoulders Display',sans-serif;
    font-weight:800;
    font-size:clamp(44px, 13vw, 68px);
    line-height:1;
    letter-spacing:-0.01em;
    margin:8px 0 10px;
    font-variant-numeric:tabular-nums;
    background:var(--hero-num-grad);
    -webkit-background-clip:text; background-clip:text; color:transparent;
  }
  .hero-status{
    display:inline-flex; align-items:center; gap:6px;
    font-family:'JetBrains Mono',monospace; font-size:10px; font-weight:600;
    text-transform:uppercase; letter-spacing:0.06em;
    padding:4px 10px; border-radius:999px;
    color:var(--ink-dim); background:var(--glass);
  }
  .hero-status::before{ content:''; width:6px; height:6px; border-radius:50%; background:currentColor; }
  .hero-status.good{ color:var(--olive); background:var(--olive-soft); }
  .hero-status.warn{ color:var(--red); background:var(--red-soft); }
  .hero-status.is-off{ display:none; }
  /* Sits under the hero number: says what "Free to Spend" means so the figure can't be misread. */
  .hero-caption{ font-size:11.5px; color:var(--ink-dim); margin:2px 0 8px; }

  /* ---- The hero's two supporting figures, and the way in to the balance ----
     The hero is the first thing on the screen and it was a stack of text: label, number, sentence.
     One number dominates and the other two sit under it as tiles, so the eye lands on the big one
     and can still find the other two without reading a paragraph. Deliberately NOT three equal
     numbers - three things shouting is the same as none of them shouting. */
  /* MOBILE FIRST: compact label-left / amount-right rows. Stacked tiles doubled the hero's height
     on a 375px screen for no gain, and the hero is the one card that must not need scrolling to
     read. The tile form is desktop-only, below the 860px breakpoint (CLAUDE.md §5). */
  .hero-figs{ display:flex; flex-wrap:wrap; align-items:stretch; gap:6px; margin:2px 0 10px; }
  .hero-fig{
    flex:1 1 100%; min-width:0;
    display:flex; flex-direction:row; align-items:baseline; justify-content:space-between; gap:10px;
    padding:6px 11px; border-radius:var(--radius-sm);
    background:var(--glass); border:1px solid var(--glass-border);
  }
  .hero-fig-label{
    font-family:'JetBrains Mono',monospace; font-size:9.5px; letter-spacing:0.10em;
    text-transform:uppercase; color:var(--ink-faint);
  }
  .hero-fig-amt{
    font-family:'JetBrains Mono',monospace; font-weight:700; font-size:15px;
    color:var(--ink); font-variant-numeric:tabular-nums;
  }
  /* app111: why the figure is what it is, when a bare number would mislead. Wraps to its own line
     inside the tile in BOTH layouts - the tile is a row on mobile and a column above 860px, and a
     full-basis third child lands correctly either way. */
  .hero-fig{ flex-wrap:wrap; }
  .hero-fig-note{
    flex:1 1 100%; font-size:10.5px; line-height:1.3; color:var(--ink-faint);
  }
  /* The short/square tile is the only coloured thing on the hero, so the colour means something. */
  .hero-fig.is-short{ border-color:rgba(255,92,122,0.30); }
  .hero-fig.is-short .hero-fig-amt{ color:var(--red); }
  .hero-fig.is-square{ border-color:rgba(138,154,91,0.35); }
  .hero-fig.is-square .hero-fig-amt{ font-size:12px; color:var(--olive); }
  /* The balance is the input every other figure on this card is derived from, so the way to change
     it lives beside them rather than inside a different card. */
  .hero-edit{
    flex:0 0 auto; align-self:center;
    background:var(--glass); border:1px solid var(--glass-border-strong); color:var(--ink);
    border-radius:999px; padding:9px 15px; cursor:pointer; white-space:nowrap;
    font-family:'JetBrains Mono',monospace; font-size:11px; letter-spacing:0.02em;
  }
  .hero-edit:hover{ border-color:var(--amber); color:var(--amber); }
  .hero-edit:focus-visible{ outline:2px solid var(--amber); outline-offset:2px; }
  /* One-time hero-meaning note (reuses .merge-note inside). */
  .intro-note{ margin:0 0 14px; }

  /* ---- Sprout mascot ---- */
  .hero-mascot{ flex:0 0 auto; width:80px; height:84px; position:relative; z-index:1; cursor:pointer; border-radius:12px; }
  .hero-mascot:focus-visible{ outline:2px solid var(--amber); outline-offset:3px; }
  .hero-mascot.mascot-hidden{ display:none; }
  .mascot-svg{ width:100%; height:100%; overflow:visible; }
  .m-shadow{ fill:rgba(0,0,0,0.28); }
  .m-pot{ fill:var(--amber); }
  .m-pot-rim{ fill:var(--amber-2); }
  .m-soil{ fill:#2c2015; }
  .m-stem{ stroke:var(--olive-2); stroke-width:3.2; fill:none; stroke-linecap:round; }
  .m-leaf{ fill:var(--olive); }
  .m-bud-body{ fill:var(--olive); }
  .m-eye{ fill:var(--bg-deep); }
  .m-mouth{ stroke:var(--bg-deep); stroke-width:1.5; fill:none; stroke-linecap:round; transform-box:fill-box; transform-origin:center; }
  .m-plant{ transform-box:fill-box; transform-origin:bottom center; animation:sway 4.6s ease-in-out infinite; }
  @keyframes sway{ 0%,100%{ transform:rotate(-2.5deg); } 50%{ transform:rotate(2.5deg); } }

  /* Bloom petals + thriving sparkle are hidden by default */
  .m-bloom{ opacity:0; transform-box:fill-box; transform-origin:center;
    transform:scale(0); transition:transform .45s cubic-bezier(.34,1.56,.64,1), opacity .3s; }
  .m-petal{ fill:#F4B8CC; }
  .m-spark{ fill:#FFE29A; opacity:0; transform-box:fill-box; transform-origin:center; }
  .m-drops{ opacity:0; }
  .m-drop{ fill:var(--teal-2); }
  .m-leaf-x{ opacity:0; transform-box:fill-box; transform-origin:bottom center;
    transform:scale(.35); transition:opacity .35s, transform .45s cubic-bezier(.34,1.56,.64,1); }

  /* Tier: neutral = base sprout (no class). thriving = brighter + perkier + sparkle. */
  .hero-mascot.thriving .m-plant{ animation-duration:3.1s; }
  .hero-mascot.thriving .m-leaf,
  .hero-mascot.thriving .m-bud-body{ fill:#B6DA6B; }
  .hero-mascot.thriving .m-spark{ opacity:1; animation:twinkle 2s ease-in-out infinite; }
  @keyframes twinkle{ 0%,100%{ opacity:.35; transform:scale(.7); } 50%{ opacity:1; transform:scale(1.1); } }
  /* Extra upper leaves fill out a thriving/blooming sprout (clear step up from steady). */
  .hero-mascot.thriving .m-leaf-x,
  .hero-mascot.bloom .m-leaf-x{ opacity:1; transform:scale(1); }

  /* Tier: bloom = flower opens, warm center, brightest foliage + gentle idle sway of the petals. */
  .hero-mascot.bloom .m-bloom{ opacity:1; animation:petalIdle 6s ease-in-out infinite; }
  @keyframes petalIdle{ 0%,100%{ transform:scale(1) rotate(-4deg); } 50%{ transform:scale(1) rotate(4deg); } }
  .hero-mascot.bloom .m-leaf{ fill:#C6E27A; }
  .hero-mascot.bloom .m-bud-body{ fill:#FFD36B; }
  .hero-mascot.bloom .m-plant{ animation-duration:3.4s; }

  /* Tier: wilt (mild) and wilt-deep (heavy) — clear multi-stage droop. */
  .hero-mascot.wilt .m-plant{ animation:none; transform:rotate(7deg) translateY(3px); }
  .hero-mascot.wilt .m-leaf, .hero-mascot.wilt .m-bud-body{ fill:#7f8a6a; }
  .hero-mascot.wilt .m-stem{ stroke:#6c7458; }
  .hero-mascot.wilt .m-mouth{ transform:rotate(180deg) translateY(-3.5px); }
  .hero-mascot.wilt-deep .m-plant{ transform:rotate(14deg) translateY(6px); }
  .hero-mascot.wilt-deep .m-leaf, .hero-mascot.wilt-deep .m-bud-body{ fill:#69735a; }
  .hero-mascot.wilt-deep .m-leaf-l{ transform-box:fill-box; transform-origin:right bottom; transform:rotate(10deg); }
  .hero-mascot.wilt-deep .m-leaf-r{ transform-box:fill-box; transform-origin:left bottom; transform:rotate(-10deg); }

  /* Watering flourish: droplets fall + bud gives a happy grow-bounce. */
  .hero-mascot.watering .m-drops{ animation:drip 1.4s ease-in forwards; }
  .hero-mascot.watering .m-bud{ transform-box:fill-box; transform-origin:bottom center; animation:growbounce 1.4s .1s ease-out; }
  @keyframes drip{ 0%{ opacity:0; transform:translateY(-6px); } 25%{ opacity:1; } 100%{ opacity:0; transform:translateY(12px); } }
  @keyframes growbounce{ 0%,100%{ transform:scale(1); } 40%{ transform:scale(1.18); } 70%{ transform:scale(.96); } }

  @media (prefers-reduced-motion: reduce){
    .m-plant, .m-spark,
    .hero-mascot.bloom .m-bloom,
    .hero-mascot.watering .m-drops, .hero-mascot.watering .m-bud{ animation:none; }
    .m-bloom, .m-leaf-x{ transition:none; }
    .hero-mascot.bloom .m-bloom{ opacity:1; }
  }
  /* Sprout animation turned off in Settings: freeze motion but keep the state
     (extra leaves, open flower) so the tier is still readable. */
  .hero-mascot.mascot-static .m-plant,
  .hero-mascot.mascot-static .m-spark,
  .hero-mascot.mascot-static.bloom .m-bloom,
  .hero-mascot.mascot-static.watering .m-drops,
  .hero-mascot.mascot-static.watering .m-bud{ animation:none; }
  .hero-mascot.mascot-static .m-bloom, .hero-mascot.mascot-static .m-leaf-x{ transition:none; }
  .hero-mascot.mascot-static.bloom .m-bloom{ opacity:1; }
  .hero-mascot.mascot-static.thriving .m-leaf-x,
  .hero-mascot.mascot-static.bloom .m-leaf-x{ opacity:1; transform:scale(1); }

  /* ---- Lighthouse mascot (default) ---------------------------------------------
     Which SVG shows is switched by data-mascot on #heroMascot. The sprout is hidden
     by default, so the lighthouse is also the fallback for any unknown/absent value. */
  .hero-mascot .mascot-sprout{ display:none; }
  .hero-mascot[data-mascot="sprout"] .mascot-sprout{ display:block; }
  .hero-mascot[data-mascot="sprout"] .mascot-lighthouse{ display:none; }

  /* Structure: light linework that reads on the dark hero; same silhouette as the eyebrow mark. */
  .mascot-lighthouse .lh-shadow{ fill:rgba(0,0,0,0.20); }
  .mascot-lighthouse .lh-body{ fill:#E9EDF3; stroke:#98A4B2; stroke-width:1.6; stroke-linejoin:round; }
  .mascot-lighthouse .lh-base{ fill:#C7D0DB; stroke:#98A4B2; stroke-width:1.6; stroke-linejoin:round; }
  .mascot-lighthouse .lh-gallery{ fill:#C7D0DB; stroke:#98A4B2; stroke-width:1.2; stroke-linejoin:round; }
  .mascot-lighthouse .lh-band{ stroke:#C24A63; stroke-width:5; }
  .mascot-lighthouse .lh-door{ fill:#5C6675; }
  .mascot-lighthouse .lh-frame{ fill:none; stroke:#7E8A99; stroke-width:1.6; stroke-linejoin:round; }
  .mascot-lighthouse .lh-glazing{ stroke:#7E8A99; stroke-width:1; }
  .mascot-lighthouse .lh-dome{ fill:#2E3949; stroke:#7E8A99; stroke-width:1.5; stroke-linejoin:round; }
  .mascot-lighthouse .lh-finial{ stroke:#7E8A99; stroke-width:1.6; stroke-linecap:round; }
  .mascot-lighthouse .lh-finial-ball{ fill:#7E8A99; }

  /* THE LAMP CORE - the lit glass. Its opacity is driven ONLY by --lamp-op, which is set
     solely in the five tier rules below (minimum 0.55). No animation, no reduced-motion rule,
     and no other selector ever touches this element, so the beacon can never go dark. */
  .mascot-lighthouse .lh-lamp-core{ fill:#FFDE97; opacity:var(--lamp-op, 0.9); }

  /* Emitted light: soft glow halo + rays. Tier-scaled and animated - SEPARATE from the core. */
  .mascot-lighthouse .lh-glow{ fill:#FFD37A; opacity:var(--glow-op, 0.42); filter:blur(5px); }
  .mascot-lighthouse .lh-rays line{ stroke:#FFD37A; stroke-width:2; stroke-linecap:round; opacity:var(--ray-op, 0.52); }
  .mascot-lighthouse .lh-rays{ transform-box:view-box; transform-origin:60px 36px; transform:scale(var(--ray-scale, 0.85)); }

  /* Tiers = beam brightness. --lamp-op floor is 0.55 (wilt-deep) and is set NOWHERE else. */
  .hero-mascot .mascot-lighthouse{ --lamp-op:0.90; --glow-op:0.42; --ray-op:0.52; --ray-scale:0.85; }   /* steady */
  .hero-mascot.thriving .mascot-lighthouse{ --lamp-op:1;    --glow-op:0.62; --ray-op:0.80; --ray-scale:1.0; }
  .hero-mascot.bloom .mascot-lighthouse{    --lamp-op:1;    --glow-op:0.85; --ray-op:1;    --ray-scale:1.15; }
  .hero-mascot.wilt .mascot-lighthouse{     --lamp-op:0.72; --glow-op:0.26; --ray-op:0.28; --ray-scale:0.62; }
  .hero-mascot.wilt-deep .mascot-lighthouse{ --lamp-op:0.55; --glow-op:0.14; --ray-op:0.12; --ray-scale:0.48; }

  /* Idle: rays gently breathe (transform only - never the core). Watering -> one-shot glow flare. */
  @keyframes beaconBreathe{ 0%,100%{ transform:scale(var(--ray-scale,0.85)); } 50%{ transform:scale(calc(var(--ray-scale,0.85) * 1.06)); } }
  .hero-mascot .mascot-lighthouse .lh-rays{ animation:beaconBreathe 4.2s ease-in-out infinite; }
  @keyframes beaconFlare{ 0%{ opacity:var(--glow-op,0.42); } 30%{ opacity:0.92; } 100%{ opacity:var(--glow-op,0.42); } }
  .hero-mascot.watering .mascot-lighthouse .lh-glow{ animation:beaconFlare 1.4s ease-out; }
  @media (prefers-reduced-motion: reduce){
    .hero-mascot .mascot-lighthouse .lh-rays{ animation:none; }
    .hero-mascot.watering .mascot-lighthouse .lh-glow{ animation:none; }
  }
  .hero-mascot.mascot-static .mascot-lighthouse .lh-rays{ animation:none; }
  .hero-mascot.mascot-static.watering .mascot-lighthouse .lh-glow{ animation:none; }

  /* ---- KPI tiles ---- */
  .kpi-row{
    display:grid; grid-template-columns:1fr 1fr; gap:10px; margin:12px 0;
  }
  /* Pay Calc has three KPIs (no "This Shift" tile). Three columns at every width - higher
     specificity than the base and the desktop repeat(4), so it wins in both. */
  .kpi-row.kpi-row-3{ grid-template-columns:repeat(3,1fr); }
  .kpi-tile{
    background:var(--glass);
    backdrop-filter:blur(18px) saturate(140%);
    -webkit-backdrop-filter:blur(18px) saturate(140%);
    border:1px solid var(--glass-border);
    border-radius:var(--radius-sm);
    padding:14px;
    position:relative;
    overflow:hidden;
  }
  .kpi-tile .kpi-icon{
    width:16px; height:16px; fill:none; stroke:var(--ink-faint);
    stroke-width:1.7; stroke-linecap:round; stroke-linejoin:round; margin-bottom:8px;
  }
  .kpi-tile:nth-child(1) .kpi-icon{ stroke:var(--olive); }
  .kpi-tile:nth-child(2) .kpi-icon{ stroke:var(--red); }
  .kpi-tile:nth-child(3) .kpi-icon{ stroke:var(--amber); }
  .kpi-tile:nth-child(4) .kpi-icon{ stroke:var(--olive); }
  .kpi-label{
    font-size:10px; text-transform:uppercase; letter-spacing:0.07em;
    color:var(--ink-dim); font-family:'JetBrains Mono',monospace; margin-bottom:5px;
  }
  .kpi-val{
    font-family:'Big Shoulders Display',sans-serif; font-weight:800; font-size:24px;
    font-variant-numeric:tabular-nums;
  }
  /* Pay-cycle dropdown on the Expenses KPI (weekly/fortnightly/monthly). Display only. */
  .kpi-cycle{
    margin-top:6px; width:auto; max-width:100%;
    padding:3px 22px 3px 7px; font-size:10.5px; font-family:'JetBrains Mono',monospace;
    color:var(--ink-dim); background:var(--glass); border:1px solid var(--glass-border);
    border-radius:6px; cursor:pointer;
  }
  .kpi-cycle:focus-visible{ outline:2px solid var(--amber); outline-offset:1px; }
  /* Caveat shown under Income/Expenses only when a non-weekly cycle is selected: the
     figure is the weekly rate scaled, not a confirmed total. Muted, small, unobtrusive. */
  .kpi-cycle-note{
    margin-top:5px; font-size:9.5px; line-height:1.35; color:var(--ink-faint);
    font-family:'JetBrains Mono',monospace;
  }
  .kpi-cycle-note[hidden]{ display:none; }
  /* Variable Income pay-cadence control + its persistent question. The question sits on a
     soft amber tint so it reads as a calm callout (never an error/alarm) and stays until
     the user picks a cadence. It's a plain question, so the tone is quiet, not urgent. */
  .var-freq{ display:flex; flex-wrap:wrap; align-items:center; gap:8px 12px; margin-bottom:14px; }
  .var-freq-q{ flex:1 1 100%; margin:0; padding:9px 12px; font-size:12px; line-height:1.45;
    color:var(--ink); background:var(--amber-soft); border-radius:8px; }
  .var-freq-q[hidden]{ display:none; }
  .var-freq-label{ display:inline-flex; align-items:center; gap:7px; font-size:10px;
    text-transform:uppercase; letter-spacing:0.05em; color:var(--ink-faint);
    font-family:'JetBrains Mono',monospace; }
  #varFreqSelect{ padding:5px 24px 5px 9px; font-size:12px; font-family:'JetBrains Mono',monospace;
    color:var(--ink); background:var(--glass); border:1px solid var(--glass-border-strong);
    border-radius:7px; cursor:pointer; text-transform:none; letter-spacing:normal; min-height:32px; }
  #varFreqSelect:focus-visible{ outline:2px solid var(--amber); outline-offset:1px; }
  /* Small qualifier under a KPI value (e.g. "this week's plan", or the Avg
     Leftover "estimated" marker when older entries predate the leftover snapshot). */
  .kpi-note{
    font-size:9px; letter-spacing:0.04em; color:var(--ink-faint);
    font-family:'JetBrains Mono',monospace; margin-top:4px; line-height:1.3;
  }
  .kpi-note:empty{ display:none; }
  /* Total-vs-pot breakdown under the daily KPI strip: keeps "total spent" and "against the
     plan" distinct. Hidden when nothing came from pots this week. */
  .kpi-pot-note{
    font-size:12px; letter-spacing:0.02em; color:var(--ink-faint);
    font-family:'JetBrains Mono',monospace; margin:10px 2px 0; line-height:1.4;
  }
  .kpi-pot-note:empty{ display:none; }
  /* Neutral, informational caption under the Pay Calc KPI strip: explains that Shift
     Hrs covers only days with recorded hours (marked with *). Deliberately NOT an
     error style - faint ink, no amber/red - because most weeks carry it until every
     day is re-saved and the user has done nothing wrong. */
  .pay-kpi-note{
    font-size:12px; letter-spacing:0.02em; color:var(--ink-faint);
    font-family:'JetBrains Mono',monospace; margin:10px 2px 0; line-height:1.4;
  }
  .pay-kpi-note:empty{ display:none; }

  /* ---- Bento tiles (Expenses summary; dashboard now uses .kpi-row) ---- */
  .bento{
    display:grid;
    grid-template-columns:1fr 1fr;
    gap:10px;
    margin:14px 0;
  }
  .bento-tile{
    background:var(--glass);
    backdrop-filter:blur(18px) saturate(140%);
    -webkit-backdrop-filter:blur(18px) saturate(140%);
    border:1px solid var(--glass-border);
    border-radius:var(--radius-sm);
    padding:14px;
    position:relative;
    overflow:hidden;
  }
  .bento-tile .bt-label{
    font-size:10px; text-transform:uppercase; letter-spacing:0.07em;
    color:var(--ink-dim); font-family:'JetBrains Mono',monospace; margin-bottom:6px;
  }
  .bento-tile .bt-val{
    font-family:'Big Shoulders Display',sans-serif; font-weight:800; font-size:24px;
  }
  .bento-tile .bt-icon{ position:absolute; top:10px; right:10px; width:16px; height:16px; opacity:0.5; stroke:currentColor; fill:none; stroke-width:1.6; }

  .icon-btn{ width:15px; height:15px; stroke:currentColor; fill:none; stroke-width:1.8; stroke-linecap:round; stroke-linejoin:round; vertical-align:-2px; }
  .arrow-icon{ width:13px; height:13px; stroke:currentColor; fill:none; stroke-width:2; stroke-linecap:round; stroke-linejoin:round; vertical-align:-2px; margin-right:2px; }

  section.card{
    background:var(--glass);
    backdrop-filter:blur(18px) saturate(140%);
    -webkit-backdrop-filter:blur(18px) saturate(140%);
    border:1px solid var(--glass-border);
    border-radius:var(--radius);
    margin-bottom:14px;
    overflow:hidden;
    box-shadow:var(--card-shadow);
  }
  /* Informational callout card (e.g. the Timebank explainer) — a soft amber wash
     and left accent so it reads as "read me" rather than a data card. */
  section.card.info-card{
    border-color:var(--amber-soft);
    border-left:3px solid var(--amber);
    background:linear-gradient(180deg, var(--amber-soft), var(--glass));
  }
  .card-head{
    display:flex;
    justify-content:space-between;
    align-items:center;
    padding:13px 15px;
    border-bottom:1px solid var(--glass-border);
    flex-wrap:wrap;   /* a header-mounted control (e.g. the benchmark select) drops
                         below the heading on a narrow card instead of overflowing. */
    row-gap:8px;
  }
  .card-head h2{
    font-family:'Big Shoulders Display',sans-serif;
    font-size:16px;
    font-weight:700;
    text-transform:uppercase;
    letter-spacing:0.02em;
    margin:0;
    color:var(--ink);
  }
  .card-head .subtotal{
    font-family:'JetBrains Mono',monospace;
    font-size:12.5px;
    font-weight:600;
    color:var(--amber);
  }
  /* Collapsible Expenses frequency cards (scoped to .exp-head so other cards are untouched). */
  .exp-head{ cursor:pointer; user-select:none; -webkit-user-select:none; }
  .exp-head:focus-visible{ outline:2px solid var(--amber); outline-offset:-2px; }
  .exp-head-title{ display:flex; align-items:center; gap:8px; min-width:0; }
  .exp-chevron{ width:15px; height:15px; flex-shrink:0; stroke:var(--ink-faint); stroke-width:2.2; fill:none; transition:transform 0.2s ease; }
  .exp-head.collapsed .exp-chevron{ transform:rotate(-90deg); }
  .exp-collapsed-meta{ font-family:'JetBrains Mono',monospace; font-size:11.5px; color:var(--ink-faint); padding:8px 15px 12px; }
  /* Compact period selector that sits in a card-head (e.g. Logged spending by category). */
  .mini-select{
    flex:0 0 auto; width:auto; min-width:0;
    padding:5px 8px; font-size:11px;
    font-family:'JetBrains Mono',monospace;
    border-radius:7px;
  }
  .card-body{padding:13px 15px 16px;}

  .plan-row{
    display:flex;
    justify-content:space-between;
    align-items:baseline;
    padding:8px 0;
    border-bottom:1px solid var(--glass-border);
    font-size:13px;
    color:var(--ink);
  }
  .plan-row:last-child{border-bottom:none;}
  .plan-row .amt{font-family:'JetBrains Mono',monospace;font-weight:600;}
  .plan-row.hero{
    background:linear-gradient(90deg, rgba(155,192,74,0.16), rgba(111,160,69,0.08));
    margin:8px -15px -16px;
    padding:13px 15px;
    border-bottom:none;
    border-left:3px solid var(--olive);
  }
  .plan-row.emerg{background:var(--red-soft);margin:0 -15px;padding:11px 15px;border-bottom:none;border-left:3px solid var(--red);}
  .plan-row.save{background:var(--olive-soft);margin:0 -15px;padding:11px 15px;border-bottom:none;border-left:3px solid var(--olive);}
  .plan-row.oneoff{background:var(--amber-soft);margin:0 -15px;padding:11px 15px;border-bottom:none;border-left:3px solid var(--amber);}
  .plan-row.emerg .label, .plan-row.save .label, .plan-row.oneoff .label{font-weight:600;color:var(--ink);}
  .plan-row.hero .label, .plan-row.hero .amt{font-size:15px;font-weight:700;color:var(--ink);}
  /* Note under the Emergency row: this tick MOVES money, so it says so before it's tapped.
     Continues the emergency row's red band (same bg + left border) so it reads as one unit. */
  .plan-row-note{background:var(--red-soft);margin:-1px -15px 0;padding:0 15px 10px;border-left:3px solid var(--red);font-size:11px;line-height:1.4;color:var(--ink-dim);}
  /* The "calculation" rows above the split: a plain leftover, a dimmed deduction, and
     a ruled "To allocate" subtotal. Kept visually quieter than the coloured split rows
     so the two kinds of row read differently (deduction vs allocation). */
  .plan-row.deduct .label, .plan-row.deduct .amt{color:var(--ink-dim);font-weight:500;}
  .plan-subtotal{
    display:flex; justify-content:space-between; align-items:baseline;
    border-top:1.5px solid var(--glass-border);
    margin:2px 0 4px; padding:9px 0 3px;
  }
  .plan-subtotal .label{font-weight:700;color:var(--ink);font-size:13px;}
  .plan-subtotal .amt{font-family:'JetBrains Mono',monospace;font-weight:700;color:var(--ink);font-size:15px;}

  /* ---- Weekly allocation checklist ----
     A quiet round tick per item (hollow ring -> olive-filled check when done). When
     done the row's AMOUNT dims, like a crossed-off list item, so a card of ticks reads
     as progress without a wall of green. */
  .alloc-tick{
    flex:0 0 auto; width:24px; height:24px; padding:0; border-radius:50%;
    border:1.6px solid var(--ink-faint); background:none; color:transparent;
    display:inline-flex; align-items:center; justify-content:center; cursor:pointer;
    transition:background .15s, border-color .15s, color .15s; -webkit-tap-highlight-color:transparent;
  }
  .alloc-tick svg{ width:14px; height:14px; }
  .alloc-tick:hover{ border-color:var(--olive); }
  .alloc-tick.done{ background:var(--olive); border-color:var(--olive); color:#fff; }
  /* Locked once ticked: it stays visibly done but can't be tapped again (undo is deleting the
     deposit in the pot's tab). No hover affordance, default cursor. */
  .alloc-tick.locked, .alloc-tick:disabled{ cursor:default; }
  .alloc-tick.locked:hover{ border-color:var(--olive); }
  .alloc-tick:focus-visible{ outline:2px solid var(--amber); outline-offset:2px; }
  .item-row.alloc-done .amt-wrap{ opacity:0.5; }
  .oo-card-head .alloc-tick{ margin-right:2px; }
  /* Dashboard plan: leading tick on the Emergency/Savings rows; the rollup bar. */
  .plan-row .label{ flex:1 1 auto; }
  .plan-row.alloc-done .amt{ opacity:0.55; }
  .plan-alloc{ display:flex; align-items:center; gap:8px; margin:0 0 11px; }
  .plan-alloc-bar{ flex:1 1 auto; height:5px; border-radius:3px; background:var(--glass-border); overflow:hidden; }
  .plan-alloc-fill{ height:100%; background:var(--olive); border-radius:3px; transition:width .3s ease; }
  .plan-alloc-label{ flex:0 0 auto; font-size:10.5px; font-family:'JetBrains Mono',monospace; color:var(--ink-dim); white-space:nowrap; }
  .plan-alloc.all-done .plan-alloc-label{ color:var(--olive); }

  .item-block{ border-bottom:1px solid var(--glass-border); }
  .item-block:last-of-type{ border-bottom:none; }
  .item-row{
    display:flex;
    align-items:center;
    gap:6px;
    padding:5px 0;
    flex-wrap:nowrap;   /* tick, name, amount and delete stay on ONE line - the name
                           input shrinks instead of the delete button wrapping below. */
  }
  .cat-icon{
    display:flex; align-items:center; justify-content:center;
    width:22px; height:22px; flex-shrink:0; color:var(--amber);
  }
  .cat-icon svg{ width:16px; height:16px; stroke:currentColor; fill:none; stroke-width:1.7; stroke-linecap:round; stroke-linejoin:round; }
  .due-row{
    display:flex; align-items:center; gap:6px; flex-wrap:wrap;
    padding:0 0 6px 28px; margin-top:-4px;
  }
  .cat-select{
    font-size:11px; padding:4px 6px; min-height:26px; width:auto;
    color:var(--ink-dim); background:transparent; border:1px dashed var(--glass-border-strong);
    max-width:160px;   /* fits the longest built-in category ("Debt Repayments") without clipping */
  }
  .due-icon{ width:13px; height:13px; stroke:var(--ink-faint); fill:none; stroke-width:1.6; stroke-linecap:round; stroke-linejoin:round; flex-shrink:0; }
  .due-input{
    font-size:11.5px; padding:4px 6px; min-height:26px; width:auto;
    color:var(--ink-dim); background:transparent; border:1px dashed var(--glass-border-strong);
  }
  .due-countdown{ font-size:11px; color:var(--ink-faint); font-family:'JetBrains Mono',monospace; }
  /* "Ticked Fri 8 Aug" - the date an allocation checkbox was ticked. Small, muted,
     sits at the trailing edge of the due row; only rendered while the tick is live
     (it clears with the tick on the next cycle). Olive echoes the ticked state quietly. */
  .alloc-stamp{ font-size:10.5px; color:var(--olive); font-family:'JetBrains Mono',monospace; margin-left:auto; white-space:nowrap; }
  /* Catch-up note: quiet supporting text under an item, aligned with the due row.
     Not a banner — muted body, the ongoing figure in ink, the catch-up in amber. */
  .exp-catchup{ font-size:11px; line-height:1.5; color:var(--ink-dim); padding:0 6px 9px 28px; margin-top:-3px; }
  .exp-catchup:empty{ display:none; padding:0; }
  .exp-catchup b{ color:var(--ink); font-weight:600; }
  .exp-catchup .cu-fig{ color:var(--amber); font-family:'JetBrains Mono',monospace; }
  /* Set-aside block: reset notice, covered chip, progress, and the two actions.
     Quiet and compact — only appears on bills with a gap, saved money, or a
     pending reset, so a long list never fills with progress bars. */
  .sa-reset{ color:var(--amber); margin-bottom:4px; }
  .sa-covered{ color:var(--olive); font-weight:600; margin-bottom:2px; }
  .sa-note{ margin-bottom:4px; }
  .sa-progress{ display:flex; align-items:center; gap:8px; margin:4px 0; }
  .sa-progress .progress-outer{ flex:1 1 auto; margin:0; }
  .sa-plabel{ flex:0 0 auto; font-family:'JetBrains Mono',monospace; color:var(--ink-dim); font-size:10px; white-space:nowrap; }
  .sa-actions{ display:flex; flex-wrap:wrap; align-items:center; gap:6px; margin-top:6px; }
  /* Field + button joined into one control (input flush-left, button flush-right)
     so they read as a single "add to set aside" unit rather than a cramped box beside
     a wide button. Wraps to its own row on a narrow card; "I'm covered" sits apart. */
  .sa-addgroup{ display:flex; flex:1 1 220px; min-width:0; }
  .sa-add-input{ flex:1 1 auto; min-width:0; width:auto; padding:6px 8px; font-size:12px; border-radius:7px 0 0 7px; border-right-width:0; }
  .sa-add-btn{ flex:0 0 auto; border-radius:0 7px 7px 0; white-space:nowrap; }
  /* Direct set-aside correction (quiet - the edit path, not the primary increment). */
  .sa-set{ display:inline-flex; align-items:center; gap:5px; font-size:11px; color:var(--ink-dim); font-family:'Public Sans',sans-serif; }
  /* Wide enough for a real value like 102.46 plus the number spinner, which the old
     66px clipped ("102.4(" ). */
  .sa-set-input{ width:92px; padding:5px 7px; font-size:12px; text-align:right; }
  .sa-btn{ background:var(--glass); border:1px solid var(--glass-border-strong); color:var(--ink-dim); border-radius:7px; padding:6px 11px; font-size:11px; cursor:pointer; font-family:'Public Sans',sans-serif; }
  .sa-btn:hover{ color:var(--ink); }
  .sa-cover{ border-color:rgba(155,192,74,0.45); color:var(--olive); }
  .sa-link{ background:none; border:none; color:var(--ink-faint); font-size:11px; cursor:pointer; text-decoration:underline; padding:2px 4px; font-family:'Public Sans',sans-serif; }
  .sa-link:hover{ color:var(--ink-dim); }
  /* Quiet early opt-in on a clean dated bill: subtle, no underline, not a button. */
  .sa-optin{ text-decoration:none; color:var(--ink-faint); padding:2px 0; }
  .sa-optin:hover{ color:var(--amber); }

  .upcoming-row{
    display:flex; align-items:center; gap:10px;
    padding:9px 0; border-bottom:1px solid var(--glass-border);
  }
  .upcoming-row:last-child{ border-bottom:none; }
  .upcoming-row .cat-icon{ background:var(--amber-soft); border-radius:8px; }
  .upcoming-row .up-info{ flex:1; min-width:0; }
  .upcoming-row .up-name{ font-size:13.5px; color:var(--ink); }
  .upcoming-row .up-when{ font-size:11px; color:var(--teal); font-family:'JetBrains Mono',monospace; }
  .upcoming-row .up-amt{ font-family:'JetBrains Mono',monospace; font-weight:700; font-size:13px; color:var(--ink); white-space:nowrap; }
  /* Summed cash-out footer: full bill amounts due in the next 7 days (not a weekly rate). */
  .upcoming-total{
    display:flex; align-items:baseline; justify-content:space-between; gap:10px;
    margin-top:6px; padding-top:11px; border-top:1.5px solid var(--glass-border-strong);
  }
  .up-total-label{ font-size:11px; text-transform:uppercase; letter-spacing:0.05em; color:var(--ink-dim); font-family:'JetBrains Mono',monospace; }
  .up-total-amt{ font-family:'Big Shoulders Display',sans-serif; font-weight:800; font-size:20px; color:var(--amber); font-variant-numeric:tabular-nums; white-space:nowrap; }

  /* ---- Bills First: the beside-build ----
     Presented as a comparison, not a verdict, because that is what it is right now: two answers to
     the same question with nothing switched over. The deduction rows read downward to a single
     total, the same shape the plan card already uses for its one-off deduction, so the arithmetic
     is followable without a legend. */
  .bf-intro{ margin:0 0 11px; font-size:12.5px; line-height:1.55; color:var(--ink-dim); }
  .bf-row{ display:flex; align-items:baseline; justify-content:space-between; gap:10px; padding:7px 0; }
  .bf-row + .bf-row{ border-top:1px solid var(--glass-border); }
  .bf-label{ font-size:13px; color:var(--ink); }
  .bf-amt{ font-family:'JetBrains Mono',monospace; font-size:13px; color:var(--ink); white-space:nowrap; font-variant-numeric:tabular-nums; }
  .bf-deduct .bf-amt{ color:var(--ink-dim); }
  .bf-why{ display:block; font-size:11px; color:var(--ink-faint); font-family:'JetBrains Mono',monospace; }
  .bf-tag{ font-family:'JetBrains Mono',monospace; font-size:10px; padding:1px 6px; border-radius:999px; white-space:nowrap; }
  .bf-tag-ok{ color:var(--teal); border:1px solid var(--teal); }
  .bf-tag-short{ color:var(--red); border:1px solid var(--red); }
  /* Stale balance: a statement of fact, carrying no claim that the money is there. */
  .bf-tag-plain{ color:var(--ink-faint); border:1px solid var(--glass-border-strong); }
  .bf-total{
    display:flex; align-items:baseline; justify-content:space-between; gap:10px;
    margin-top:6px; padding-top:11px; border-top:1.5px solid var(--glass-border-strong);
  }
  .bf-total .bf-label{ font-size:11px; text-transform:uppercase; letter-spacing:0.05em; color:var(--ink-dim); font-family:'JetBrains Mono',monospace; }
  .bf-total .bf-amt{ font-family:'Big Shoulders Display',sans-serif; font-weight:800; font-size:22px; color:var(--amber); }
  .bf-split{ margin-top:9px; padding-left:13px; border-left:2px solid var(--glass-border-strong); }
  .bf-srow{ display:flex; justify-content:space-between; gap:10px; padding:3px 0; font-size:12.5px; color:var(--ink-dim); }
  .bf-srow span:last-child{ font-family:'JetBrains Mono',monospace; color:var(--ink); font-variant-numeric:tabular-nums; }
  .bf-note{ margin-top:10px; }
  .bf-compare{ margin-top:15px; padding-top:13px; border-top:1px solid var(--glass-border); }
  .bf-compare-head{ font-family:'JetBrains Mono',monospace; font-size:10px; letter-spacing:0.12em; text-transform:uppercase; color:var(--ink-faint); margin-bottom:7px; }
  .bf-crow{ display:grid; grid-template-columns:1fr auto auto; gap:12px; padding:4px 0; font-size:12px; color:var(--ink-dim); }
  .bf-crow span:nth-child(2), .bf-crow span:nth-child(3){ font-family:'JetBrains Mono',monospace; text-align:right; min-width:74px; font-variant-numeric:tabular-nums; }
  .bf-crow span:nth-child(3){ color:var(--amber); }
  .bf-chead{ font-size:10px; text-transform:uppercase; letter-spacing:0.05em; color:var(--ink-faint); }

  /* The hero's second figure. Given real weight - it is one of the two numbers the hero exists for,
     not a footnote under the first. */
  .hero-caption{ font-family:'JetBrains Mono',monospace; font-size:13px; color:var(--amber); letter-spacing:0.01em; }
  /* What's Coming: pay period vs full cycle. A switch, not a link - it changes what you are looking
     at, and the long view must stay one tap away. */
  .pos-switch{ display:flex; gap:6px; margin:2px 0 9px; }
  .pos-swbtn{
    flex:1 1 0; background:none; border:1px solid var(--glass-border); color:var(--ink-faint);
    border-radius:999px; padding:5px 8px; cursor:pointer; white-space:nowrap;
    font-family:'JetBrains Mono',monospace; font-size:10.5px; letter-spacing:0.02em;
  }
  .pos-swbtn.is-on{ border-color:var(--amber); color:var(--amber); }
  /* What the balance has tracked since it was typed. */
  .pos-tracked{ margin-top:5px; font-size:11px; color:var(--ink-faint); font-family:'JetBrains Mono',monospace; }

  /* ---- Bill Buffer: the destination pot ----
     The drawdown ask sits at the TOP of Bills First because it is the only time-critical thing on
     the card: a direct debit bounces before anyone reads a timeline. Amber, not red - this is a
     thing you can still fix, and it should not look like a failure. */
  .bf-draw{
    background:var(--amber-soft); border:1px solid rgba(245,166,35,0.32);
    border-radius:var(--radius-sm); padding:10px 12px; margin-bottom:13px;
  }
  .bf-draw-line{ font-size:13px; line-height:1.5; color:var(--ink); margin-bottom:8px; }
  .bf-draw-btn{ width:100%; }
  .bf-draw-note{ margin-top:7px; font-size:11px; color:var(--ink-dim); font-family:'JetBrains Mono',monospace; }
  .bf-move-btn{ width:100%; margin-top:11px; }
  /* Both of these exist to stop the buffer being read as a second pile of money. */
  .bf-held{ margin-top:9px; }
  .bf-drift{ margin-top:9px; color:var(--amber); }
  /* The one moment worth marking. A quiet teal panel, not a banner: something changed and the app
     says so once, then stops going on about it. */
  .bf-grad-square{
    background:var(--teal-soft); border:1px solid rgba(34,211,184,0.28);
    border-radius:var(--radius-sm); padding:11px 12px;
  }
  .bf-grad-square .bf-grad-done{ font-size:14px; }
  .bf-grad-keep{ margin-top:8px; }

  .bb-of{ margin-top:4px; }
  /* Deposit / withdraw, on the pot's own page. The pot the whole catch-up model points at could
     not be paid into except through one conditional button on another tab. */
  .bb-form{ display:flex; flex-wrap:wrap; align-items:center; gap:8px; margin-top:12px; }
  .bb-amt{
    flex:1 1 110px; min-width:0;
    background:var(--input-bg); border:1px solid var(--glass-border-strong); color:var(--ink);
    border-radius:var(--radius-sm); padding:9px 11px;
    font-family:'JetBrains Mono',monospace; font-size:14px; font-variant-numeric:tabular-nums;
  }
  .bb-amt:focus{ outline:2px solid var(--amber); outline-offset:1px; }
  .bb-in-btn{ flex:0 0 auto; }
  .bb-out-btn[disabled]{ opacity:0.4; cursor:not-allowed; }
  .bb-form-note{ margin-top:7px; }
  .bb-row{ display:flex; align-items:center; gap:10px; padding:9px 0; }
  .bb-row + .bb-row{ border-top:1px solid var(--glass-border); }
  .bb-info{ flex:1; min-width:0; }
  .bb-note{ font-size:13px; color:var(--ink); }
  .bb-date{ font-size:11px; color:var(--ink-faint); font-family:'JetBrains Mono',monospace; }
  .bb-amt{ font-family:'JetBrains Mono',monospace; font-weight:700; font-size:13px; white-space:nowrap; font-variant-numeric:tabular-nums; }
  .bb-in{ color:var(--teal); }
  .bb-out{ color:var(--amber); }
  .bb-del{ flex:0 0 auto; font-size:16px; text-decoration:none; line-height:1; padding:0 4px; }

  /* ---- The graduation target and the three paces ----
     Three sentences, given room to be read as sentences rather than compressed into stats. The
     paces are buttons carrying a DATE, never an adjective: the date is the thing being traded and
     the label is only what it costs. */
  .bf-grad{ margin-top:15px; padding-top:13px; border-top:1px solid var(--glass-border); }
  .bf-grad-lines p{ margin:0 0 5px; font-size:13.5px; line-height:1.55; color:var(--ink-dim); }
  .bf-grad-lines p:last-child{ margin-bottom:0; color:var(--ink); }
  .bf-grad-lines b{ color:var(--ink); font-weight:600; }
  /* The moving-target explanation is PERMANENT, not a one-time tip: a figure that changes with no
     reason on screen reads as a broken app rather than as a target that moves with the bills. */
  .bf-grad-moves{ margin-top:9px; }
  .bf-grad-done{ margin:0; font-size:13px; line-height:1.55; color:var(--teal); }
  .bf-paces{ margin-top:13px; }
  .bf-pace-head{
    font-family:'JetBrains Mono',monospace; font-size:10px; letter-spacing:0.12em;
    text-transform:uppercase; color:var(--ink-faint); margin-bottom:7px;
  }
  .bf-pace{
    display:flex; align-items:baseline; justify-content:space-between; gap:12px; width:100%;
    background:var(--glass); border:1px solid var(--glass-border); border-radius:var(--radius-sm);
    padding:9px 11px; margin-bottom:6px; cursor:pointer; text-align:left; color:var(--ink);
  }
  .bf-pace:hover{ border-color:var(--glass-border-strong); }
  .bf-pace.is-on{ border-color:var(--amber); }
  .bf-pace[disabled]{ opacity:0.55; cursor:default; }
  .bf-pace-label{ font-size:12.5px; }
  .bf-pace-date{
    font-family:'JetBrains Mono',monospace; font-size:11px; color:var(--amber); white-space:nowrap;
  }
  .bf-pace.is-on .bf-pace-date{ font-weight:700; }
  .bf-pace[disabled] .bf-pace-date{ color:var(--ink-faint); }
  .bf-pace-note{ margin-top:8px; }

  /* ---- Overdue: the three-button answer ----
     Sits INSIDE the overdue block, directly under the bill it is about, so the date and the amount
     are on screen a line above the question. The buttons are equal weight on purpose: the app does
     not know which happened, and styling one as primary would be a guess dressed as a
     recommendation. Only one bill is asked at a time, oldest first. */
  .pos-ask-row{
    margin:8px 0 2px; padding:9px 10px;
    background:var(--panel-strong-bg); border-radius:var(--radius-sm);
  }
  .pos-ask-line{ font-size:12.5px; color:var(--ink); line-height:1.45; margin-bottom:8px; }
  .pos-obtns{ display:flex; flex-wrap:wrap; gap:7px; }
  .pos-obtn{
    flex:1 1 auto; min-width:96px;
    background:var(--glass); border:1px solid var(--glass-border-strong); color:var(--ink);
    border-radius:var(--radius-sm); padding:8px 10px; cursor:pointer;
    font-family:'JetBrains Mono',monospace; font-size:11px; letter-spacing:0.02em;
  }
  .pos-obtn:hover{ border-color:var(--amber); color:var(--amber); }
  /* A second bounce is a pattern, and the dates are what make it one. */
  .pos-ask-prior{
    margin-top:7px; font-size:11px; color:var(--red);
    font-family:'JetBrains Mono',monospace;
  }
  .pos-ask-rest{
    margin-top:7px; font-size:11px; color:var(--ink-dim);
    font-family:'JetBrains Mono',monospace;
  }

  /* How the bill is paid, on the Expenses due row. Two named options with the live one lit, so the
     state is readable without pressing anything - the single-button version could be read as either
     the current state or the action, and was. Unset lights the label instead of an option, because
     "neither is on" has to look deliberate rather than broken. */
  .bill-pay{ display:inline-flex; align-items:center; gap:4px; flex-wrap:wrap; }
  .bill-pay-lab{
    font-family:'JetBrains Mono',monospace; font-size:9.5px; letter-spacing:0.08em;
    text-transform:uppercase; color:var(--ink-faint); margin-right:1px;
  }
  .bill-pay.is-unset .bill-pay-lab{ color:var(--amber); }
  .bill-pay-opt{
    background:none; border:1px solid var(--glass-border); color:var(--ink-faint);
    border-radius:999px; padding:2px 9px; cursor:pointer; white-space:nowrap;
    font-family:'JetBrains Mono',monospace; font-size:10px; letter-spacing:0.02em;
  }
  .bill-pay-opt:hover{ border-color:var(--glass-border-strong); color:var(--ink-dim); }
  .bill-pay-opt.is-on{
    border-color:var(--amber); color:var(--amber);
    background:rgba(255,176,32,0.10);
  }

  /* ---- The verdict: the one sentence the whole card exists to produce ----
     Given the weight of a pull-quote, not a stat: it is prose, and it is the only thing on the card
     that is allowed to make a claim. Three tones, and the neutral one ('ask') is deliberately NOT
     alarming - "I cannot tell you yet" is a normal state for a new user, not a warning. A left rule
     carries the tone rather than a filled panel, so a shortfall reads as serious without the card
     shouting every time you open the app. */
  .pos-verdict{
    border-left:2.5px solid var(--ink-faint);
    padding:2px 0 2px 13px; margin:0 0 14px;
  }
  .pos-verdict-text{ margin:0; font-size:14.5px; line-height:1.55; color:var(--ink); }
  .pos-verdict-ok{ border-left-color:var(--teal); }
  .pos-verdict-short{ border-left-color:var(--red); }
  .pos-verdict-ask{ border-left-color:var(--glass-border-strong); }
  .pos-verdict-ask .pos-verdict-text{ color:var(--ink-dim); }
  /* Caveats sit UNDER the sentence, never inside it. A sentence carrying five qualifiers stops
     being read, and these are exactly the things that must not be skipped. */
  .pos-caveats{ margin:8px 0 0; padding-left:15px; }
  .pos-caveats li{
    font-size:11.5px; line-height:1.5; color:var(--ink-dim);
    font-family:'JetBrains Mono',monospace; margin-top:3px;
  }

  /* ---- Money set aside: the answer the verdict rests on, and how old it is ---- */
  .pos-bal{
    display:flex; flex-direction:column; gap:3px;
    padding:10px 12px; margin-bottom:13px;
    background:var(--glass); border:1px solid var(--glass-border); border-radius:var(--radius-sm);
  }
  .pos-bal-main{ display:flex; align-items:baseline; justify-content:space-between; gap:10px; }
  .pos-bal-label{
    font-size:11px; text-transform:uppercase; letter-spacing:0.05em;
    color:var(--ink-dim); font-family:'JetBrains Mono',monospace;
  }
  .pos-bal-amt{
    font-family:'Big Shoulders Display',sans-serif; font-weight:800; font-size:22px;
    color:var(--ink); font-variant-numeric:tabular-nums; white-space:nowrap;
  }
  /* The freshness line. Never hidden, never rounded away: a balance typed three weeks ago is not
     today's truth and the card says which it is, every single render. */
  .pos-bal-meta{
    font-size:11px; color:var(--ink-faint); font-family:'JetBrains Mono',monospace;
    display:flex; align-items:center; gap:6px; flex-wrap:wrap;
  }
  .pos-bal-stale{ color:var(--amber); }
  /* The two answers contradicting each other. Said in words, because the alternative was rendering
     "Money set aside: -$20.00", which is not a quantity of money anyone has. */
  .var-freq-hint{
    margin:6px 0 0; font-size:11px; line-height:1.5; color:var(--ink-faint);
    font-family:'JetBrains Mono',monospace;
  }
  .pos-bal-warn{
    margin-top:6px; font-size:11.5px; line-height:1.5; color:var(--amber);
  }

  .pos-ask{ margin-bottom:13px; }
  .pos-ask-q{ font-size:13.5px; color:var(--ink); font-weight:600; margin-bottom:4px; }
  .pos-q2{ margin-top:14px; }
  .pos-ask-why{ margin:0 0 9px; font-size:12px; line-height:1.55; color:var(--ink-dim); }
  .pos-ask-why b{ color:var(--ink); }

  .pos-form{ margin-bottom:13px; }
  .pos-acct{ display:flex; align-items:center; gap:7px; margin-bottom:7px; }
  .pos-acct input{ min-width:0; }
  .pos-acct .pos-acct-name, .pos-acct .pos-comm-note{ flex:1 1 auto; }
  .pos-acct .pos-acct-amt, .pos-acct .pos-comm-amt{ flex:0 0 92px; width:92px; }
  .pos-form-actions{ display:flex; align-items:center; gap:12px; margin-top:12px; }
  .pos-btn{
    background:none; border:1px dashed var(--amber); color:var(--amber);
    border-radius:var(--radius-sm); font-size:11.5px; font-weight:600; padding:8px 12px;
    cursor:pointer; font-family:'JetBrains Mono',monospace;
    text-transform:uppercase; letter-spacing:0.03em;
  }
  .pos-link{
    background:none; border:none; padding:0; cursor:pointer;
    font-family:'JetBrains Mono',monospace; font-size:11px; color:var(--ink-faint);
    text-decoration:underline; text-underline-offset:2px;
  }
  .pos-link:hover{ color:var(--amber); }
  .pos-del{ flex:0 0 auto; font-size:16px; text-decoration:none; line-height:1; padding:0 4px; }

  /* ---- What's Coming: the POSITION card ----
     A dated SPINE, not another list. The hairline runs the height of the card and every bill is a
     node on it, so the GAPS carry information - three bills in one week look crowded and a quiet
     fortnight looks quiet, which is the thing a row-per-bill list cannot show. Same rail vocabulary
     as the admin audit log, so the app has one way of drawing "things in time" rather than two.
     Colour is spent in exactly one place: red, on overdue. Everything else is ink and one amber
     total, because a card whose job is "do not panic unless you should" must not look alarming by
     default. */
  .pos-spine{ position:relative; margin:2px 0 0 0; padding-left:18px; }
  .pos-spine::before{
    content:''; position:absolute; left:3px; top:6px; bottom:6px;
    width:1px; background:var(--glass-border-strong);
  }
  .pos-month{
    font-family:'JetBrains Mono',monospace; font-size:10px; letter-spacing:0.12em;
    color:var(--ink-faint); text-transform:uppercase;
    margin:14px 0 2px; padding-top:2px;
  }
  .pos-spine .pos-month:first-child{ margin-top:4px; }
  .pos-row{ position:relative; display:flex; align-items:center; gap:10px; padding:8px 0; }
  .pos-row + .pos-row{ border-top:1px solid var(--glass-border); }
  .pos-node{
    position:absolute; left:-18px; top:50%; margin-top:-3px;
    width:7px; height:7px; border-radius:50%;
    background:var(--bg-deep); border:1.5px solid var(--amber);
  }
  .pos-info{ flex:1; min-width:0; }
  .pos-name{ font-size:13.5px; color:var(--ink); }
  .pos-when{ font-size:11px; color:var(--ink-dim); font-family:'JetBrains Mono',monospace; }
  .pos-amt{
    font-family:'JetBrains Mono',monospace; font-weight:700; font-size:13px;
    color:var(--ink); white-space:nowrap; font-variant-numeric:tabular-nums;
  }

  /* The per-row tick. An empty box that fills on hover and focus: at rest it is a question, and the
     check only appears under the pointer that is about to answer it. Sized for a thumb (36px) while
     drawing at 19px, so a crowded row does not become an unhittable one. The rows are ~60px tall,
     so a 42px target sits inside one without stretching it. */
  .pos-tick{
    flex:0 0 auto; width:42px; height:42px; margin:0 -8px 0 0;
    display:inline-flex; align-items:center; justify-content:center;
    background:none; border:none; padding:0; cursor:pointer; color:var(--ink-faint);
  }
  .pos-tick svg{
    width:19px; height:19px; fill:none; stroke:currentColor; stroke-width:1.6;
    stroke-linecap:round; stroke-linejoin:round;
  }
  .pos-tick .pos-tick-mark{ opacity:0; transition:opacity 120ms ease; }
  .pos-tick:hover, .pos-tick:focus-visible{ color:var(--green); }
  .pos-tick:hover .pos-tick-mark, .pos-tick:focus-visible .pos-tick-mark{ opacity:1; }
  .pos-overdue .pos-tick{ color:rgba(255,92,122,0.55); }
  .pos-overdue .pos-tick:hover, .pos-overdue .pos-tick:focus-visible{ color:var(--green); }

  /* Bills whose first payment falls past the eight-week window. Listed so a car registration in
     March is still visible, and visually separated so it cannot be read as part of the total. */
  .pos-beyond{
    margin-top:14px; padding-top:10px; border-top:1px dashed var(--glass-border-strong);
  }
  .pos-beyond .pos-row{ opacity:0.72; }
  .pos-beyond .pos-node{ border-color:var(--ink-faint); }
  .pos-total-soft{ opacity:0.8; }
  .pos-total-soft .pos-total-amt{ font-weight:600; }

  /* Ticked today, with a way back. Only today's, so it is a short list or no list at all. */
  .pos-paid{ margin-top:12px; }
  .pos-paid-row{
    display:flex; align-items:center; gap:10px; padding:5px 0;
    font-size:12.5px; color:var(--ink-dim);
  }
  .pos-paid-name{ flex:1; min-width:0; }
  .pos-paid-amt{
    font-family:'JetBrains Mono',monospace; font-size:11.5px;
    color:var(--ink-faint); font-variant-numeric:tabular-nums;
  }

  /* Overdue is its OWN block above everything, not a red row in the timeline. A bill that went a
     week ago is not part of what is coming, and filing it under the same heading reads as a lie. */
  .pos-overdue{
    background:var(--red-soft); border:1px solid rgba(255,92,122,0.28);
    border-radius:var(--radius-sm); padding:10px 12px; margin-bottom:12px;
  }
  .pos-section-head{
    font-family:'JetBrains Mono',monospace; font-size:10px; letter-spacing:0.14em;
    text-transform:uppercase; color:var(--ink-dim); margin-bottom:4px;
  }
  .pos-section-head-overdue{ color:var(--red); }
  .pos-overdue .pos-row{ padding:6px 0; }
  .pos-overdue .pos-row + .pos-row{ border-top:1px solid rgba(255,92,122,0.20); }
  .pos-overdue .pos-node{ display:none; }
  .pos-overdue .pos-when{ color:var(--red); }
  .pos-overdue-total{
    display:flex; justify-content:space-between; gap:10px;
    margin-top:7px; padding-top:7px; border-top:1px solid rgba(255,92,122,0.28);
    font-family:'JetBrains Mono',monospace; font-size:11.5px; font-weight:700; color:var(--red);
  }
  /* The "nothing is overdue" line. Stated, never implied by absence. */
  .pos-clear{
    margin:0 0 10px; font-size:12.5px; color:var(--teal);
    font-family:'JetBrains Mono',monospace;
  }
  .pos-horizon{ margin:0 0 4px; font-size:12.5px; color:var(--ink-dim); line-height:1.5; }
  .pos-horizon b{ color:var(--ink); font-weight:600; }
  .pos-total{
    display:flex; align-items:baseline; justify-content:space-between; gap:10px;
    margin-top:12px; padding-top:11px; border-top:1.5px solid var(--glass-border-strong);
  }
  .pos-total-label{
    font-size:11px; text-transform:uppercase; letter-spacing:0.05em;
    color:var(--ink-dim); font-family:'JetBrains Mono',monospace;
  }
  .pos-total-amt{
    font-family:'Big Shoulders Display',sans-serif; font-weight:800; font-size:20px;
    color:var(--amber); font-variant-numeric:tabular-nums; white-space:nowrap;
  }
  /* Empty state and coverage sentence: prose, deliberately not a stat. There is no number to show
     and inventing a 0 here would be the exact failure the card exists to prevent. */
  .pos-empty{ margin:0; font-size:13px; color:var(--ink-dim); line-height:1.6; }
  .pos-note{ margin-top:11px; }

  /* ---- Unified glass form controls ---- */
  input[type=text], input[type=number], input[type=date], select{
    border:1.5px solid var(--glass-border-strong);
    background:var(--input-bg);
    border-radius:var(--radius-sm);
    padding:8px 10px;
    font-size:14px;
    color:var(--ink);
    font-family:'Public Sans',sans-serif;
    min-height:38px;
  }
  input[type=number], input[type=date]{ font-family:'JetBrains Mono',monospace; }
  input:focus, select:focus{
    outline:none;
    border-color:var(--amber);
    box-shadow:0 0 0 3px rgba(245,166,35,0.18);
    background:var(--input-bg-focus);
  }
  input::placeholder{ color:var(--ink-faint); }
  select option{ background:var(--select-bg); color:var(--ink); }

  .item-row input[type=text]{
    flex:1 1 auto;
    min-width:90px;   /* the name is the row's primary job - keep it readable. The /wk
                         equivalent moved to the metadata row so this can hold width
                         without forcing the delete to wrap (row stays nowrap). */
    font-size:14px;
    padding:7px 9px;
  }
  .item-row .amt-wrap{
    display:flex;align-items:center;gap:5px;flex-shrink:0;
    font-family:'JetBrains Mono',monospace;
    font-size:13px;
  }
  .item-row input[type=number]{
    width:92px;
    text-align:right;
    padding:7px 8px;
    font-size:14px;
  }
  .item-row .del{
    border:none;background:none;color:var(--ink-faint);
    font-size:17px;cursor:pointer;padding:6px 2px;line-height:1;flex-shrink:0;
  }
  .item-row .del:hover{color:var(--red);}
  /* Weekly-equivalent of a non-weekly bill. Lives in the metadata row next to the
     category and due date - supporting detail, not competing with the name. */
  .equiv{
    font-size:11px;color:var(--ink-faint);
    font-family:'JetBrains Mono',monospace;
    white-space:nowrap;
  }
  .add-row-btn{
    margin-top:8px;
    background:none;border:1px dashed var(--amber);
    color:var(--amber);border-radius:var(--radius-sm);
    font-size:11.5px;font-weight:600;
    padding:8px 12px;
    cursor:pointer;font-family:'JetBrains Mono',monospace;
    text-transform:uppercase;letter-spacing:0.03em;
  }
  .add-row-btn:hover{background:var(--amber-soft);}

  .add-category-row{display:flex;gap:7px;margin-top:8px;}
  .add-category-row input{flex:1;}
  .add-category-row button{
    background:var(--grad-amber);border:none;border-radius:var(--radius-sm);
    color:var(--bg-deep);font-weight:700;font-size:12.5px;padding:0 14px;cursor:pointer;
  }
  .category-chip-row{display:flex;flex-wrap:wrap;gap:6px;margin-top:8px;}
  .category-chip{
    display:inline-flex;align-items:center;gap:5px;
    background:var(--glass);border:1px solid var(--glass-border);border-radius:20px;
    padding:4px 6px 4px 10px;font-size:11px;color:var(--ink-dim);
  }
  .category-chip button{
    background:none;border:none;color:var(--ink-faint);font-size:13px;line-height:1;
    cursor:pointer;padding:2px 4px;
  }
  .category-chip button:hover{color:var(--red);}

  .history-toggle{
    display:flex; align-items:center; gap:6px;
    margin-top:10px; margin-left:6px;
    background:none; border:none; cursor:pointer; padding:2px;
    color:var(--ink-faint); font-family:'JetBrains Mono',monospace;
    font-size:10.5px; text-transform:uppercase; letter-spacing:0.03em;
  }
  .history-toggle svg{ width:13px; height:13px; stroke:currentColor; fill:none; stroke-width:1.6; stroke-linecap:round; stroke-linejoin:round; }
  .history-toggle:hover{ color:var(--ink-dim); }
  .history-panel{ margin-top:6px; }
  .history-table{
    background:var(--panel-strong-bg); border-radius:var(--radius-sm);
    padding:4px 10px; margin-top:4px;
  }
  .history-row{
    display:flex; justify-content:space-between; padding:6px 0;
    border-bottom:1px solid var(--glass-border); font-size:12px;
  }
  .history-row:last-child{ border-bottom:none; }
  .history-date{ color:var(--ink-dim); font-family:'JetBrains Mono',monospace; }
  .history-amt{ color:var(--ink); font-family:'JetBrains Mono',monospace; font-weight:600; }

  .field-row{
    display:flex;justify-content:space-between;align-items:center;
    padding:8px 0;border-bottom:1px solid var(--glass-border);
    font-size:13px; color:var(--ink);
    gap:10px;
  }
  .field-row:last-child{border-bottom:none;}
  .field-row span:first-child{flex:1;}
  .field-row input{
    width:112px;text-align:right;font-size:14px;
  }
  .field-row .static{font-family:'JetBrains Mono',monospace;font-weight:600;font-size:14px;color:var(--ink);}

  .progress-outer{
    height:8px;background:rgba(255,255,255,0.06);border-radius:6px;overflow:hidden;margin:10px 0 4px;
    border:1px solid var(--glass-border);
  }
  .progress-inner{height:100%;background:var(--grad-teal);transition:width .4s cubic-bezier(.22,1,.36,1);}
  .progress-inner.warn{background:var(--grad-amber);}
  .progress-inner.over{background:var(--grad-red);}
  .progress-label{font-size:10.5px;color:var(--ink-dim);text-align:right;font-family:'JetBrains Mono',monospace;}

  /* ---- Savings goals (waterfall list) ---- */
  .goal-item{
    padding:12px 0;border-bottom:1px solid var(--glass-border);
  }
  .goal-item:first-child{padding-top:0;}
  .goal-actions{display:flex;align-items:center;gap:8px;margin-top:10px;}
  .goal-move{
    width:28px;height:28px;flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;
    border-radius:8px;border:1px solid var(--glass-border);background:rgba(255,255,255,0.04);
    color:var(--ink-dim);font-size:14px;line-height:1;cursor:pointer;transition:background .15s,color .15s;
  }
  .goal-move:hover:not(:disabled){background:rgba(255,255,255,0.09);color:var(--ink);}
  .goal-move:disabled{opacity:0.3;cursor:default;}
  .goal-del{
    margin-left:auto;padding:6px 12px;border-radius:8px;border:1px solid var(--glass-border);
    background:transparent;color:var(--ink-dim);font-size:11.5px;cursor:pointer;transition:color .15s,border-color .15s;
  }
  .goal-del:hover{color:#FF5C7A;border-color:rgba(255,92,122,0.5);}
  .goal-add-wrap{margin-top:14px;}

  /* ---- Category budgets (read-only allocated list) ---- */
  .budget-cap-row{
    display:flex;justify-content:space-between;align-items:center;
    padding:10px 0;border-bottom:1px solid var(--glass-border);font-size:13.5px;
  }
  .budget-cap-row:last-child{border-bottom:none;}
  .budget-cap-name{font-weight:600;color:var(--ink);}
  .budget-cap-spend{font-family:'JetBrains Mono',monospace;font-size:12px;color:var(--ink-dim);}

  /* ---- Due-soon reminder banner (dismissible, dashboard) ---- */
  .reminder-banner{display:flex;flex-direction:column;gap:8px;margin-bottom:14px;}
  .reminder-pill{
    display:flex;align-items:center;gap:10px;padding:10px 12px;border-radius:var(--radius-sm);
    background:var(--red-soft);border:1px solid rgba(255,92,122,0.35);
  }
  .reminder-text{flex:1;font-size:12.5px;color:var(--ink);}
  .reminder-dismiss{
    background:none;border:none;color:var(--ink-dim);font-size:18px;line-height:1;cursor:pointer;
    padding:2px 6px;flex-shrink:0;
  }
  .reminder-dismiss:hover{color:var(--ink);}

  /* ---- My Daily Spend ---- */
  .daily-day-group{margin-bottom:12px;}
  .daily-day-group:last-child{margin-bottom:0;}
  .daily-day-head{
    display:flex;justify-content:space-between;align-items:center;
    font-family:'JetBrains Mono',monospace;font-size:11px;color:var(--ink-dim);
    text-transform:uppercase;letter-spacing:0.05em;padding-bottom:5px;
    border-bottom:1px solid var(--glass-border-strong);margin-bottom:2px;
  }
  .daily-day-head .amt{color:var(--amber);font-weight:700;}
  .daily-thumb{width:32px;height:32px;border-radius:7px;object-fit:cover;flex-shrink:0;margin-right:8px;}
  .daily-day-group .log-entry .lhs{display:flex;align-items:center;flex-direction:row;}

  /* ---- Calendar (Daily Spend) ---- */
  .cal-nav{display:flex;align-items:center;gap:10px;}
  .cal-nav-btn{
    background:var(--glass);border:1px solid var(--glass-border);border-radius:8px;
    color:var(--ink);width:26px;height:26px;font-size:15px;line-height:1;cursor:pointer;
  }
  .cal-nav-btn:active{transform:scale(0.92);}
  /* Bounded nav: an arrow greys out when there is nothing further that way. */
  .cal-nav-btn:disabled{opacity:0.3;cursor:default;}
  .cal-nav-btn:disabled:active{transform:none;}

  /* History jump-line: the escape hatch out of a scoped month. Styled as clear accent
     controls, not muted status text, and placed above the list so they catch the eye
     the moment a month looks empty and someone fears their data is gone. */
  .hist-jump{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin:0 0 12px;}
  .hist-jump-btn{
    display:inline-flex;align-items:center;gap:6px;
    background:var(--amber-soft);color:var(--amber);border:none;border-radius:999px;
    padding:5px 12px;font-size:12px;font-weight:600;cursor:pointer;
    font-family:'Public Sans',sans-serif;line-height:1.2;
  }
  .hist-jump-btn:hover{background:var(--amber);color:var(--bg-deep);}
  .hist-jump-sep{color:var(--ink-faint);font-size:12px;}
  .cal-month-label{
    font-family:'JetBrains Mono',monospace;font-size:11.5px;color:var(--ink-dim);
    min-width:84px;text-align:center;
  }
  .cal-weekday-row{
    display:grid;grid-template-columns:repeat(7,1fr);gap:4px;margin-bottom:6px;
    font-family:'JetBrains Mono',monospace;font-size:10px;color:var(--ink-faint);
    text-align:center;text-transform:uppercase;
  }
  .cal-grid{display:grid;grid-template-columns:repeat(7,1fr);gap:4px;}
  .cal-day{
    aspect-ratio:1;display:flex;flex-direction:column;align-items:center;justify-content:center;
    border-radius:9px;background:var(--glass);border:1px solid var(--glass-border);
    cursor:pointer;position:relative;
  }
  .cal-day.empty{background:none;border:none;cursor:default;}
  .cal-day.today{border-color:var(--amber);}
  .cal-day.selected{border-color:var(--ink);box-shadow:0 0 0 1px var(--ink) inset;}
  .cal-day .cal-daynum{font-size:11px;font-weight:600;color:var(--ink);}
  .cal-day .cal-dayamt{font-size:8px;font-family:'JetBrains Mono',monospace;color:var(--ink-dim);margin-top:1px;}
  .cal-day.ok{background:var(--teal-soft);border-color:rgba(34,211,184,0.35);}
  .cal-day.warn{background:var(--amber-soft);border-color:rgba(245,166,35,0.35);}
  .cal-day.over{background:var(--red-soft);border-color:rgba(255,92,122,0.35);}
  .cal-legend{display:flex;gap:14px;flex-wrap:wrap;margin-top:12px;}
  .cal-legend-item{display:flex;align-items:center;gap:5px;font-size:10.5px;color:var(--ink-dim);}
  .cal-dot{width:8px;height:8px;border-radius:50%;display:inline-block;}
  .cal-dot.ok{background:var(--olive);}
  .cal-dot.warn{background:var(--amber);}
  .cal-dot.over{background:var(--red);}
  #calDayDetail{margin-top:12px;}
  #calDayDetail .cal-detail-head{
    display:flex;justify-content:space-between;align-items:center;
    font-family:'JetBrains Mono',monospace;font-size:11px;color:var(--ink-dim);
    text-transform:uppercase;letter-spacing:0.05em;padding-bottom:6px;
    border-bottom:1px solid var(--glass-border-strong);margin-bottom:2px;
  }
  #calDayDetail .cal-detail-head .amt{color:var(--amber);font-weight:700;}
  #calDayDetail .log-entry .lhs{display:flex;align-items:center;flex-direction:row;}

  /* ---- Net Position (dashboard) ---- */
  .net-position-total{
    border-top:1px solid var(--glass-border-strong);margin-top:6px;padding-top:12px;
  }
  .net-position-total span:first-child{font-weight:700;color:var(--ink);}
  .net-position-total .static{font-size:17px;font-weight:800;}

  .log-entry{
    display:flex;justify-content:space-between;align-items:center;
    padding:8px 0;border-bottom:1px solid var(--glass-border);font-size:12.5px;
    gap:8px; color:var(--ink);
  }
  .log-entry:last-child{border-bottom:none;}
  .log-entry .lhs{display:flex;flex-direction:column;}
  .log-entry .date{font-size:11px;color:var(--ink-dim);font-family:'JetBrains Mono',monospace;}
  .log-entry .note{font-size:11px;color:var(--ink-faint);font-style:italic;}
  .log-entry .amt{font-family:'JetBrains Mono',monospace;font-weight:700;white-space:nowrap;}
  .log-entry .amt.dep{color:var(--olive);}
  .log-entry .amt.wd{color:var(--red);}
  .log-entry .del{border:none;background:none;color:var(--ink-faint);cursor:pointer;font-size:14px;flex-shrink:0;}
  /* Variable Income: a pay period's breakdown (main pay + extra amounts) and the inline
     "add another amount" row on the current period. Mobile-first; the current entry reads as
     a small highlighted card so "This period" is obviously where new amounts land. */
  .log-entry-wrap{ border-bottom:1px solid var(--glass-border); }
  .log-entry-wrap:last-child{ border-bottom:none; }
  .log-entry-wrap > .log-entry{ border-bottom:none; }
  .log-entry-wrap.current{ background:var(--glass-strong); border:1px solid var(--glass-border-strong);
    border-radius:12px; padding:4px 10px 10px; margin:8px 0; }
  .inc-tag{ font-size:9.5px; font-weight:700; letter-spacing:0.05em; text-transform:uppercase;
    color:var(--amber); background:var(--glass-strong); padding:1px 7px; border-radius:999px;
    align-self:flex-start; margin-top:3px; }
  .inc-items{ display:flex; flex-direction:column; gap:5px; padding:2px 0 4px; }
  .inc-item{ display:flex; align-items:center; gap:8px; font-size:12px; color:var(--ink-dim); }
  .inc-item-name{ flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .inc-item-amt{ font-family:'JetBrains Mono',monospace; white-space:nowrap; color:var(--ink); }
  .inc-item-del{ border:none; background:none; color:var(--ink-faint); cursor:pointer; font-size:17px;
    line-height:1; width:24px; height:24px; flex-shrink:0; border-radius:6px; }
  .inc-item-del:active{ transform:scale(0.9); }
  .inc-add-item{ display:flex; flex-wrap:wrap; gap:7px; margin-top:8px; }
  .inc-add-item input{ padding:9px 10px; border-radius:9px; border:1px solid var(--glass-border);
    background:var(--bg-deep-2); color:var(--ink); font-size:14px; }
  .inc-add-item input[type=number]{ flex:1; min-width:90px; text-align:right; }
  .inc-add-item input[type=text]{ flex:2; min-width:110px; }
  .inc-add-item button{ flex:0 0 auto; padding:9px 15px; border:none; border-radius:9px;
    background:var(--amber); color:#1a1205; font-weight:700; font-size:13px; cursor:pointer; }
  .inc-add-item button:active{ transform:scale(0.94); }
  .tag{
    font-size:9px;text-transform:uppercase;letter-spacing:0.04em;
    padding:2px 6px;border-radius:5px;font-family:'JetBrains Mono',monospace;font-weight:700;
    display:inline-block;margin-right:6px;
  }
  .tag.dep{background:var(--olive-soft);color:var(--olive);}
  .tag.wd{background:var(--red-soft);color:var(--red);}
  /* Quiet "from Excess/Savings" hint on a funded daily-spend row - muted so it never
     competes with the note or amount, just confirms the spend was drawn from a pot. */
  .funded-tag{font-size:10px;color:var(--ink-faint);font-style:italic;white-space:nowrap;}

  /* Daily Budget card in pot-drawdown mode: a subtle tint + coloured bar tied to the
     ledger's own tab colour (Excess olive, Savings teal), so switching the benchmark
     from a category to a pot visibly changes what the card is, not just its numbers. */
  #dailyBudgetStatCard.pot-mode-excess{ background:var(--olive-soft); }
  #dailyBudgetStatCard.pot-mode-savings{ background:var(--teal-soft); }
  .progress-inner.pot-excess{ background:var(--olive); }
  .progress-inner.pot-savings{ background:var(--teal); }

  /* Funding-source picker on the log form: a low-key labelled select on its own line,
     kept visually subordinate to the main log-add row since most spends won't set it. */
  .funded-from-row{display:flex;align-items:center;gap:9px;margin-top:7px;}
  .funded-from-row label{font-size:11px;text-transform:uppercase;letter-spacing:0.03em;
    color:var(--ink-faint);font-family:'JetBrains Mono',monospace;white-space:nowrap;flex:0 0 auto;}
  /* Fill the row like the form's other controls (up to a cap that lines up with the
     category select above), same height and font - so it reads as a finished field,
     not a narrow control floating in empty space. */
  .funded-from-row select{font-family:'JetBrains Mono',monospace;font-size:13.5px;
    flex:1 1 auto;min-width:0;max-width:300px;height:37px;padding:0 10px;}
  /* Follow caption under "Paid from": quiet one-liner shown while the picker tracks the
     pot benchmark, so the coupling reads as deliberate. Hidden once the user overrides. */
  .funded-follow{font-size:11px;color:var(--ink-faint);font-style:italic;margin-top:5px;line-height:1.4;}

  /* Benchmark control (Compare against) mounted in the Daily Budget card header. */
  .dbs-benchmark{display:flex;align-items:center;gap:7px;}
  .dbs-benchmark label{font-size:10px;text-transform:uppercase;letter-spacing:0.03em;
    color:var(--ink-faint);font-family:'JetBrains Mono',monospace;white-space:nowrap;}
  .dbs-benchmark select{font-family:'JetBrains Mono',monospace;font-size:12.5px;max-width:200px;padding:4px 7px;}
  /* The budget card sits high on the tab now - keep its rows compact. */
  #dailyBudgetStatCard .field-row{padding:6px 0;}

  .log-add{display:flex;flex-wrap:wrap;gap:7px;margin-top:10px;}
  .log-add input, .log-add select{
    font-family:'JetBrains Mono',monospace;font-size:13.5px;
  }
  .log-add input[type=date]{flex:1.3;min-width:130px;}
  /* Labelled date field in an add-row: a type=date can't show a placeholder, so an
     empty one reads as a blank dropdown - this captions it ("Due date") like the rest. */
  .log-add-date{ display:flex; flex-direction:column; gap:2px; flex:1.3; min-width:130px;
    font-size:9px; text-transform:uppercase; letter-spacing:0.03em; color:var(--ink-faint); font-family:'JetBrains Mono',monospace; }
  .log-add-date input[type=date]{ flex:none; width:100%; min-width:0; }
  /* Wide enough for the longest fixed option a log-add select carries - "Fortnightly" /
     "Half-yearly" (frequency) and "Liability" (account type) - and flex-grows to fill the
     line for long category names when the row wraps. */
  .log-add select{flex:1 1 140px;min-width:140px;}
  /* Category pickers carry the longest free-text options ("Health & Fitness",
     "Memberships & subscriptions"), so give them a bigger basis to claim more of the
     line and wrap sooner. Frequency/type selects keep the tighter 140px above. */
  #dsCat, #ooCat, #taxCategory{ flex-basis:176px; }
  .log-add input[type=number]{flex:1;min-width:90px;text-align:right;}
  .log-add input[type=text].note-input{flex:2;min-width:110px;font-family:'Public Sans',sans-serif;font-size:14px;}
  /* The longest name placeholders (Source / Account name / New folder name) take their own
     row on mobile so they aren't clipped - but ONLY on the panels where that costs NO extra
     height (measured: 0px delta), so no add-form grows taller. Other panels' shorter
     placeholders fit inline at standard mobile widths; My Tax is out of scope entirely. */
  @media (max-width:859px){
    #panel-dashboard .log-add input[type=text].note-input,
    #panel-networth .log-add input[type=text].note-input,
    #panel-library .log-add input[type=text].note-input{ flex:1 1 100%; }
  }
  .log-add button{
    background:var(--grad-amber);color:var(--bg-deep);border:none;
    border-radius:var(--radius-sm);padding:0 16px;font-size:19px;cursor:pointer;font-weight:700;
    min-width:44px;
  }
  .quick-btn{
    width:100%;margin-top:10px;
    background:var(--grad-olive);color:#0c1705;border:none;
    border-radius:var(--radius-sm);padding:11px;font-size:12.5px;font-weight:700;
    cursor:pointer;font-family:'JetBrains Mono',monospace;
    text-transform:uppercase;letter-spacing:0.03em;
    box-shadow:0 6px 18px rgba(155,192,74,0.25);
  }
  .quick-btn:hover{opacity:.92;}
  /* "Added this week - tap to undo": the Emergency quick-add reflects that the deposit is
     already made, so it drops the strong green fill for a soft, clearly-toggleable look. */
  .quick-btn.is-done{background:var(--olive-soft);color:var(--ink);box-shadow:none;text-transform:none;letter-spacing:normal;font-weight:600;cursor:default;opacity:1;}

  .proj-table{width:100%;border-collapse:collapse;font-size:13px;margin-top:10px;}
  .proj-table td{padding:6px 0;border-bottom:1px solid var(--glass-border);font-family:'JetBrains Mono',monospace;color:var(--ink);}
  .proj-table td:first-child{font-family:'Public Sans',sans-serif;color:var(--ink-dim);}
  .proj-table td:last-child{text-align:right;font-weight:700;}
  .proj-table tr:last-child td{border-bottom:none;}

  .chart-wrap{position:relative;height:190px;margin-top:8px;}
  .chart-wrap.short{height:150px;}
  .chart-wrap.donut{height:220px;}
  .chart-fallback{
    font-family:'JetBrains Mono',monospace;font-size:11.5px;color:var(--ink-dim);
    text-align:center;padding:30px 10px;
  }

  .note{font-size:11px;color:var(--ink-dim);line-height:1.5;margin-top:8px;}

  /* ---- Admin dashboard (read only, step 1) ---------------------------------
     Reuses the card/field-row vocabulary; these only add the list rows, the status
     pills and the accepted-vs-withdrawn distinction. Mobile-first like everything
     else: the meta lines wrap, so nothing here needs a desktop breakpoint. */
  /* ============================================================================
     ADMIN CONSOLE — presentation only (app79). Nothing here adds or removes a
     capability; it is the same markup, given a hierarchy.

     THE IDEA: every other tab in this app is about money, and uses the amber and
     teal gradients to say so. This screen is about CONSEQUENCE - each row is an
     irreversible act somebody will one day have to account for. So it is the
     QUIETEST surface in the product: no gradient, no glow, and colour used for
     exactly one purpose, marking how much an action costs. If something here is
     coloured, it mattered.

     THE SIGNATURE is the ledger rail: one hairline running the length of the audit
     list with each entry's severity marker sitting ON it, broken by labelled day
     nodes. It encodes what the content actually is - a continuous, chronological,
     permanent record read downward - rather than a stack of boxes. It is the one
     accessory; everything around it stays plain.

     Type does three jobs and no more: Big Shoulders for card titles (small, tracked,
     uppercase - an instrument plate, not a headline), Public Sans for the one prose
     sentence per entry, JetBrains Mono for anything that must align or be read out
     loud - times, ids, status, counts.
     ============================================================================ */

  /* Card titles across the console. Distinct from the money tabs on purpose. */
  #panel-admin .card-head h2{
    font-family:'Big Shoulders Display',sans-serif;
    font-size:15px;font-weight:700;letter-spacing:0.09em;text-transform:uppercase;
    color:var(--ink-dim);
  }
  #panel-admin .card{ margin-bottom:18px; }

  /* Filters: their own band, separated by space rather than another border. */
  /* Consent detail (app81). A missing value is never a blank - it carries the reason instead,
     set in a quieter, italic voice so it reads as an explanation rather than as data. A blank in
     a consent audit reads as an ABSENCE OF CONSENT, which is the opposite of the truth. */
  .adm-drow{
    display:flex;gap:10px;align-items:baseline;padding:5px 0;
    border-bottom:1px solid var(--line);
  }
  .adm-drow:last-child{border-bottom:none;}
  .adm-dlabel{
    flex:none;min-width:150px;font-size:10.5px;letter-spacing:0.04em;text-transform:uppercase;
    color:var(--ink-faint);font-family:'JetBrains Mono',monospace;
  }
  .adm-val{font-size:13px;color:var(--ink);}
  .adm-nocap{font-size:12px;color:var(--ink-dim);font-style:italic;}
  .adm-doc-btn{
    background:none;border:1px solid var(--line);border-radius:var(--radius-sm);
    padding:4px 10px;font-size:11px;color:var(--ink-dim);cursor:pointer;
  }
  .adm-doc-btn:hover{border-color:var(--glass-border-strong);color:var(--ink);}
  .adm-doc-btn:focus-visible{outline:2px solid var(--amber);outline-offset:2px;}
  .adm-doc{margin-top:12px;padding-top:12px;border-top:1px solid var(--line);}
  .adm-doc-body{
    max-height:320px;overflow:auto;margin-top:8px;padding:10px;
    background:var(--panel-strong-bg);border-radius:var(--radius-sm);
    font-family:'JetBrains Mono',monospace;font-size:10.5px;line-height:1.5;
    white-space:pre-wrap;word-break:break-word;color:var(--ink-dim);
  }
  .adm-audit-filters{
    display:grid;grid-template-columns:1fr;gap:10px;
    margin:0 0 18px;padding-bottom:16px;border-bottom:1px solid var(--line);
  }
  .adm-field{display:flex;flex-direction:column;gap:5px;}
  .adm-field .adm-label{margin:0;}
  .adm-scope{
    font-family:'JetBrains Mono',monospace;font-size:10px;letter-spacing:0.05em;
    color:var(--ink-faint);margin-bottom:14px;
  }

  /* ---- the ledger rail ---- */
  .adm-day{border:none;}
  .adm-day-sum{
    list-style:none;cursor:pointer;display:flex;align-items:center;gap:10px;
    padding:10px 0;margin:0;
    font-family:'JetBrains Mono',monospace;font-size:10px;letter-spacing:0.08em;
    text-transform:uppercase;color:var(--ink-dim);
  }
  .adm-day-sum::-webkit-details-marker{display:none;}
  /* The node that breaks the rail. A ring, not a filled dot - a day is a marker, not an event. */
  .adm-day-sum::before{
    content:'';flex:none;width:9px;height:9px;margin-left:1px;border-radius:50%;
    border:1px solid var(--ink-faint);background:var(--bg-deep);
  }
  .adm-day[open] .adm-day-sum{color:var(--ink);}
  .adm-day[open] .adm-day-sum::before{border-color:var(--ink-dim);}
  .adm-day-name{flex:1;}
  .adm-day-count{
    font-variant-numeric:tabular-nums;color:var(--ink-faint);
    border:1px solid var(--line);border-radius:999px;padding:1px 7px;font-size:9.5px;
  }
  /* The rail itself: one hairline, drawn once per day group, behind the markers. */
  .adm-day > .adm-audit{
    position:relative;border:none;padding:2px 0 16px 24px;margin:0;
  }
  .adm-day > .adm-audit::before{
    content:'';position:absolute;left:5px;top:0;bottom:0;width:1px;background:var(--line);
  }
  .adm-day > .adm-audit:last-child::before{bottom:auto;height:9px;}
  /* The severity marker, sitting ON the rail. Colour means consequence, nothing else. */
  .adm-day > .adm-audit::after{
    content:'';position:absolute;left:2px;top:5px;width:7px;height:7px;border-radius:50%;
    background:var(--ink-faint);box-shadow:0 0 0 3px var(--bg-deep);
  }
  .adm-day > .adm-audit.sev-danger::after{background:var(--red);}
  .adm-day > .adm-audit.sev-change::after{background:var(--amber);}
  .adm-day > .adm-audit.sev-read::after{background:var(--ink-faint);}

  .adm-audit-line{font-size:13.5px;line-height:1.5;color:var(--ink);}
  .adm-audit-meta{
    display:flex;gap:10px;align-items:baseline;margin-top:4px;
    font-family:'JetBrains Mono',monospace;font-size:10px;letter-spacing:0.04em;
    color:var(--ink-faint);
  }
  .adm-audit-meta .adm-status{text-transform:uppercase;}
  .adm-audit-meta .adm-id{margin-left:auto;text-align:right;}
  .adm-day > .adm-audit .adm-reason{
    margin-top:6px;padding-left:10px;border-left:1px solid var(--line);
    color:var(--ink-dim);font-size:12px;font-style:italic;
  }

  .adm-more{
    display:block;width:100%;margin-top:6px;padding:11px;
    background:none;border:1px solid var(--line);border-radius:var(--radius-sm);
    color:var(--ink-dim);cursor:pointer;
    font-family:'JetBrains Mono',monospace;font-size:10px;letter-spacing:0.07em;
    text-transform:uppercase;
  }
  .adm-more:hover{border-color:var(--glass-border-strong);color:var(--ink);}
  .adm-more:focus-visible{outline:2px solid var(--amber);outline-offset:2px;}

  /* Consent rows lose their full-width colour wash - two saturated blocks competing for
     attention said "look here" about routine records. The marker keeps the meaning. */
  .adm-consent.granted,.adm-consent.withdrawn{background:none;}

  @media (min-width: 860px){
    /* Only the filter row becomes two columns; the rail is identical at every width. */
    .adm-audit-filters{grid-template-columns:minmax(160px,220px) 1fr;gap:14px;align-items:end;}
  }

  .adm-user,.adm-consent,.adm-audit{
    padding:10px 0;border-bottom:1px solid var(--line-soft);
  }
  .adm-user:last-child,.adm-consent:last-child,.adm-audit:last-child{border-bottom:none;}
  .adm-user{cursor:pointer;}
  .adm-user:hover,.adm-user:focus-visible{background:var(--glass-hover,rgba(255,255,255,0.03));}
  .adm-user:focus-visible{outline:2px solid var(--amber);outline-offset:-2px;}
  .adm-user-top,.adm-consent-top{
    display:flex;justify-content:space-between;align-items:center;gap:8px;flex-wrap:wrap;
  }
  .adm-email{font-weight:600;word-break:break-all;}
  .adm-badges{display:flex;gap:6px;flex-wrap:wrap;}
  .adm-user-meta{
    display:flex;gap:12px;flex-wrap:wrap;margin-top:4px;
    font-size:11px;color:var(--ink-dim);
  }
  .adm-id{font-family:'JetBrains Mono',monospace;}
  .adm-kind{font-family:'JetBrains Mono',monospace;font-weight:600;color:var(--amber);}
  .adm-reason{
    font-size:11px;color:var(--ink-dim);font-style:italic;margin-top:4px;
    word-break:break-word;
  }
  .adm-badge{
    font-size:10px;padding:2px 8px;border-radius:999px;white-space:nowrap;
    border:1px solid var(--line);color:var(--ink-dim);
  }
  .adm-badge.premium,.adm-badge.ok{color:var(--green);border-color:var(--green);background:var(--green-soft);}
  .adm-badge.admin{color:var(--amber);border-color:var(--amber);background:var(--amber-soft);}
  .adm-badge.danger{color:var(--red);border-color:var(--red);background:var(--red-soft);}
  .adm-flag{
    font-family:'JetBrains Mono',monospace;font-weight:700;font-size:12px;
    padding:2px 10px;border-radius:999px;
  }
  .adm-flag.on{color:var(--green);background:var(--green-soft);}
  .adm-flag.off{color:var(--ink-dim);border:1px solid var(--line);}
  /* A WITHDRAWAL must not be distinguishable by wording alone: it gets its own left
     border and tint, so scanning a long list is reliable at a glance. */
  .adm-consent{border-left:3px solid var(--green);padding-left:10px;cursor:pointer;}
  .adm-consent.withdrawn{border-left-color:var(--red);background:var(--red-soft);}
  .adm-consent.granted{background:var(--green-soft);}
  /* The selected account has to be unmistakable - every action below acts on it. */
  .adm-user.selected{
    background:var(--amber-soft);border-left:3px solid var(--amber);padding-left:10px;
  }
  .adm-actions{display:flex;gap:8px;flex-wrap:wrap;margin-top:8px;}
  .admin-btn{
    font-size:12px;padding:7px 14px;border-radius:8px;cursor:pointer;
    border:1px solid var(--line);background:transparent;color:var(--ink);
    font-family:inherit;
  }
  .admin-btn:hover{border-color:var(--amber);color:var(--amber);}
  .admin-btn:focus-visible{outline:2px solid var(--amber);outline-offset:2px;}
  .admin-btn.danger{border-color:var(--red);color:var(--red);}
  .admin-btn.danger:hover{background:var(--red-soft);}
  .adm-confirm{
    margin-top:10px;padding:12px;border-radius:10px;
    border:1px solid var(--amber);background:var(--amber-soft);
  }
  .adm-label{display:block;font-size:11px;color:var(--ink-dim);margin:8px 0 4px;}
  .adm-input{
    width:100%;padding:8px 10px;border-radius:8px;font-family:inherit;font-size:13px;
    border:1px solid var(--line);background:var(--glass,transparent);color:var(--ink);
  }
  .adm-input:focus-visible{outline:2px solid var(--amber);outline-offset:1px;}
  .adm-confirm-actions{display:flex;gap:8px;margin-top:10px;flex-wrap:wrap;}
  .adm-detail{
    margin-top:8px;padding:8px 10px;border-radius:8px;
    border:1px dashed var(--line);
  }
  /* A live grant has to be impossible to miss, and an expired one has to be equally obvious
     rather than simply vanishing - "it disappeared" reads as "it is still running" to nobody's
     benefit. Two clearly different states, both loud. */
  .adm-grant{margin-bottom:10px;padding:10px 12px;border-radius:10px;border:2px solid;}
  .adm-grant.live{border-color:var(--red);background:var(--red-soft);color:var(--red);}
  .adm-grant.live .note{color:var(--ink-dim);}
  .adm-grant.expired{border-color:var(--line);background:transparent;color:var(--ink-dim);}
  #admBgCountdown{font-family:'JetBrains Mono',monospace;font-weight:700;}
  /* Photo capture: side-by-side "Take photo" / "Choose file" buttons. */
  .photo-btn-row{ display:flex; gap:8px; margin-top:8px; }
  .photo-btn-row > button{ flex:1; margin-top:0; }
  .reset-link{
    display:block;text-align:center;margin-top:10px;font-size:11px;
    color:var(--red);text-decoration:underline;cursor:pointer;background:none;border:none;
    font-family:'JetBrains Mono',monospace;text-transform:uppercase;letter-spacing:0.03em;
  }
  /* Build identity under Settings. Deliberately quiet - it is a diagnostic, not a feature -
     but selectable, because the whole point is being able to read it out. */
  .app-version-line{
    display:block;text-align:center;margin-top:14px;font-size:10px;
    color:var(--ink-dim);opacity:0.65;font-family:'JetBrains Mono',monospace;
    letter-spacing:0.04em;user-select:text;
  }
  .saved-flag{
    position:fixed;bottom:88px;left:50%;transform:translateX(-50%);
    background:var(--toast-bg);backdrop-filter:blur(10px);
    color:var(--ink);font-size:10.5px;
    padding:7px 15px;border-radius:20px;font-family:'JetBrains Mono',monospace;
    opacity:0;transition:opacity .3s;pointer-events:none;
    letter-spacing:0.05em;z-index:50;text-transform:uppercase;
    border:1px solid var(--glass-border-strong);
    box-shadow:0 6px 20px rgba(0,0,0,0.4);
  }
  .saved-flag.show{opacity:0.98;}

  .onboard-overlay{
    position:fixed; inset:0; z-index:100;
    background:rgba(4,6,10,0.72); backdrop-filter:blur(6px);
    display:flex; align-items:center; justify-content:center; padding:20px;
  }
  .onboard-overlay.hidden{ display:none; }
  .onboard-card{
    background:var(--bg-deep-2); border:1px solid var(--glass-border-strong);
    border-radius:var(--radius); padding:26px 22px 22px; max-width:420px; width:100%;
    max-height:85vh; overflow-y:auto;
    box-shadow:0 24px 60px rgba(0,0,0,0.5);
  }
  .onboard-eyebrow{
    font-family:'JetBrains Mono',monospace; font-size:10.5px; text-transform:uppercase;
    letter-spacing:0.14em; color:var(--amber); margin-bottom:4px;
  }
  .onboard-card h2{
    font-family:'Big Shoulders Display',sans-serif; font-size:26px; font-weight:800;
    text-transform:uppercase; color:var(--ink); margin:0 0 16px;
  }
  .onboard-item{ display:flex; gap:12px; margin-bottom:14px; align-items:flex-start; }
  .onboard-item svg{ width:20px; height:20px; stroke:var(--teal); fill:none; stroke-width:1.7; stroke-linecap:round; stroke-linejoin:round; flex-shrink:0; margin-top:1px; }
  .onboard-item div{ font-size:13px; color:var(--ink-dim); line-height:1.4; }
  .onboard-item b{ color:var(--ink); }
  .template-options{ display:flex; flex-direction:column; gap:8px; margin-top:8px; }
  .template-opt{
    background:var(--glass); border:1.5px solid var(--glass-border-strong);
    border-radius:var(--radius-sm); padding:10px 12px; cursor:pointer; text-align:left;
    color:var(--ink-dim); font-family:'Public Sans',sans-serif;
  }
  .template-opt b{ display:block; font-size:13px; color:var(--ink); }
  .template-opt span{ display:block; font-size:11px; color:var(--ink-faint); margin-top:2px; }
  .template-opt.active{ border-color:var(--amber); background:var(--amber-soft); }
  .template-opt.active b{ color:var(--amber); }

  .help-card-top{ display:flex; justify-content:space-between; align-items:flex-start; margin-bottom:2px; }
  .help-close{
    background:var(--glass); border:1px solid var(--glass-border-strong);
    border-radius:10px; width:32px; height:32px; flex-shrink:0;
    display:flex; align-items:center; justify-content:center; cursor:pointer;
    color:var(--ink-dim); margin-top:2px;
  }
  .help-close svg{ width:16px; height:16px; stroke:currentColor; fill:none; stroke-width:1.8; stroke-linecap:round; stroke-linejoin:round; }
  .help-section-label{
    font-family:'JetBrains Mono',monospace; font-size:10px; font-weight:700;
    text-transform:uppercase; letter-spacing:0.08em; color:var(--teal);
    margin:16px 0 8px; padding-top:12px; border-top:1px solid var(--glass-border);
  }
  .onboard-item:first-of-type + .help-section-label,
  .help-section-label:first-of-type{ margin-top:12px; padding-top:0; border-top:none; }

  /* ---- Shared destructive-confirm modal ---- */
  .modal-overlay{
    position:fixed; inset:0; z-index:200;
    background:rgba(4,6,10,0.72); backdrop-filter:blur(6px);
    display:flex; align-items:center; justify-content:center; padding:20px;
  }
  .modal-overlay.hidden{ display:none; }
  .modal-box{
    background:var(--bg-deep-2); border:1px solid var(--glass-border-strong);
    border-radius:var(--radius); padding:22px 20px 18px; max-width:400px; width:100%;
    box-shadow:0 24px 60px rgba(0,0,0,0.5);
  }
  .modal-box h3{ font-family:'Big Shoulders Display',sans-serif; font-weight:800; font-size:22px; margin:0 0 10px; color:var(--ink); }
  .modal-body{ font-size:13.5px; line-height:1.5; color:var(--ink-dim); }
  .modal-line{ margin:0; }
  .modal-line b{ color:var(--ink); }
  .modal-warn{ margin:8px 0 0; color:var(--red); font-weight:600; font-size:12.5px; }
  .modal-type-input{ width:100%; margin-top:14px; text-transform:uppercase; letter-spacing:0.08em; }
  .modal-type-input.hidden{ display:none; }
  .modal-actions{ display:flex; flex-wrap:wrap; align-items:center; gap:8px; margin-top:18px; }
  /* max-width caps the button at the row so it can never push the modal sideways: the confirm
     label now carries its own consequence ("Switch account and delete 12 unsynced items"), which
     at 375px is wider than the ~295px of content the modal has. flex:0 0 auto does not shrink, so
     without this the row overflows horizontally on mobile. Over the cap the label wraps instead. */
  .modal-btn{ flex:0 0 auto; max-width:100%; padding:10px 16px; border-radius:10px; font-size:13px; font-family:'Public Sans',sans-serif; cursor:pointer; border:1px solid transparent; transition:background .15s, color .15s; }
  .modal-btn:focus-visible{ outline:2px solid var(--amber); outline-offset:2px; }
  .modal-cancel{ background:var(--glass); border-color:var(--glass-border-strong); color:var(--ink); margin-right:auto; }
  .modal-cancel:hover{ background:var(--glass-strong); }
  .modal-extra{ background:none; border-color:var(--glass-border-strong); color:var(--ink-dim); font-size:12px; }
  .modal-extra.hidden{ display:none; }
  .modal-extra:hover{ color:var(--ink); }
  .modal-danger{ background:#D24A63; border-color:#D24A63; color:#fff; font-weight:700; }
  .modal-danger:hover{ background:#c03e56; }
  .modal-danger:disabled{ opacity:0.4; cursor:not-allowed; }

  /* ---- 2B: clearing-warning sections (confirmDestructive `sections`, separate boxes between
     the lead line and `warn`) - the general "N items not backed up" / "N items rejected" lines
     get the plain treatment below; the bytes-loss box is visually the strongest thing in the
     modal (OWNER DIRECTIVE) via .warn-permanent, never sharing a box with the lines above it. */
  .modal-section{ margin:10px 0 0; padding:10px 12px; border-radius:10px; background:var(--glass); border:1px solid var(--glass-border-strong); }
  .modal-section-title{ margin:0 0 4px; font-weight:700; color:var(--ink); font-size:13px; }
  .modal-section-body{ margin:0; font-size:12.5px; line-height:1.45; color:var(--ink-dim); }
  .modal-section.warn-permanent{ border:2px solid var(--red); background:var(--red-soft); }
  .modal-section.warn-permanent .modal-section-title{ color:var(--red); font-size:14px; }
  .modal-section.warn-permanent .modal-section-body{ color:var(--ink); }

  .undo-toast{
    position:fixed;bottom:88px;left:50%;transform:translateX(-50%) translateY(8px);
    background:var(--toast-bg);backdrop-filter:blur(14px);
    color:var(--ink);font-size:12.5px;
    padding:9px 10px 9px 16px;border-radius:24px;font-family:'Public Sans',sans-serif;
    display:flex; align-items:center; gap:10px;
    opacity:0;pointer-events:none;transition:opacity .25s, transform .25s;
    z-index:51;border:1px solid var(--glass-border-strong);
    box-shadow:0 10px 28px rgba(0,0,0,0.35);
  }
  .undo-toast.show{opacity:1;pointer-events:auto;transform:translateX(-50%) translateY(0);}
  .undo-toast button{
    background:var(--grad-amber);color:#241300;border:none;border-radius:16px;
    padding:6px 14px;font-size:11.5px;font-weight:700;cursor:pointer;
    font-family:'JetBrains Mono',monospace;text-transform:uppercase;letter-spacing:0.03em;
  }

  /* ---- Pay Calculator ---- */
  /* Hourly Rate is a single field, so pull its input up next to the label instead of
     pinning it to the far side (the .field-row default), which left dead space between. */
  .pc-rate-row{ justify-content:flex-start; gap:12px; }
  .pc-rate-row span:first-child{ flex:0 0 auto; }
  .pay-cat-table{width:100%;}
  /* A label is a short word (Base, Sat, Night), so it is CAPPED - not 1fr, which let it
     eat the row and squeeze the numbers. LABEL/MULT/HOURS/PAY are all compact and sit
     together; a flexible spacer (track 5) then pushes only the delete to the row end, so
     PAY no longer flies to the far edge with a gap mid-row. Head + rows share the exact
     same track sizes so the columns line up. */
  .pay-cat-head{
    display:grid;grid-template-columns:minmax(48px,88px) 64px 62px 88px 1fr 22px;gap:6px;
    font-size:9px;text-transform:uppercase;letter-spacing:0.02em;
    color:var(--ink-dim);font-family:'JetBrains Mono',monospace;
    padding-bottom:6px;border-bottom:1px solid var(--glass-border);
  }
  .pay-cat-row{
    display:grid;grid-template-columns:minmax(48px,88px) 64px 62px 88px 1fr 22px;gap:6px;
    align-items:center;padding:8px 0;border-bottom:1px solid var(--glass-border);
  }
  .pay-cat-row:last-child{border-bottom:none;}
  /* Delete sits in the last track; the flexible spacer (track 5) falls between PAY and
     it, so on a wide desktop the row still spans the card (no narrow table floating in
     empty space) while LABEL/MULT/HOURS/PAY read as one tight unit at the left. */
  .pay-cat-row .del-mini{ grid-column:6; }
  .pay-cat-row .cat-label-input{
    font-family:'Big Shoulders Display',sans-serif;font-weight:700;font-size:12px;
    color:var(--amber);text-align:left;padding:6px 4px;min-height:34px;
    white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
  }
  /* Compact enough that "1.25"/"2.5" fit without clipping. This element+class
     selector matches the generic number rule's specificity but comes later, so
     these values win. */
  .pay-cat-row input[type=number]{width:100%;text-align:center;padding:6px 3px;font-size:13px;min-height:34px;}
  .pay-cat-row input.mult-input{text-align:center;}
  .pay-cat-row .row-pay{
    font-family:'JetBrains Mono',monospace;font-weight:700;font-size:13px;text-align:right;color:var(--ink);
  }
  .del-mini{
    border:none;background:none;color:var(--ink-faint);cursor:pointer;padding:2px;
    display:flex;align-items:center;justify-content:center;flex-shrink:0;
  }
  .del-mini:hover{ color:var(--red); }
  .del-mini svg{ width:14px;height:14px; }

  .allow-row{
    display:flex; align-items:center; gap:6px; flex-wrap:wrap;
    padding:7px 0; border-bottom:1px solid var(--glass-border);
  }
  .allow-row:last-child{ border-bottom:none; }
  .allow-row input[type=text]{ flex:1 1 116px; min-width:114px; font-size:13.5px; padding:7px 8px; }
  .allow-row input[type=number]{ width:56px; text-align:right; padding:7px 4px; font-size:13px; }
  .allow-row .allow-amt{
    font-family:'JetBrains Mono',monospace;font-weight:700;font-size:13px;color:var(--ink);
    min-width:64px; text-align:right;
  }

  .debt-row{
    display:flex; align-items:center; gap:6px; flex-wrap:wrap;
    padding:8px 0; border-bottom:1px solid var(--glass-border);
  }
  .debt-row:last-child{ border-bottom:none; }
  .debt-row input[type=text]{ flex:1 1 96px; min-width:88px; font-size:13.5px; padding:7px 8px; }
  .debt-row input[type=number]{ width:64px; text-align:right; padding:7px 4px; font-size:12.5px; }
  .debt-row .debt-field-label{ font-size:8.5px; color:var(--ink-faint); text-transform:uppercase; display:block; margin-bottom:2px; font-family:'JetBrains Mono',monospace; }
  .debt-field{ display:flex; flex-direction:column; }
  /* Debt Payoff row = a liability with an "include in plan" toggle (name from Your Accounts). */
  .debt-include{ display:flex; align-items:center; gap:8px; flex:1 1 130px; min-width:120px; cursor:pointer; }
  .debt-include input[type=checkbox]{ width:18px; height:18px; flex:0 0 auto; accent-color:var(--amber); cursor:pointer; }
  .debt-name{ font-size:13.5px; font-weight:600; }
  .debt-bal{ font-family:'JetBrains Mono',monospace; font-size:13px; font-weight:600; color:var(--ink); }
  .merge-note{
    display:flex; align-items:flex-start; gap:12px; justify-content:space-between;
    background:rgba(245,166,35,0.12); border:1px solid var(--amber);
    border-radius:var(--radius-sm); padding:10px 12px; margin-bottom:12px; font-size:12.5px; line-height:1.5;
  }
  .merge-note button{ flex:0 0 auto; }

  /* ---- Rollover: "has your pay landed?" prompt (mobile-first) ----
     High-priority action card above the hero. Amber-accented like merge-note but with real
     Yes/No controls (>=44px touch). Stacks: text over full-width buttons on phones. */
  /* End-of-pay-period sweep. Deliberately quieter than the pay prompt: that one is a question about
     money that may not have arrived, this one is about money already sitting there, so it informs
     rather than alarms. Neutral panel, no amber border, and it disappears once answered. */
  /* THE STORY LINE. The one piece of prose on Overview, and the first thing read - so it is set as
     a sentence, not a stat: larger than a note, quieter than the hero, and it never competes with
     the number underneath it. Three tones, and two of the four states share the 'ask' one because
     they are the same thing - the app has not been told enough to have a story yet. */
  .story-line{
    font-size:15px; line-height:1.5; color:var(--ink);
    margin:0 0 14px; padding:11px 14px;
    border-radius:var(--radius-sm);
    background:var(--panel-strong-bg);
    border-left:3px solid var(--glass-border-strong);
  }
  .story-line:empty{ display:none; }
  .story-line.story-behind{ border-left-color:var(--amber); }
  .story-line.story-ahead{ border-left-color:var(--olive); }
  .story-line.story-ask{ border-left-color:var(--glass-border-strong); color:var(--ink-dim); }

  /* The bills line on This Week's Plan, and the sentence that explains it. Deliberately the same
     weight as the other deductions - it is not a warning, it is the rent the plan pays to stay
     level - but tinted so the one row that is new after graduating is findable. */
  .plan-row.plan-keep .label{ color:var(--ink); }
  .plan-row.plan-keep .amt{ color:var(--amber); }
  /* app105: the card now opens by naming the pay it is dividing, so the first thing read is the
     instruction rather than a column of arithmetic. The figure carries the weight; the sentence
     around it stays quiet. */
  .plan-lede{
    margin:0 0 10px; font-size:14px; line-height:1.5; color:var(--ink-dim);
  }
  .plan-lede b{ font-family:'JetBrains Mono',monospace; font-weight:700; color:var(--ink); font-size:16px; }
  /* Catch-up money. Olive, not amber: this row is progress, not a cost. */
  .plan-row.plan-square .label{ color:var(--ink); }
  .plan-row.plan-square .amt{ color:var(--olive); }
  /* The derivation of the bills line. A plain note - it inherits .plan-row-note's red band
     otherwise, which would read as a warning about a figure that is simply a fact. */
  /* The cadence-drift note on Variable Income. Amber, not red: nothing is broken and nothing has
     been lost - two facts the person gave the app disagree, and only they can say which is right. */
  .var-drift{
    margin:8px 0 0; padding:9px 11px; font-size:12px; line-height:1.5; color:var(--ink);
    background:var(--amber-soft); border-left:3px solid var(--amber);
    border-radius:0 var(--radius-sm) var(--radius-sm) 0;
  }
  .var-drift[hidden]{ display:none; }
  .plan-row-note.plan-rate{
    background:none; border-left:none; margin:8px 0 0; padding:0;
    font-size:11.5px; line-height:1.5; color:var(--ink-dim);
  }
  /* What is coming next (app108). Also not a warning - it is the one line that tells you a pay
     logged for a future date registered at all. Neutral panel, the same idiom the story line uses,
     so it reads as its own block rather than a second footnote under the bills rate. */
  .plan-row-note.plan-next{
    margin:10px 0 0; padding:9px 11px; font-size:11.5px; line-height:1.5; color:var(--ink-dim);
    background:var(--panel-strong-bg); border-left:3px solid var(--glass-border-strong);
    border-radius:0 var(--radius-sm) var(--radius-sm) 0;
  }
  .plan-row-note.plan-next b{ color:var(--ink); font-family:'JetBrains Mono',monospace; }
  .bf-grad-keepline{
    margin-top:10px; font-size:13.5px; line-height:1.5; color:var(--ink);
    padding-left:11px; border-left:3px solid var(--olive);
  }

  .sweep-prompt{ margin-bottom:14px; }
  .sweep-ask{
    background:var(--panel-strong-bg); border:1px solid var(--glass-border-strong);
    border-radius:var(--radius-sm); padding:12px 13px; box-shadow:var(--card-shadow);
  }
  .sweep-line{ font-size:14px; line-height:1.5; color:var(--ink); margin-bottom:10px; }
  .sweep-btns{ display:flex; flex-wrap:wrap; gap:8px; }
  /* A rare, deliberate decision about real money - given a proper thumb target rather than the
     11px pill the overdue answers use, which sit in a much denser block. */
  .sweep-btns .pos-obtn{ padding:11px 14px; font-size:11.5px; }
  .sweep-note{ margin-top:9px; }

  .pay-prompt{ margin-bottom:14px; }
  .pay-prompt-card{
    background:var(--amber-soft, rgba(245,166,35,0.12)); border:1px solid var(--amber);
    border-radius:var(--radius-sm); padding:12px 13px; box-shadow:var(--card-shadow);
  }
  .pay-prompt-head{
    font-family:'JetBrains Mono',monospace; font-size:10px; font-weight:600; letter-spacing:0.03em;
    text-transform:uppercase; color:var(--amber); margin-bottom:10px; line-height:1.5;
  }
  .pay-prompt-row{ display:flex; flex-direction:column; gap:9px; padding:9px 0; border-top:1px solid var(--glass-border); }
  .pay-prompt-row:first-of-type{ border-top:none; padding-top:0; }
  .pay-prompt-row:last-child{ padding-bottom:0; }
  .pay-prompt-text{ font-size:14px; line-height:1.45; color:var(--ink); }
  .pay-prompt-text b{ font-weight:700; }
  .pay-prompt-due{ display:block; font-size:11.5px; color:var(--ink-dim); margin-top:2px; }
  .pay-prompt-actions{ display:flex; gap:8px; }
  .pay-prompt-actions button{
    flex:1 1 0; min-height:44px; padding:0 14px; font-size:13.5px; font-weight:600;
    border-radius:10px; cursor:pointer; transition:filter .15s, background .15s, border-color .15s;
  }
  .pp-yes{ background:var(--amber); color:#1a1206; border:1px solid var(--amber); }
  .pp-yes:hover{ filter:brightness(1.06); }
  .pp-no{ background:transparent; color:var(--ink-dim); border:1px solid var(--glass-border); }
  .pp-no:hover{ color:var(--ink); border-color:var(--ink-faint); }
  @media (min-width:520px){
    .pay-prompt-row{ flex-direction:row; align-items:center; justify-content:space-between; gap:12px; }
    .pay-prompt-text{ flex:1 1 auto; }
    .pay-prompt-actions{ flex:0 0 auto; }
    .pay-prompt-actions button{ flex:0 0 auto; min-width:112px; }
  }

  /* ---- Rollover: recent pay answers + one-tap Undo (findable, under the hero) ---- */
  .pay-history{ margin:0 0 14px; }
  .pay-hist-card{
    background:var(--panel-strong-bg); border:1px solid var(--glass-border);
    border-radius:var(--radius-sm); padding:11px 13px;
  }
  .pay-hist-head{
    font-family:'JetBrains Mono',monospace; font-size:10px; font-weight:600; letter-spacing:0.03em;
    text-transform:uppercase; color:var(--ink-faint); margin-bottom:8px; line-height:1.5;
  }
  .pay-hist-row{ display:flex; align-items:center; justify-content:space-between; gap:12px; padding:7px 0; border-top:1px solid var(--glass-border); }
  .pay-hist-row:first-of-type{ border-top:none; }
  .pay-hist-info{ display:flex; flex-direction:column; gap:1px; min-width:0; }
  .pay-hist-name{ font-size:13.5px; font-weight:600; color:var(--ink); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .pay-hist-meta{ font-size:11.5px; color:var(--ink-dim); }
  .pay-hist-undo{
    flex:0 0 auto; min-height:40px; padding:0 16px; font-size:13px; font-weight:600;
    background:transparent; color:var(--amber); border:1px solid var(--glass-border);
    border-radius:9px; cursor:pointer; transition:border-color .15s, background .15s;
  }
  .pay-hist-undo:hover{ border-color:var(--amber); background:var(--amber-soft, rgba(245,166,35,0.10)); }

  /* ---- Period summary: shown when the hero reaches zero because everything is allocated ---- */
  .period-summary{ margin:0 0 14px; }
  .period-summary-card{
    background:var(--olive-soft, rgba(155,192,74,0.12)); border:1px solid var(--olive, #9BC04A);
    border-radius:var(--radius-sm); padding:13px 15px; line-height:1.55;
  }
  .period-summary-card b{ font-size:15px; color:var(--ink); }
  .period-summary-card .ps-line{ font-family:'JetBrains Mono',monospace; font-size:12.5px; color:var(--ink-dim); margin:6px 0 4px; }
  .period-summary-card .ps-warm{ font-size:13px; color:var(--ink); }

  /* ---- Income source: optional payday line under each row (pay-date reminder) ---- */
  .inc-src{ border-bottom:1px solid var(--glass-border); }
  .inc-src:last-child{ border-bottom:none; }
  .inc-src .nw-row{ border-bottom:none; }
  .pay-date-row{ display:flex; align-items:center; flex-wrap:wrap; gap:8px; padding:0 0 10px 2px; }
  .pay-date-row label{
    font-family:'JetBrains Mono',monospace; font-size:10px; font-weight:600; letter-spacing:0.03em;
    text-transform:uppercase; color:var(--ink-faint);
  }
  .pay-date-row input.pay-date{ min-height:38px; padding:6px 8px; font-size:13px; color:var(--ink); }
  .pay-date-hint{ flex:1 1 100%; font-size:11px; color:var(--ink-dim); line-height:1.4; }
  .log-add input.pay-date{ min-height:40px; padding:7px 8px; font-size:13px; }
  @media (min-width:520px){ .pay-date-hint{ flex:1 1 auto; } }

  /* ---- Net Worth account rows (mirror debt rows) ---- */
  .nw-row{
    display:flex; align-items:center; gap:6px; flex-wrap:wrap;
    padding:8px 0; border-bottom:1px solid var(--glass-border);
  }
  .nw-row:last-child{ border-bottom:none; }
  .nw-row input[type=text]{ flex:1 1 120px; min-width:100px; font-size:13.5px; padding:7px 8px; }
  .nw-row input[type=number]{ width:84px; text-align:right; padding:7px 4px; font-size:12.5px; }
  /* Income-source frequency select in a row: wide enough for "Fortnightly"/"Half-yearly". */
  .nw-row select{ flex:1 1 130px; min-width:130px; font-size:13px; }
  .nw-group-head{
    font-family:'JetBrains Mono',monospace; font-size:10px; font-weight:600; letter-spacing:0.04em;
    text-transform:uppercase; color:var(--ink-faint); margin:16px 0 4px;
  }

  /* ---- One-Off Bills — display-first card (mobile-first) ----
     Name is the headline; the weekly set-aside is the hero number; total/due/
     category are quiet detail; fields only appear on Edit. Matches the app's
     Big Shoulders + amber/olive/red card language. */
  .oneoff-card{ padding:15px 0; border-bottom:1px solid var(--glass-border); }
  .oneoff-card:first-child{ padding-top:2px; }
  .oneoff-card:last-child{ border-bottom:none; }
  .oo-card-head{ display:flex; align-items:center; gap:8px; }
  .oo-name-h{
    flex:1 1 auto; min-width:0; font-family:'Big Shoulders Display',sans-serif; font-weight:700;
    font-size:17px; color:var(--ink); overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
  }
  .oo-badge{
    flex:0 0 auto; font-family:'JetBrains Mono',monospace; font-size:9.5px; font-weight:600;
    text-transform:uppercase; letter-spacing:0.03em; padding:4px 8px; border-radius:999px;
    border:1px solid var(--glass-border); color:var(--ink-dim); white-space:nowrap;
  }
  .oo-badge-overdue{ color:#FF5C7A; background:rgba(255,92,122,0.10); border-color:rgba(255,92,122,0.4); }
  .oo-badge-soon{ color:var(--amber); background:var(--amber-soft); border-color:rgba(245,166,35,0.4); }
  .oo-badge-covered{ color:var(--olive); background:var(--olive-soft); border-color:rgba(155,192,74,0.4); }
  /* Hero: the weekly set-aside — the thing the user opens this tab to see. */
  .oo-hero{ display:flex; align-items:baseline; gap:8px; margin:8px 0 3px; flex-wrap:wrap; }
  .oo-hero-num{ font-family:'Big Shoulders Display',sans-serif; font-weight:800; font-size:30px; line-height:1; color:var(--amber); }
  .oo-hero-label{ font-size:11px; color:var(--ink-dim); }
  .oo-hero-overdue .oo-hero-num{ color:#FF5C7A; }
  .oo-hero-covered .oo-hero-num{ color:var(--olive); font-size:22px; }
  .oo-detail{ font-size:12px; color:var(--ink-dim); margin:0 0 9px; }
  .oo-actions{ display:flex; flex-wrap:wrap; align-items:center; gap:8px; margin-top:11px; }
  /* The add-set field + button join into one full-width control on its own row;
     "Mark as paid" and "Edit" wrap to the row below. width:auto defeats the base
     .clear-calc-btn width:100% that was stretching the button and cramping the input. */
  .oo-addset{ display:flex; flex:1 1 100%; }
  .oo-add-input{ flex:1 1 auto; min-width:0; padding:9px 11px; font-size:13px; border-radius:9px 0 0 9px; border-right-width:0; }
  .oo-actions .clear-calc-btn{ margin-top:0; flex:0 0 auto; width:auto; }
  .oo-add-btn{ flex:0 0 auto; white-space:nowrap; border-radius:0 9px 9px 0; }
  .oo-edit-btn{
    margin-left:auto; flex:0 0 auto; background:transparent; border:1px solid var(--glass-border);
    color:var(--ink-dim); border-radius:8px; padding:8px 14px; font-size:12px; cursor:pointer;
    font-family:'Public Sans',sans-serif; transition:color .15s, border-color .15s;
  }
  .oo-edit-btn:hover{ color:var(--ink); border-color:var(--glass-border-strong); }
  /* Edit mode: revealed fields */
  .oo-editing{ background:rgba(255,255,255,0.03); border-radius:var(--radius-sm); padding:14px; margin:6px 0; }
  .oo-edit-grid{ display:flex; flex-wrap:wrap; gap:10px; }
  .oo-elabel{ display:flex; flex-direction:column; gap:3px; flex:1 1 120px; font-size:9px; text-transform:uppercase; letter-spacing:0.03em; color:var(--ink-faint); font-family:'JetBrains Mono',monospace; }
  .oo-einput{ width:100%; padding:8px; font-size:13px; font-family:'Public Sans',sans-serif; text-transform:none; letter-spacing:normal; color:var(--ink); }
  .oo-edit-actions{ display:flex; align-items:center; gap:10px; margin-top:12px; }
  .oo-done-btn{ margin-top:0; flex:0 0 auto; width:auto; padding:9px 20px; }
  .oo-del-text{ margin-left:auto; background:none; border:none; color:#FF5C7A; font-size:12px; cursor:pointer; padding:6px; font-family:'Public Sans',sans-serif; }
  .oo-del-text:hover{ text-decoration:underline; }
  .oo-history-label{ margin-top:14px; font-size:10px; text-transform:uppercase; letter-spacing:0.06em; color:var(--ink-faint); font-family:'JetBrains Mono',monospace; }
  .oo-history{ margin-top:8px; }
  /* Upcoming card: emphasise an overdue one-off */
  .upcoming-row.up-overdue .up-when{ color:#FF5C7A; font-weight:600; }

  .method-toggle{ display:flex; gap:8px; }
  .method-btn{
    flex:1; background:var(--glass); border:1.5px solid var(--glass-border-strong);
    border-radius:var(--radius-sm); padding:10px 8px; cursor:pointer; text-align:left;
    color:var(--ink-dim); font-family:'Public Sans',sans-serif; font-size:12.5px; font-weight:600;
  }
  .method-btn span{ display:block; font-size:10px; font-weight:400; color:var(--ink-faint); margin-top:2px; font-family:'JetBrains Mono',monospace; }
  .method-btn.active{ border-color:var(--amber); color:var(--ink); background:var(--amber-soft); }
  .method-btn.active span{ color:var(--ink-dim); }

  .debt-result-row{
    display:flex; justify-content:space-between; padding:8px 0;
    border-bottom:1px solid var(--glass-border); font-size:13px; color:var(--ink);
  }
  .debt-result-row:last-child{ border-bottom:none; }
  .debt-result-row .amt{ font-family:'JetBrains Mono',monospace; font-weight:700; }
  .debt-order-list{ font-size:12px; color:var(--ink-dim); margin-top:2px; }
  .debt-order-list b{ color:var(--amber); }

  .pay-summary-row{
    display:flex;justify-content:space-between;padding:8px 0;
    border-bottom:1px solid var(--glass-border);font-size:13.5px;color:var(--ink);
  }
  .pay-summary-row:last-child{border-bottom:none;}
  .pay-summary-row .amt{font-family:'JetBrains Mono',monospace;font-weight:600;}
  .pay-summary-row.grand .label, .pay-summary-row.grand .amt{font-size:16px;font-weight:700;}
  /* Footer: Total Pay (the summary) and the day picker + Save (the action) read as ONE
     resolved block - an olive-accented panel - instead of three loose elements. */
  /* Neutral wrapper - the green tint + accent bar belong to the Gross Pay ROW only, not
     the whole footer, so the day-picker below matches the surrounding cards. */
  .pay-footer{ margin-top:14px; }
  .pay-footer .pay-summary-row.grand{
    background:linear-gradient(90deg, rgba(155,192,74,0.16), rgba(111,160,69,0.06));
    margin:0 -15px;padding:13px 15px;
    border-left:3px solid var(--olive);border-bottom:none;
  }
  .day-picker-row{display:flex;gap:10px;margin-top:14px;align-items:center;}
  .day-picker-row select{flex:1;min-height:38px;}
  .save-day-btn{
    background:var(--grad-teal);color:#04211C;border:none;border-radius:var(--radius-sm);
    padding:0 16px;min-height:38px;font-size:12.5px;font-weight:700;
    font-family:'JetBrains Mono',monospace;text-transform:uppercase;letter-spacing:0.03em;
    cursor:pointer;white-space:nowrap;
  }
  .save-day-btn:hover{opacity:0.92;}
  .week-row{
    display:flex;justify-content:space-between;align-items:center;
    padding:8px 0;border-bottom:1px solid var(--glass-border);font-size:13.5px;color:var(--ink);
  }
  .week-row:last-child{border-bottom:none;}
  .week-row .day-name{font-weight:600;}
  .week-row.today .day-name{color:var(--amber);}
  .week-row input[type=number]{width:104px;text-align:right;padding:8px;font-size:14px;}
  .week-total-row{
    display:flex;justify-content:space-between;align-items:center;
    padding:13px 15px;margin:8px -15px -16px;
    background:var(--panel-strong-bg);color:var(--ink);
    border-left:3px solid var(--amber);
  }
  .week-total-row .label{
    font-family:'Big Shoulders Display',sans-serif;font-weight:700;
    text-transform:uppercase;font-size:15px;letter-spacing:0.02em;
  }
  .week-total-row .amt{font-family:'JetBrains Mono',monospace;font-weight:700;font-size:17px;color:var(--amber);}
  .clear-calc-btn{
    background:none;border:1px solid var(--glass-border-strong);color:var(--ink-dim);
    border-radius:var(--radius-sm);padding:9px 12px;font-size:11.5px;font-family:'JetBrains Mono',monospace;
    text-transform:uppercase;letter-spacing:0.03em;cursor:pointer;margin-top:10px;width:100%;
  }
  .clear-calc-btn:hover{background:var(--glass-strong);}

  /* Danger zone (account deletion). Walled off from the rest of the card by a top rule and
     spacing; the control is muted-red until hover so it reads as destructive without shouting. */
  .danger-zone{ margin-top:22px; padding-top:16px; border-top:1px solid rgba(210,74,99,0.35); }
  .danger-zone-title{ font-family:'JetBrains Mono',monospace; font-size:10.5px; text-transform:uppercase;
    letter-spacing:0.08em; color:#D24A63; margin-bottom:10px; }
  .danger-zone-btn{ background:none; border:1px solid rgba(210,74,99,0.55); color:#D24A63;
    border-radius:var(--radius-sm); padding:9px 14px; font-size:11.5px; font-family:'JetBrains Mono',monospace;
    text-transform:uppercase; letter-spacing:0.03em; cursor:pointer; min-height:40px; flex:0 0 auto; }
  .danger-zone-btn:hover{ background:#D24A63; color:#fff; }
  .danger-zone-btn:active{ transform:scale(0.97); }

  /* ===== Kakeibo mode (js/kakeibo.js): optional, read-only monthly view. Mobile-first: each jar
     is a compact row (vessel + text); 2x2 grid of taller vessels on wider screens. The vessels
     FILL with liquid - a rising level (transition) + a scrolling wave surface. Reduced-motion off. */
  [data-container="survival"]{ --kb: 58,143,176; }   /* teal-blue - essential */
  [data-container="optional"]{ --kb: 214,150,58; }   /* amber - discretionary */
  [data-container="culture"] { --kb: 141,111,176; }  /* violet - the mind */
  [data-container="extra"]   { --kb: 200,102,118; }  /* rose - the unplanned */

  .kb-jars{ display:grid; grid-template-columns:1fr; gap:12px; margin-top:4px; }
  .kb-jar{ display:flex; flex-direction:row; align-items:center; gap:16px;
    background:var(--glass); border:1px solid var(--glass-border); border-radius:var(--radius); padding:12px 14px; }
  .kb-jar-svg{ width:86px; height:110px; flex:0 0 auto; display:block; }
  .kb-jar-bg{ fill: rgba(var(--kb),0.07); }
  .kb-jar-rim{ fill:none; stroke: rgba(var(--kb),0.55); stroke-width:2; }
  .kb-liquid{ transition: transform 1100ms cubic-bezier(.22,.61,.36,1); will-change: transform; }
  .kb-wave-b{ fill: rgba(var(--kb),0.40); animation: kb-wave 3.6s linear infinite; }
  .kb-wave-f{ fill: rgba(var(--kb),0.72); animation: kb-wave 2.6s linear infinite; }
  @keyframes kb-wave{ from{ transform: translateX(0); } to{ transform: translateX(-120px); } }
  .kb-jar-info{ flex:1 1 auto; min-width:0; }
  .kb-jar-label{ font-family:'JetBrains Mono',monospace; font-size:10.5px; text-transform:uppercase; letter-spacing:0.09em; color: rgb(var(--kb)); }
  .kb-jar-amt{ font-family:'Big Shoulders Display',sans-serif; font-weight:800; font-size:26px; line-height:1.05; margin-top:2px; }
  .kb-jar-blurb{ font-size:12px; color:var(--ink-dim); margin-top:3px; }

  @media (min-width:560px){
    .kb-jars{ grid-template-columns:1fr 1fr; gap:16px; }
    .kb-jar{ flex-direction:column; align-items:stretch; text-align:center; padding:16px; }
    .kb-jar-svg{ width:100%; height:168px; }
    .kb-jar-info{ margin-top:6px; }
  }

  .kb-empty{ background:var(--glass); border:1px dashed var(--glass-border-strong); border-radius:var(--radius);
    padding:16px; color:var(--ink-dim); font-size:13.5px; margin-bottom:12px; text-align:center; }
  .kb-unsorted{ margin-top:14px; font-size:12.5px; color:var(--ink-dim); background:var(--glass);
    border:1px solid var(--glass-border); border-radius:var(--radius-sm); padding:10px 12px; }
  .kb-unsorted b{ color:var(--ink); }
  .kb-foot{ margin-top:12px; }
  .kb-link{ background:none; border:none; color:var(--teal); font:inherit; text-decoration:underline; cursor:pointer; padding:0; }

  /* Explainer legend + the sort sheet (inside the kbOverlay modal) */
  .kb-legend{ list-style:none; padding:0; margin:10px 0 0; }
  .kb-legend li{ display:flex; align-items:flex-start; gap:8px; font-size:13px; margin:7px 0; line-height:1.45; }
  .kb-dot{ width:12px; height:12px; border-radius:50%; background: rgb(var(--kb)); flex:0 0 auto; margin-top:3px; }
  .kb-sort-list{ margin-top:10px; display:flex; flex-direction:column; gap:12px; max-height:52vh; overflow-y:auto; }
  .kb-sort-cat{ font-weight:600; font-size:13.5px; margin-bottom:6px; }
  .kb-pick-row{ display:flex; flex-wrap:wrap; gap:6px; }
  .kb-pick{ border:1px solid rgba(var(--kb),0.5); color: rgb(var(--kb)); background:none; border-radius:999px;
    padding:6px 12px; font-size:12px; font-family:'JetBrains Mono',monospace; cursor:pointer; min-height:34px; }
  .kb-pick.on{ background: rgb(var(--kb)); color:#fff; border-color: rgb(var(--kb)); }
  .kb-pick:active{ transform:scale(0.97); }

  @media (prefers-reduced-motion: reduce){
    .kb-liquid{ transition:none !important; }
    .kb-wave-b, .kb-wave-f{ animation:none !important; }
  }

  /* Per-tab customise layout. `.tab-cards` is a transparent wrapper that groups a tab's
     reorderable cards WITHOUT changing layout: display:contents on every breakpoint (unlike
     .dashboard-cards, which becomes a 2-column grid on desktop), so cards stack in DOM order
     exactly as before. The `.layout-control` card below the cards opens the reorder/hide list;
     section.card carries no padding of its own (that lives in .card-body), so add it here. */
  .tab-cards{ display:contents; }
  .layout-control{ padding:13px 15px 16px; }
  .layout-control .layout-control-toggle{ margin-top:0; }
  .layout-control-body{ margin-top:12px; }

  /* ---- Library + My Tax (Phase 2) ---- */
  .lib-folder-chips{ display:flex; flex-wrap:wrap; gap:8px; margin-top:12px; }
  .lib-chip{
    display:inline-flex; align-items:center; gap:6px; min-height:36px;
    padding:0 12px; border-radius:999px; cursor:pointer;
    background:var(--glass); border:1px solid var(--glass-border);
    color:var(--ink-dim); font-family:'JetBrains Mono',monospace; font-size:11px;
    font-weight:600; text-transform:uppercase; letter-spacing:0.02em;
    transition:color .2s, background .2s, border-color .2s;
  }
  .lib-chip.active{ color:var(--bg-deep); background:var(--grad-olive); border-color:transparent; }
  .lib-chip-count{ font-size:10px; opacity:0.75; }
  .lib-chip-wrap{ display:inline-flex; align-items:center; }
  .lib-chip-wrap .lib-chip{ border-top-right-radius:0; border-bottom-right-radius:0; }
  .lib-chip-del{
    min-height:36px; padding:0 9px; border:1px solid var(--glass-border); border-left:none;
    border-top-right-radius:999px; border-bottom-right-radius:999px;
    background:var(--glass); color:var(--ink-faint); cursor:pointer; font-size:15px; line-height:1;
  }
  .lib-chip-del:hover{ color:var(--red); }

  .lib-pending-row{
    display:flex; align-items:center; gap:10px; padding:8px 10px; margin-top:8px;
    background:var(--glass); border:1px solid var(--glass-border); border-radius:var(--radius-sm);
  }
  .lib-pending-row .lib-doc-name{ flex:1; min-width:0; }
  .lib-pending-row .lib-doc-meta{ flex-shrink:0; }
  .lib-pending-row .del{ border:none; background:none; color:var(--ink-faint); cursor:pointer; font-size:16px; flex-shrink:0; }
  .lib-pending-row .del:hover{ color:var(--red); }

  .lib-doc-row{
    display:flex; align-items:center; gap:12px; padding:12px 0;
    border-bottom:1px solid var(--glass-border);
  }
  .lib-doc-row:last-child{ border-bottom:none; }
  .lib-doc-icon{
    flex-shrink:0; width:34px; height:34px; display:flex; align-items:center; justify-content:center;
    border-radius:9px; background:var(--olive-soft);
  }
  .lib-doc-icon svg{ width:20px; height:20px; fill:none; stroke:var(--olive); stroke-width:1.5; stroke-linecap:round; stroke-linejoin:round; }
  .lib-doc-info{ flex:1; min-width:0; }
  .lib-doc-name{ font-weight:600; font-size:13.5px; color:var(--ink); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .lib-doc-meta{ font-size:11px; color:var(--ink-faint); font-family:'JetBrains Mono',monospace; margin-top:2px; }
  /* Orphaned-file badge (Library + My Tax): a record whose bytes are missing from
     IndexedDB. Muted amber, small, non-alarming - it flags, it doesn't shout. */
  .doc-missing-badge{
    display:inline-block; font-family:inherit; font-size:10px; font-weight:600;
    font-style:normal; letter-spacing:0.02em; vertical-align:baseline;
    padding:1px 6px; border-radius:6px; white-space:nowrap;
    color:var(--amber); background:var(--amber-soft);
  }
  .doc-missing .lib-doc-icon{ opacity:0.5; }
  .lib-doc-folder{ margin-top:6px; font-size:11px; max-width:100%; min-height:34px; }
  .lib-doc-actions{ display:flex; gap:5px; flex-shrink:0; }
  .lib-doc-actions button{
    width:36px; height:36px; display:flex; align-items:center; justify-content:center;
    border:1px solid var(--glass-border); background:var(--glass); border-radius:9px;
    color:var(--ink-dim); cursor:pointer;
  }
  .lib-doc-actions button:hover{ color:var(--ink); background:var(--glass-strong); }
  .lib-doc-actions svg{ width:16px; height:16px; fill:none; stroke:currentColor; stroke-width:1.6; stroke-linecap:round; stroke-linejoin:round; }

  .tax-cat-row{ padding:9px 0; border-bottom:1px solid var(--glass-border); }
  .tax-cat-row:last-child{ border-bottom:none; }
  .tax-cat-top{ display:flex; justify-content:space-between; align-items:center; margin-bottom:6px; font-size:13px; color:var(--ink); }
  .tax-cat-top .amt{ font-family:'JetBrains Mono',monospace; font-weight:700; color:var(--olive); }
  .rollup-budget{ color:var(--ink-faint); font-weight:400; }
  /* A category with spending but no derived budget: marked as such, not left blank. */
  .rollup-nobudget{ font-style:italic; }
  /* Pot-funded spend in a category: insight only (it left the weekly plan), never vs the bar. */
  .rollup-pot{ font-size:11px; color:var(--ink-faint); font-family:'JetBrains Mono',monospace;
    letter-spacing:0.02em; margin-top:5px; line-height:1.35; }

  /* Forecast: the leanest-week fact carries real weight (it's the safety number), the
     caveat stays quiet under it. Neither invents anything - both are recorded data. */
  .forecast-fact{ margin-top:10px; font-size:13px; font-weight:600; color:var(--ink); }
  .forecast-fact:empty{ display:none; }
  .forecast-caveat{ margin-top:6px; }

  /* Dashboard-layout control: a card per row with up/down arrows (reusing .goal-move,
     thumb-friendly - no drag) and a show/hide toggle. Hidden cards read struck-through. */
  .dash-layout-row{ display:flex; align-items:center; justify-content:space-between; gap:10px;
    padding:9px 0; border-bottom:1px solid var(--glass-border); }
  .dash-layout-row:last-of-type{ border-bottom:none; }
  .dash-layout-name{ font-size:14px; color:var(--ink); }
  .dash-layout-row.is-hidden .dash-layout-name{ color:var(--ink-faint); text-decoration:line-through; }
  .dash-layout-controls{ display:flex; align-items:center; gap:6px; flex-shrink:0; }
  .dash-vis{ background:var(--glass); border:1px solid var(--glass-border-strong); color:var(--ink-dim);
    border-radius:7px; padding:6px 11px; font-size:11px; cursor:pointer; font-family:'Public Sans',sans-serif; min-width:60px; }
  .dash-vis[aria-pressed="false"]{ color:var(--ink-faint); }
  .dash-vis:hover{ color:var(--ink); }

  /* ---- Tax category accordions ---- */
  .tax-acc{ border-bottom:1px solid var(--glass-border); }
  .tax-acc:last-child{ border-bottom:none; }
  .tax-acc-head{
    width:100%; display:flex; align-items:center; gap:10px; padding:11px 2px;
    background:none; border:none; cursor:pointer; text-align:left; color:var(--ink);
    font-family:'JetBrains Mono',monospace; min-height:44px;
  }
  .tax-acc-caret{
    width:15px; height:15px; flex-shrink:0; fill:none; stroke:var(--ink-faint);
    stroke-width:2; stroke-linecap:round; stroke-linejoin:round; transition:transform .2s;
  }
  .tax-acc.open .tax-acc-caret{ transform:rotate(90deg); }
  .tax-acc-name{ flex:1; min-width:0; font-size:13px; font-weight:600; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
  .tax-acc-count{
    font-size:10px; color:var(--ink-dim); background:var(--glass); border:1px solid var(--glass-border);
    border-radius:999px; padding:1px 7px; flex-shrink:0;
  }
  .tax-acc-total{ font-size:13px; font-weight:700; color:var(--olive); flex-shrink:0; }
  .tax-acc-body{ display:none; padding:0 2px 8px 25px; }
  .tax-acc.open .tax-acc-body{ display:block; }

  /* ---- Lightbox (photo / receipt viewer) ---- */
  .lightbox{
    display:none; position:fixed; inset:0; z-index:1000;
    align-items:center; justify-content:center; padding:24px;
    background:rgba(6,9,14,0.9); cursor:zoom-out;
    -webkit-backdrop-filter:blur(4px); backdrop-filter:blur(4px);
  }
  .lightbox.show{ display:flex; }
  .lightbox img{ max-width:100%; max-height:100%; border-radius:12px; box-shadow:0 24px 70px rgba(0,0,0,0.55); }
  .daily-thumb{ cursor:zoom-in; }

  /* ---- Show more / fewer (paginated history lists) ---- */
  .show-more-btn{
    width:100%; margin-top:10px; padding:9px; min-height:40px;
    background:none; border:1px dashed var(--glass-border-strong);
    border-radius:var(--radius-sm); color:var(--ink-dim); cursor:pointer;
    font-family:'JetBrains Mono',monospace; font-size:11px; font-weight:600;
    text-transform:uppercase; letter-spacing:0.04em; transition:color .2s, background .2s;
  }
  .show-more-btn:hover{ background:var(--glass); color:var(--ink); }
  .show-more-btn:active{ transform:scale(0.98); }

  /* ---- hero-stat (Savings / Timebank) ---- */
  .hero-stat{
    background:var(--glass);
    backdrop-filter:blur(20px) saturate(150%);
    -webkit-backdrop-filter:blur(20px) saturate(150%);
    color:var(--ink);
    border:1px solid var(--glass-border);
    border-radius:var(--radius);
    padding:24px 18px;
    margin-bottom:16px;
    text-align:center;
    position:relative;
    overflow:hidden;
    box-shadow:var(--card-shadow-lg);
  }
  /* Per-tab help "?" - sits in the tab's hero header, never on the sub-tab bar. Native
     <button> so it's tab-focusable and Enter/Space-activated, matching the header "?". */
  .hero-help{
    position:absolute; top:12px; right:12px; z-index:2;
    width:28px; height:28px; border-radius:50%;
    display:flex; align-items:center; justify-content:center;
    font-family:'JetBrains Mono',monospace; font-size:15px; font-weight:700; line-height:1;
    color:var(--ink-dim); background:var(--glass); border:1px solid var(--glass-border);
    cursor:pointer; transition:color 0.15s, border-color 0.15s;
  }
  .hero-help:hover{ color:var(--teal); border-color:var(--teal); }
  .hero-help:focus-visible{ outline:2px solid var(--teal); outline-offset:2px; }
  .hero-stat::before{
    content:'';
    position:absolute; inset:-40%;
    background:conic-gradient(from 0deg, transparent, rgba(245,166,35,0.08), transparent 30%);
    animation:heroSpin 9s linear infinite;
    pointer-events:none;
  }
  @media (prefers-reduced-motion: reduce){ .hero-stat::before{ animation:none; } }
  .hero-stat .label{
    font-size:10.5px;text-transform:uppercase;letter-spacing:0.12em;
    color:var(--amber);margin-bottom:8px;font-family:'JetBrains Mono',monospace;
    position:relative; z-index:1;
  }
  .hero-stat .sub{font-size:11.5px;color:var(--ink-dim);margin-top:8px;font-family:'JetBrains Mono',monospace;position:relative;z-index:1;}

  /* ============================================================
     DESKTOP LAYOUT (>=860px) - same markup and JS as mobile, just
     reflowed: sidebar nav instead of bottom bar, wider content with
     paired/grid cards, bigger charts. Nothing below 860px changes.
  ============================================================ */
  @media (min-width: 860px){
    body{ padding-bottom:24px; padding-left:108px; }
    header{ padding:28px 32px 8px 32px; max-width:1100px; margin:0 auto; }
    header h1{ font-size:46px; }
    .header-actions{ right:30px; top:24px; }

    .bottomnav{
      left:16px; right:auto; bottom:16px; top:16px;
      width:84px; max-width:84px;
      flex-direction:column;
      border-radius:22px;
      padding:18px 8px;
      gap:10px;
      justify-content:flex-start;
    }
    .navbtn{ padding:13px 4px; flex:0 0 auto; gap:6px; border-radius:14px; }
    .navbtn svg{ width:22px; height:22px; }
    .navbtn span{ font-size:9.5px; letter-spacing:0.02em; }

    .wrap{ max-width:1100px; padding:16px 32px 0; }

    .dash-hero{ padding:32px 40px; gap:24px; }
    /* Room to breathe: the two supporting figures become tiles side by side, label above amount. */
    .hero-figs{ gap:10px; }
    .hero-fig{
      flex:1 1 150px;
      flex-direction:column; align-items:flex-start; justify-content:flex-start; gap:3px;
      padding:9px 13px;
      /* NOWRAP here on purpose. The tile is a ROW on mobile, where wrapping is what puts the note
         on its own line - but as a COLUMN a wrap makes a second COLUMN, and the note landed beside
         the amount instead of under it. Caught on screen, not in the markup. */
      flex-wrap:nowrap;
    }
    .hero-fig-note{ flex:0 0 auto; }
    .hero-fig-amt{ font-size:17px; }
    .hero-fig.is-square .hero-fig-amt{ font-size:14px; }
    .hero-flap{ margin:12px 0 12px; }
    .flap-char{ font-size:clamp(38px, 4vw, 58px); }
    .hero-mascot{ width:104px; height:110px; }

    .kpi-row{ grid-template-columns:repeat(4, 1fr); }
    .page-title{ font-size:38px; }

    /* Dashboard is a plain block; its one pair-grid splits into two balanced
       stack-col columns (cards assigned by height so neither column dead-ends). */
    #panel-dashboard.tabpanel{ display:none; }
    #panel-dashboard.tabpanel.active{ display:block; }

    /* Expense cards have no charts, so a CSS masonry packs the four uneven
       frequency lists into two balanced columns with no dead gaps. display:block
       overrides the mobile display:contents so the multicol box actually forms. */
    .expense-grid{ display:block; column-count:2; column-gap:16px; }
    .expense-grid > .card{ break-inside:avoid; -webkit-column-break-inside:avoid; }
    .dashboard-cards{ display:block; column-count:2; column-gap:16px; }
    .dashboard-cards > .card{ break-inside:avoid; -webkit-column-break-inside:avoid; }
    .pair-grid{
      display:grid; grid-template-columns:1fr 1fr; gap:16px; align-items:start;
    }
    .stack-col{ display:flex; flex-direction:column; gap:16px; }
    .chart-wrap{ height:280px; }
    .chart-wrap.short{ height:220px; }
    .chart-wrap.donut{ height:320px; }

    .saved-flag, .undo-toast{ left:108px; transform:translateX(0); bottom:24px; }
    .saved-flag.show{ transform:translateX(0); }
    .undo-toast.show{ transform:translateX(0) translateY(0); }
  }
  @media (min-width: 860px) and (max-width: 1099px){
    .wrap, header{ max-width:100%; }
  }

  /* ============================================================
     PRINTABLE REPORT - a self-contained light-on-white document,
     independent of whatever theme is active on screen. Hidden
     entirely until the browser is actually printing.
  ============================================================ */
  .print-only{ display:none; }
  @media print{
    body > *:not(#reportPrintArea){ display:none !important; }
    body{ background:#fff !important; animation:none !important; }
    #reportPrintArea.print-only{ display:block !important; }
    @page{ margin:14mm; }
  }
  #reportPrintArea{
    background:#fff; color:#161B22;
    font-family:'Public Sans',sans-serif;
    padding:0; max-width:720px; margin:0 auto;
  }
  .rpt-header{ margin-bottom:18px; border-bottom:2px solid #161B22; padding-bottom:10px; }
  .rpt-header .rpt-eyebrow{ font-family:'JetBrains Mono',monospace; font-size:10px; letter-spacing:0.1em; text-transform:uppercase; color:#C77A12; }
  .rpt-header h1{ font-family:'Big Shoulders Display',sans-serif; font-size:30px; font-weight:800; text-transform:uppercase; margin:2px 0; color:#161B22; }
  .rpt-header .rpt-date{ font-size:11px; color:#59626D; font-family:'JetBrains Mono',monospace; }
  .rpt-section{ margin:20px 0; page-break-inside:avoid; }
  .rpt-section h2{
    font-family:'Big Shoulders Display',sans-serif; font-size:17px; font-weight:700;
    text-transform:uppercase; color:#161B22; border-bottom:1px solid #D8D3C8; padding-bottom:4px; margin-bottom:10px;
  }
  .rpt-stats{ display:flex; gap:14px; flex-wrap:wrap; margin-bottom:6px; }
  .rpt-stat{ flex:1; min-width:110px; }
  .rpt-stat .rpt-stat-label{ font-size:9.5px; text-transform:uppercase; letter-spacing:0.05em; color:#8A929C; font-family:'JetBrains Mono',monospace; }
  .rpt-stat .rpt-stat-val{ font-family:'JetBrains Mono',monospace; font-weight:700; font-size:18px; color:#161B22; }
  .rpt-stat.hero .rpt-stat-val{ font-size:26px; color:#C77A12; }
  .rpt-table{ width:100%; border-collapse:collapse; font-size:12px; }
  .rpt-table td{ padding:6px 4px; border-bottom:1px solid #EAE6DC; }
  .rpt-table td:last-child{ text-align:right; font-family:'JetBrains Mono',monospace; font-weight:600; }
  .rpt-table tr.rpt-total td{ font-weight:700; border-top:1.5px solid #161B22; border-bottom:none; }
  .rpt-img{ width:100%; max-width:460px; display:block; margin:6px auto; }
  .rpt-note{ font-size:10.5px; color:#8A929C; margin-top:6px; }
  .rpt-plan-row{ display:flex; justify-content:space-between; padding:5px 0; font-size:12.5px; border-bottom:1px solid #EAE6DC; }
  .rpt-plan-row:last-child{ border-bottom:none; font-weight:700; }
  .rpt-plan-row.rpt-deduct{ color:#6B6659; }
  .rpt-subtotal{ display:flex; justify-content:space-between; padding:6px 0 4px; margin-top:2px; border-top:1.5px solid #CFC9BB; border-bottom:none; font-weight:700; font-size:13px; }

  /* ---- Auth gate (Phase 1). Full-screen sign-in / sign-up, shown by auth.js for
     signed-out users when AUTH_ENABLED (dev only for now). Opaque - covers the app. ---- */
  .auth-gate{ position:fixed; inset:0; z-index:2000; display:flex; align-items:flex-start; justify-content:center;
    padding:max(40px,8vh) 20px 40px; background:var(--bg-deep); overflow-y:auto; }
  .auth-gate.hidden{ display:none; }
  body.auth-locked{ overflow:hidden; }
  .auth-card{ width:100%; max-width:380px; background:var(--glass); border:1px solid var(--glass-border);
    border-radius:var(--radius); padding:30px 24px 22px; box-shadow:var(--card-shadow);
    backdrop-filter:blur(18px) saturate(140%); -webkit-backdrop-filter:blur(18px) saturate(140%); }
  .auth-logo{ text-align:center; font-family:'Fraunces',Georgia,serif; font-weight:600; font-size:24px;
    letter-spacing:0.01em; color:var(--amber); margin-bottom:16px; }
  .auth-title{ font-size:20px; font-weight:700; color:var(--ink); text-align:center; margin:0 0 4px; }
  .auth-sub{ font-size:13px; color:var(--ink-dim); text-align:center; margin:0 0 18px; line-height:1.45; }
  .auth-tabs{ display:flex; gap:4px; background:var(--glass-strong); border-radius:11px; padding:4px; margin-bottom:16px; }
  .auth-tab{ flex:1; padding:9px; border:none; background:none; border-radius:8px; color:var(--ink-dim);
    font-size:13px; font-weight:600; cursor:pointer; }
  .auth-tab.active{ background:var(--glass); color:var(--ink); box-shadow:0 1px 3px rgba(0,0,0,0.14); }
  .auth-field{ display:block; margin-bottom:12px; }
  .auth-field span{ display:block; font-size:12px; color:var(--ink-dim); margin-bottom:5px; }
  .auth-field input{ width:100%; padding:11px 12px; border-radius:10px; border:1px solid var(--glass-border);
    background:var(--bg-deep-2); color:var(--ink); font-size:16px; }
  .auth-field input:focus-visible{ outline:2px solid var(--amber); outline-offset:1px; }
  /* Password requirement, stated up front (shown in sign-up / reset, hidden in sign-in).
     Higher specificity than `.auth-field span` so it sits below the input, not above it. */
  .auth-field .auth-hint{ margin:6px 0 0; font-size:11.5px; color:var(--ink-faint); line-height:1.4; }
  /* Signup / re-consent checkboxes. The whole label is tappable (the text toggles it), so the
     touch target is comfortably large on mobile even though the box is 20px. */
  .auth-consent{ display:flex; flex-direction:column; gap:11px; margin:2px 0 14px; }
  .auth-check{ display:flex; align-items:flex-start; gap:10px; font-size:12.5px; color:var(--ink-dim);
    line-height:1.45; cursor:pointer; }
  .auth-check input[type=checkbox]{ flex:none; width:20px; height:20px; margin-top:1px; accent-color:var(--amber); cursor:pointer; }
  .auth-check a{ color:var(--amber); text-decoration:underline; text-underline-offset:2px; }
  /* Settings marketing toggle (a switch). */
  .mkt-toggle{ position:relative; display:inline-block; width:46px; height:26px; flex:none; }
  .mkt-toggle input{ position:absolute; opacity:0; width:100%; height:100%; margin:0; cursor:pointer; }
  .mkt-slider{ position:absolute; inset:0; background:var(--glass-border-strong); border-radius:999px; transition:background .18s; }
  .mkt-slider::before{ content:''; position:absolute; width:20px; height:20px; left:3px; top:3px; background:#fff;
    border-radius:50%; transition:transform .18s; box-shadow:0 1px 3px rgba(0,0,0,0.3); }
  .mkt-toggle input:checked + .mkt-slider{ background:var(--amber); }
  .mkt-toggle input:checked + .mkt-slider::before{ transform:translateX(20px); }
  .mkt-toggle input:disabled + .mkt-slider{ opacity:0.5; }
  .mkt-toggle input:focus-visible + .mkt-slider{ outline:2px solid var(--amber); outline-offset:2px; }
  .err-note{ color:var(--red); }
  .auth-submit{ width:100%; margin-top:4px; padding:12px; border:none; border-radius:10px;
    background:var(--grad-amber); color:var(--bg-deep); font-size:15px; font-weight:700; cursor:pointer; }
  .auth-submit:disabled{ opacity:0.6; cursor:default; }
  .auth-linkbtn{ display:block; width:100%; margin-top:12px; background:none; border:none; color:var(--ink-dim);
    font-size:12.5px; cursor:pointer; text-decoration:underline; }
  .auth-msg{ margin-top:12px; font-size:12.5px; text-align:center; line-height:1.45; min-height:1.1em; color:var(--ink-dim); }
  .auth-msg.err{ color:var(--amber-2); }
  .auth-msg.ok{ color:var(--amber); }
  /* Cross-account refusal hint (sync 2B Task 9): wraps the "Switch account" link-button shown
     alongside authMsg's refusal copy. Muted-hint idiom, matching .auth-field .auth-hint above -
     the button itself already carries .auth-linkbtn's colour/size, this just centres it. */
  .auth-switch-hint{ text-align:center; }

  /* ---- Sign-up wizard (plan choice, iOS Add-to-Home-Screen, data warning, personalise) ---- */
  .auth-step-lead{ font-size:13.5px; color:var(--ink); line-height:1.5; margin:0 0 14px; }
  .auth-warn-body{ font-size:13px; color:var(--ink-dim); line-height:1.55; margin:0 0 14px; }
  .pers-intro{ font-size:13px; color:var(--ink-dim); line-height:1.5; margin:0 0 16px; }   /* post-signup personalise overlay */
  .plan-cards{ display:flex; flex-direction:column; gap:12px; margin:2px 0 16px; }
  .plan-card{ display:block; width:100%; text-align:left; background:var(--glass); border:1.5px solid var(--glass-border);
    border-radius:14px; padding:14px 16px; cursor:pointer; color:var(--ink); }
  .plan-card.selected{ border-color:var(--amber); box-shadow:0 0 0 3px rgba(245,166,35,.16); }
  .plan-card.is-soon{ opacity:.7; cursor:default; }
  .plan-name{ font-size:15px; font-weight:700; display:flex; align-items:center; justify-content:space-between; gap:8px; margin-bottom:9px; }
  .plan-tag{ font-size:10px; font-weight:700; text-transform:uppercase; letter-spacing:.05em; color:var(--amber); }
  .plan-tag.soon{ color:var(--ink-dim); }
  .plan-feats{ list-style:none; margin:0; padding:0; display:flex; flex-direction:column; gap:6px; }
  .plan-feats li{ font-size:12.5px; color:var(--ink-dim); line-height:1.4; padding-left:17px; position:relative; }
  .plan-feats li::before{ content:"\2713"; position:absolute; left:0; color:var(--amber); font-weight:700; }
  .ios-steps{ margin:0 0 16px; padding-left:20px; display:flex; flex-direction:column; gap:9px; }
  .ios-steps li{ font-size:13px; color:var(--ink-dim); line-height:1.45; }
  .ios-share{ display:inline-block; border:1px solid var(--glass-border); border-radius:5px; padding:0 6px; font-weight:700; color:var(--ink); }
  .pers-field{ display:flex; flex-direction:column; gap:8px; margin:0 0 16px; font-size:13px; color:var(--ink-dim); }
  .pers-field > span{ font-weight:600; color:var(--ink); }
  .pers-field input[type=date]{ padding:11px 12px; border-radius:10px; border:1px solid var(--glass-border); background:var(--glass); color:var(--ink); font-size:14px; }
  .pers-cadence{ display:flex; gap:8px; }
  .pers-cadence button{ flex:1; padding:10px 6px; border-radius:10px; border:1.5px solid var(--glass-border); background:var(--glass); color:var(--ink-dim); font-size:12.5px; font-weight:600; cursor:pointer; }
  .pers-cadence button.active{ border-color:var(--amber); color:var(--ink); box-shadow:0 0 0 2px rgba(245,166,35,.16); }

  /* ---- Free-tier backup reminder (dashboard card; dismissible, never blocking) ---- */
  .backup-reminder{ background:var(--glass); border:1px solid var(--glass-border); border-left:3px solid var(--amber);
    border-radius:12px; padding:13px 15px; margin:0 0 14px; }
  .br-text{ font-size:12.5px; color:var(--ink-dim); line-height:1.5; }
  .br-text b{ display:block; color:var(--ink); font-size:13.5px; margin-bottom:3px; }
  .br-actions{ display:flex; gap:9px; margin-top:12px; flex-wrap:wrap; }
  .br-primary{ padding:9px 15px; border:none; border-radius:9px; background:var(--grad-amber); color:var(--bg-deep); font-size:13px; font-weight:700; cursor:pointer; }
  .br-ghost{ padding:9px 12px; border:1px solid var(--glass-border); border-radius:9px; background:none; color:var(--ink-dim); font-size:13px; cursor:pointer; }
  .auth-fineprint{ margin-top:16px; font-size:11px; color:var(--ink-faint); text-align:center; line-height:1.4; }
