/* Timesheets app — theme tokens + timesheet rules copied VERBATIM from inline/static/css/app.css (2026-10-19)
   so it looks exactly like the InLine timesheet. App-only bits (login, top bar, jobs sheet) at the bottom. */
:root{
  --navh:64px;
  /* P1: desktop column floor width (More-tab slider drives this; grows to content, capped) + whole-board zoom */
  --col-w:305px; --board-zoom:1;
  /* 2026-08-03 (his pick "B · Graphite", after "colours look AI"): the indigo #4F46E5 was
     THE AI-product accent, and it was everywhere. Graphite makes the chrome quiet so colour
     can mean one thing again — red = overdue, green = done, amber = waiting. --on-accent is
     the text that sits ON an accent fill: white here, dark ink in the dark theme (where the
     accent is a LIGHT grey and white-on-accent would vanish). */
  --accent:#3F4653; --on-accent:#fff;
  --bg:#F2F3F5; --card:#fff; --ink:#161821; --border:#E3E5E9;
  --muted:#555A66; --faint:#9BA0AB; --third:#878C99;
  --ai-body:#3A3E4A;
  --line:#EDEEF1; --soft:#F1F2F6; --soft-border:#E2E4EA;
  /* 2026-08-10 colour tune (his call: the saturated set "looks AI"): state colours pulled down
     to the industrial family — forest / brass / brick. Hue meanings unchanged. */
  --good:#2E8B6A; --warn:#A9822F; --danger:#B4544A; --mail:#41678F; --warr:#6C7488;
  /* D13: deep text tones for sitting ON the tinted washes (light needs darker-than-token text
     for contrast; dark flips to brighter-than-token). Replaces scattered #157A52/#B07A12/etc. */
  --good-deep:#256E54; --warn-deep:#8F6E28;
  /* 2026-09-02d design tokens. Type scale: 11/12/13/14/16/18 — every app.css font-size that
     sat within 0.5px of a step now reads the token (10.5→fs-1, 11.5→fs-2, 12.5→fs-3, 13.5→fs-4,
     16.5→fs-5). Micro sizes (8–10px: badges, kickers, calendar cells) and display sizes
     (15px body, 17/19/20/21/22px titles) stay literal on purpose — snapping them would have
     been a redesign, not a consolidation. Radii: sm 8 (was 8/9) · md 12 (was 10/11/12/13) ·
     lg 16 (was 14/16) · pill 999 (was 20/99/999). --radius stays as the card alias. */
  --fs-1:11px; --fs-2:12px; --fs-3:13px; --fs-4:14px; --fs-5:16px; --fs-6:18px;
  --r-sm:8px; --r-md:12px; --r-lg:16px; --r-pill:999px;
  --radius:var(--r-lg);
  --sh:0 1px 2px rgba(20,21,26,.05);
  --sh2:0 8px 24px rgba(0,0,0,.28);
  --accent-glow:rgba(20,21,26,.10); --danger-glow:rgba(20,21,26,.12);
  /* accent tints — hex fallback first, then color-mix (older WebViews ignore the mix line) */
  --accent-7:#ECECFB;  --accent-7:color-mix(in oklab,var(--accent) 7%,#fff);
  --accent-9:#E7E7FA;  --accent-9:color-mix(in oklab,var(--accent) 9%,#fff);
  --accent-10:#E6E6FA; --accent-10:color-mix(in oklab,var(--accent) 10%,#fff);
  --accent-13:#DEDEF8; --accent-13:color-mix(in oklab,var(--accent) 13%,#fff);
  --accent-15:#DADAF7; --accent-15:color-mix(in oklab,var(--accent) 15%,#fff);
  --accent-16:#D8D8F6; --accent-16:color-mix(in oklab,var(--accent) 16%,#fff);
  --accent-22:#CBCBF3; --accent-22:color-mix(in oklab,var(--accent) 22%,#fff);
  --accent-26:#C2C2F1; --accent-26:color-mix(in oklab,var(--accent) 26%,#fff);
  --mail-16:#D7E7FD;   --mail-16:color-mix(in oklab,var(--mail) 16%,#fff);
  --mail-30:#B3D0FA;   --mail-30:color-mix(in oklab,var(--mail) 30%,#fff);
  /* file-type badge colours (theme-aware; brighter set in dark) */
  --ft-pdf:#B4544A; --ft-img:#41678F; --ft-xls:#2E8B6A; --ft-doc:#4A5568; --ft-msg:#6C7488; --ft-other:#64748B;
  --good-8:#E7F8F1;    --good-8:color-mix(in oklab,var(--good) 8%,#fff);
  --good-13:#DDF5EC;   --good-13:color-mix(in oklab,var(--good) 13%,#fff);
  --good-18:#D2F2E5;   --good-18:color-mix(in oklab,var(--good) 18%,#fff);
  --good-22:#C9EFDF;   --good-22:color-mix(in oklab,var(--good) 22%,#fff);
  --good-30:#B6E9D2;   --good-30:color-mix(in oklab,var(--good) 30%,#fff);
  --warn-8:#FEF6E7;    --warn-8:color-mix(in oklab,var(--warn) 8%,#fff);
  --warn-13:#FDF1D8;   --warn-13:color-mix(in oklab,var(--warn) 13%,#fff);
  --warn-24:#FCE7B8;   --warn-24:color-mix(in oklab,var(--warn) 24%,#fff);
  --warr-8:#F2EDFC;    --warr-8:color-mix(in oklab,var(--warr) 8%,#fff);
  --warr-13:#EBE2FA;   --warr-13:color-mix(in oklab,var(--warr) 13%,#fff);
  --warr-22:#DDD0F6;   --warr-22:color-mix(in oklab,var(--warr) 22%,#fff);
}
body.dark{
  --accent:#B9C2D0; --on-accent:#171A1F;
  --bg:#0E1013; --card:#171A1F; --ink:#E9ECF1; --border:#262A31;
  --muted:#9BA2AC; --faint:#6C727C; --third:#828997;
  --ai-body:#C4C9D4;
  --line:#262A31; --soft:#1A1D22; --soft-border:#282C33;
  /* 2026-08-10 colour tune — dark theme pulled to the same industrial family */
  --good:#4E9C7C; --warn:#C29255; --danger:#C26A5D; --mail:#8A93A3; --warr:#8A93A3;
  --good-deep:#5FB392; --warn-deep:#D3A967;
  --sh:0 1px 2px rgba(0,0,0,.4);
  --sh2:0 10px 30px rgba(0,0,0,.55);
  --accent-glow:rgba(0,0,0,.42); --danger-glow:rgba(0,0,0,.42);
  --accent-7:#1C1F30;  --accent-7:color-mix(in oklab,var(--accent) 12%,#1B1E27);
  --accent-9:#1F2336;  --accent-9:color-mix(in oklab,var(--accent) 15%,#1B1E27);
  --accent-10:#202438; --accent-10:color-mix(in oklab,var(--accent) 16%,#1B1E27);
  --accent-13:#242942; --accent-13:color-mix(in oklab,var(--accent) 20%,#1B1E27);
  --accent-15:#272C48; --accent-15:color-mix(in oklab,var(--accent) 23%,#1B1E27);
  --accent-16:#282E4A; --accent-16:color-mix(in oklab,var(--accent) 24%,#1B1E27);
  --accent-22:#2E3556; --accent-22:color-mix(in oklab,var(--accent) 30%,#1B1E27);
  --accent-26:#323A60; --accent-26:color-mix(in oklab,var(--accent) 34%,#1B1E27);
  --mail-16:#1B2740;   --mail-16:color-mix(in oklab,var(--mail) 22%,#1B1E27);
  --mail-30:#2A4166;   --mail-30:color-mix(in oklab,var(--mail) 36%,#1B1E27);
  --ft-pdf:#D98A7C; --ft-img:#8FA9C9; --ft-xls:#5FAE8F; --ft-doc:#9AA6C9; --ft-msg:#9A93B8; --ft-other:#8A93A3;
  --good-8:#15241F;    --good-8:color-mix(in oklab,var(--good) 14%,#1B1E27);
  --good-13:#16291F;   --good-13:color-mix(in oklab,var(--good) 18%,#1B1E27);
  --good-18:#173123;   --good-18:color-mix(in oklab,var(--good) 22%,#1B1E27);
  --good-22:#173826;   --good-22:color-mix(in oklab,var(--good) 26%,#1B1E27);
  --good-30:#19422C;   --good-30:color-mix(in oklab,var(--good) 32%,#1B1E27);
  --warn-8:#2A2316;    --warn-8:color-mix(in oklab,var(--warn) 14%,#1B1E27);
  --warn-13:#322817;   --warn-13:color-mix(in oklab,var(--warn) 18%,#1B1E27);
  --warn-24:#42351A;   --warn-24:color-mix(in oklab,var(--warn) 28%,#1B1E27);
  --warr-8:#241D33;    --warr-8:color-mix(in oklab,var(--warr) 14%,#1B1E27);
  --warr-13:#281F3C;   --warr-13:color-mix(in oklab,var(--warr) 18%,#1B1E27);
  --warr-22:#2F2350;   --warr-22:color-mix(in oklab,var(--warr) 28%,#1B1E27);
}
*{box-sizing:border-box;margin:0;padding:0;-webkit-tap-highlight-color:transparent}
/* D12 (2026-07-05) More-tab dark wash-out ROOT CAUSE: buttons kept the UA's near-black
   `buttontext` colour + system font — invisible in light (black≈ink) but grey-on-grey in dark.
   Inherit both; classes that set their own colour/font still override. */
button{font-family:inherit;color:inherit}
::-webkit-scrollbar{width:0;height:0;background:transparent}
*{scrollbar-width:none;-ms-overflow-style:none}
:root{--warn-wash:#FDF6E9;--warn-wash:color-mix(in oklab,var(--warn) 6%,var(--card));--danger-wash:#FDECEC;--danger-wash:color-mix(in oklab,var(--danger) 5%,var(--card));--navh:0px}
body.dark{--warn-wash:#332D20;--warn-wash:color-mix(in oklab,var(--warn) 13%,var(--card));--danger-wash:#33232B;--danger-wash:color-mix(in oklab,var(--danger) 13%,var(--card))}
body{font-family:'Hanken Grotesk',system-ui,sans-serif;background:var(--bg);color:var(--ink);font-size:15px;-webkit-font-smoothing:antialiased}
.clamp1{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.page{padding:16px 16px calc(110px + env(safe-area-inset-bottom));display:flex;flex-direction:column;gap:15px}   /* polish 08-15 #2: clearance for the ＋ FAB (74px bottom + 50px) — it was sitting on the last row's actions */
.pgstack{display:flex;flex-direction:column;gap:15px}
.card{background:var(--card);border:1px solid var(--border);border-radius:var(--radius);box-shadow:var(--sh)}
.btn{font-family:'Hanken Grotesk';font-weight:650;font-size:var(--fs-4);letter-spacing:.01em;border:none;border-radius:var(--r-md);padding:13px 16px;cursor:pointer;color:var(--on-accent);white-space:nowrap;
  background:var(--accent);
  box-shadow:0 1px 2px var(--accent-glow)}
@media(hover:hover){.btn:hover{filter:brightness(1.05)}}
.btn.ghost{background:var(--card);background-image:none;color:var(--ink);border:1px solid var(--border);box-shadow:var(--sh)}
@media(hover:hover){.btn.ghost:hover{background:var(--soft);border-color:var(--soft-border);filter:none}}
.btn.soft{background:var(--accent-10);background-image:none;color:var(--accent);border:1px solid var(--accent-16);box-shadow:none}
@media(hover:hover){.btn.soft:hover{background:var(--accent-13);filter:none}}
.btn.danger{background:var(--danger);color:#fff;box-shadow:0 1px 2px var(--danger-glow)}
.btn.sm{padding:9px 14px;font-size:var(--fs-3);border-radius:var(--r-md)}
.btn.full{width:100%}
.btn.ic{display:inline-flex;align-items:center;justify-content:center;gap:6px}
.btn:disabled{opacity:.5;cursor:default;box-shadow:none;filter:none}
input,textarea,select{font-family:inherit;font-size:var(--fs-4);border:1px solid var(--soft-border);border-radius:var(--r-md);padding:12px 13px;width:100%;background:var(--card);color:var(--ink)}
input:focus,textarea:focus,select:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-13)}
input::placeholder,textarea::placeholder{color:var(--faint);opacity:1}
.addcard{border:1.5px dashed var(--soft-border);background:transparent;border-radius:var(--r-lg);padding:11px;cursor:pointer;color:var(--faint);font-family:'Hanken Grotesk';font-size:var(--fs-2);font-weight:600}
.mirror{flex:0 0 auto;display:inline-flex;align-items:center;gap:4px;font-size:var(--fs-1);font-weight:700;color:var(--accent);background:var(--accent-9);border:1px solid var(--accent-22);border-radius:var(--r-sm);padding:5px 9px;cursor:pointer}
.jump,.seg button,.iconbtn,.qt-suggest,.addcard,.btn{transition:background .15s ease,color .15s ease,transform .12s ease,box-shadow .15s ease}
.jump:active,.seg button:active,.iconbtn:active,.addcard:active,.btn:active{transform:scale(.95)}
.toast{position:fixed;bottom:96px;left:50%;transform:translateX(-50%);background:var(--ink);color:var(--bg);font-size:var(--fs-3);font-weight:600;padding:10px 16px;border-radius:var(--r-md);z-index:99;box-shadow:var(--sh2);opacity:0;transition:opacity .2s;pointer-events:none;max-width:90%;text-align:center}
.toast.show{opacity:1;pointer-events:auto}
body{text-rendering:optimizeLegibility;line-height:1.45;letter-spacing:-.06px}
.tsov-grid{display:flex;align-items:stretch}
/* 2026-07-28e UI PASS (user: "fix inline timesheet UI make it better don't change functions at
   all"). Everything from here to .ts-ac is PRESENTATION ONLY — the inline style soup moved into
   classes, day totals now baseline-align (margin-top:auto), today's column is marked, and the
   weekend reads differently from a work day. Same data, same derivations, same handlers. */
.tsov-c{flex:1;min-width:0;padding:9px 3px 8px;border-right:1px solid var(--line);display:flex;flex-direction:column}
.tsov-c:last-child{border-right:none}
/* P7 QL-batch (2026-07-16, item 152): an empty day doesn't need a worked day's width — a dash
   shrinks to .55 flex so the chip-carrying columns get the space back on a phone. */
.tsov-c.off{flex:.55}
.tsov-c.has{background:var(--accent-7)}
.tsov-c.wknd{background:var(--soft)}
.tsov-c.wknd.has{background:var(--warn-wash)}
.tsov-c.today{box-shadow:inset 0 2px 0 var(--accent)}
.tsov-c .d{text-align:center;font-size:10px;font-weight:800;letter-spacing:.02em;color:var(--ink)}
.tsov-c.today .d{color:var(--accent)}
.tsov-c .dt{text-align:center;font-size:9px;color:var(--faint);margin-bottom:6px}
.tsov-c .dash{text-align:center;color:var(--faint);font-size:10px;padding:2px 0}
.tsov-chip{text-align:center;font-size:9.5px;background:var(--accent-13);border-radius:5px;padding:3px 2px;margin:0 1px 3px}
.tsov-chip b{display:block;color:var(--accent);font-family:'JetBrains Mono';font-size:var(--fs-1);line-height:1.25}
.tsov-chip .clamp1{opacity:.85}
.tsov-c .tot{margin-top:auto;text-align:center;font-size:var(--fs-1);font-weight:700;color:var(--accent);font-family:'JetBrains Mono';border-top:1px dashed var(--line);padding-top:4px;margin-left:1px;margin-right:1px}
.tsov-c .tot.z{color:var(--faint)}
.tsov-hd{display:flex;align-items:baseline;gap:8px;padding:10px 13px 9px}
.tsov-hd .h{font-size:10px;font-weight:800;letter-spacing:.09em;color:var(--muted)}
.tsov-hd .s{margin-left:auto;font-family:'JetBrains Mono';font-size:10px;color:var(--faint)}
/* week header card */
.ts-week{padding:0;overflow:hidden}
.ts-week .wnav{display:flex;align-items:center;gap:9px;padding:13px 12px}
.ts-week .wbtn{width:40px;height:40px;flex:0 0 auto;display:flex;align-items:center;justify-content:center;border:1px solid var(--border);background:var(--card);border-radius:var(--r-md);color:var(--muted);cursor:pointer;font-family:inherit;box-shadow:var(--sh);padding:0}
.ts-week .wbtn:active{background:var(--accent-10);color:var(--accent);border-color:var(--accent-22)}
.ts-week .wmid{flex:1;min-width:0;text-align:center}
.ts-week .wmid .l{font-size:9px;font-weight:800;letter-spacing:.11em;color:var(--faint)}
.ts-week .wmid .d{font-family:'Space Grotesk';font-size:var(--fs-6);font-weight:700;letter-spacing:-.3px;line-height:1.25}
.ts-week .wmid .r{font-family:'JetBrains Mono';font-size:var(--fs-1);color:var(--faint)}
.ts-week .wmeta{display:flex;align-items:center;gap:10px;padding:9px 14px;border-top:1px solid var(--line);background:var(--soft)}
.ts-week .who{flex:1;min-width:0;font-size:var(--fs-2);color:var(--faint);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ts-week .who b{color:var(--ink);font-weight:700}
.ts-week .who i{font-style:normal;margin:0 6px;opacity:.5}
.ts-week .wtot{flex:0 0 auto;text-align:right;line-height:1.15}
.ts-week .wtot .l{display:block;font-size:8.5px;font-weight:800;letter-spacing:.09em;color:var(--faint)}
.ts-week .wtot .n{font-family:'JetBrains Mono';font-size:var(--fs-5);font-weight:800;color:var(--accent)}
/* entry card */
.ts-list{display:flex;flex-direction:column;gap:10px}
.ts-card{padding:0;overflow:hidden}
.ts-card.on{border-color:var(--accent-22)}
.ts-head{width:100%;background:none;border:none;padding:12px 13px;display:flex;align-items:center;gap:10px;cursor:pointer;text-align:left;font-family:inherit}
.ts-head .n{flex:1;min-width:0}
.ts-head .t{font-size:var(--fs-4);font-weight:600;color:var(--ink)}
.ts-card.blank .ts-head .t{color:var(--faint);font-weight:500}
.ts-code{display:inline-block;margin-top:4px;font-family:'JetBrains Mono';font-size:10px;font-weight:700;letter-spacing:.03em;color:var(--accent);background:var(--accent-9);border:1px solid var(--accent-16);border-radius:6px;padding:1px 6px}
.ts-hrs{flex:0 0 auto;font-family:'JetBrains Mono';font-weight:700;font-size:var(--fs-3);padding:4px 10px;border-radius:var(--r-sm);border:1px solid transparent;color:var(--faint)}
.ts-hrs.on{background:var(--accent-9);color:var(--accent);border-color:var(--accent-16)}
.ts-chev{flex:0 0 auto;display:flex;color:var(--faint);transition:transform .18s cubic-bezier(.22,.61,.36,1)}
.ts-card.on .ts-chev{transform:rotate(90deg);color:var(--accent)}
.ts-body{padding:13px;border-top:1px solid var(--line);flex-direction:column;gap:14px}
.ts-lbl{display:flex;align-items:baseline;gap:7px;font-family:'JetBrains Mono';font-size:9.5px;font-weight:700;letter-spacing:.09em;text-transform:uppercase;color:var(--muted);margin-bottom:7px}
.ts-lbl i{font-style:normal;font-family:'Hanken Grotesk';font-size:var(--fs-1);font-weight:600;letter-spacing:0;text-transform:none;color:var(--faint)}
.ts-jobfields{display:flex;gap:8px}
/* P7 QL-batch (2026-07-16, item 152 "still squished"): the entry editor's hour cells were a
   hard repeat(4,1fr) — at 390px each −/＋/input trio left the input ~25px. Auto-fill sizes to
   the space: phones get 3 roomy columns, desktop 4+. Paid grid follows the same rule. */
.ts-hours-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(88px,1fr));gap:8px 7px}
.ts-day{border:1px solid var(--soft-border);border-radius:var(--r-md);padding:6px 5px 5px;background:var(--card);text-align:center}
.ts-day.wknd{background:var(--soft)}
.ts-day.on{border-color:var(--accent-22);background:var(--accent-7)}
.ts-day .dh{font-size:9.5px;font-weight:800;letter-spacing:.06em;color:var(--muted)}
.ts-day.on .dh{color:var(--accent)}
.ts-day .dd{display:block;font-size:8.5px;font-weight:600;color:var(--faint);margin-top:1px}
.ts-stp{display:flex;align-items:center;gap:3px;margin-top:5px}
.ts-stp button{width:26px;height:32px;flex:0 0 auto;border:1px solid var(--soft-border);background:var(--card);border-radius:var(--r-sm);font-size:var(--fs-5);font-weight:700;line-height:1;color:var(--muted);cursor:pointer;padding:0;font-family:inherit}
.ts-stp button:active{background:var(--accent-10);color:var(--accent);border-color:var(--accent-22)}
.ts-stp input{flex:1;min-width:0;width:100%;padding:7px 0;text-align:center;font-family:'JetBrains Mono';font-size:var(--fs-4);font-weight:700;border-radius:var(--r-sm)}
.ts-day.on .ts-stp input{color:var(--accent);border-color:var(--accent-22)}
.ts-paid{border:1px dashed var(--soft-border);border-radius:var(--r-md);padding:11px 11px 12px;background:var(--soft)}
.ts-paid-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(74px,1fr));gap:9px 7px}
.ts-paid-grid .pl{font-size:9.5px;font-weight:800;letter-spacing:.05em;color:var(--muted);margin-bottom:3px;text-align:center}
.ts-paid-grid input{padding:7px 2px;text-align:center;font-family:'JetBrains Mono';font-size:var(--fs-3);border-radius:var(--r-sm)}
.ts-foot{display:flex;justify-content:space-between;align-items:center;gap:10px;border-top:1px solid var(--line);margin:0 -13px -13px;padding:10px 13px}
.ts-foot .hint{font-size:var(--fs-1);color:var(--faint)}
.ts-foot .hint b{color:var(--accent);font-family:'JetBrains Mono';font-weight:800;font-size:var(--fs-2)}
.ts-add{width:100%;display:flex;align-items:center;justify-content:center;gap:7px}
/* floating save bar — only while there are unsaved edits; fires the SAME saveConfirm() */
.ts-dirtybar{position:fixed;left:0;right:0;bottom:calc(var(--navh) + 10px);z-index:50;display:flex;justify-content:center;pointer-events:none;padding:0 14px}
.ts-dirtybar > div{pointer-events:auto;display:flex;align-items:center;gap:11px;background:var(--card);border:1px solid var(--accent-22);border-radius:var(--r-pill);box-shadow:0 8px 24px rgba(0,0,0,.22);padding:7px 8px 7px 15px;max-width:100%}
.ts-dirtybar .m{font-size:var(--fs-2);font-weight:600;color:var(--muted);white-space:nowrap;display:flex;align-items:center;gap:7px}
.ts-dirtybar .m::before{content:'';width:7px;height:7px;border-radius:50%;background:var(--warn);flex:0 0 auto;box-shadow:0 0 0 3px var(--warn-wash)}
.ts-dirtybar .m b{color:var(--ink);font-family:'JetBrains Mono';font-weight:800}
.ts-ac{margin-top:6px;display:flex;flex-direction:column;max-height:220px;overflow:auto;border-radius:var(--r-sm)}
.ts-ac:empty{display:none}
.ts-ac button{display:block;width:100%;text-align:left;background:var(--card);border:1px solid var(--border);border-bottom:none;padding:9px 11px;cursor:pointer;font-size:var(--fs-3);font-family:inherit}
.ts-ac button:first-child{border-radius:var(--r-sm) var(--r-sm) 0 0}
.ts-ac button:last-child{border-bottom:1px solid var(--border);border-radius:0 0 var(--r-sm) var(--r-sm)}
.ts-ac button:active,.ts-ac button:hover{background:var(--soft)}

/* ── app-only (not in InLine) ─────────────────────────────────────────────────────────────── */
*{box-sizing:border-box;margin:0;padding:0;-webkit-tap-highlight-color:transparent}
button{font-family:inherit;color:inherit}
html,body{min-height:100%}
[x-cloak]{display:none!important}
.wrap{max-width:640px;margin:0 auto}
.page{padding-bottom:calc(90px + env(safe-area-inset-bottom))}
.ts-dirtybar{bottom:calc(14px + env(safe-area-inset-bottom))}
.top{position:sticky;top:0;z-index:40;background:var(--bg);border-bottom:1px solid var(--line);padding:calc(10px + env(safe-area-inset-top)) 16px 10px;display:flex;align-items:center;gap:10px}
.top .ttl{flex:1;font-family:'Space Grotesk';font-size:var(--fs-6);font-weight:700;letter-spacing:-.3px}
.top .tbtn{height:38px;padding:0 12px;border:1px solid var(--border);background:var(--card);border-radius:var(--r-md);font-size:var(--fs-3);font-weight:650;color:var(--ink);cursor:pointer;display:inline-flex;align-items:center;gap:6px;box-shadow:var(--sh)}
.top .tbtn.on{background:var(--accent-10);border-color:var(--accent-22);color:var(--accent)}
.login{min-height:100vh;display:flex;align-items:center;justify-content:center;padding:24px}
.login .card{width:100%;max-width:380px;padding:24px 20px;display:flex;flex-direction:column;gap:12px}
.login h1{font-family:'Space Grotesk';font-size:22px;font-weight:700;letter-spacing:-.3px}
.login p{color:var(--muted);font-size:var(--fs-3)}
.lbl{font-size:var(--fs-2);font-weight:700;color:var(--muted);margin-bottom:5px}
.err{color:var(--danger);font-size:var(--fs-3);font-weight:600}
.sheet-bg{position:fixed;inset:0;background:rgba(0,0,0,.45);z-index:90;display:flex;align-items:flex-end;justify-content:center}
.sheet{background:var(--card);width:100%;max-width:640px;border-radius:var(--r-lg) var(--r-lg) 0 0;padding:20px 16px calc(24px + env(safe-area-inset-bottom));max-height:88vh;overflow:auto}
.sheet h3{font-size:17px;font-weight:700;margin-bottom:10px}
.sheet .body{font-size:14px;color:var(--muted);margin-bottom:20px;line-height:1.55}
.job-row{display:flex;align-items:center;gap:10px;padding:11px 13px;border-top:1px solid var(--line)}
.job-row:first-child{border-top:none}
.job-row .c{font-family:'JetBrains Mono';font-weight:700;font-size:var(--fs-3);color:var(--accent);min-width:64px}
.job-row .nm{flex:1;min-width:0;font-size:var(--fs-4)}
.job-row button{background:none;border:none;color:var(--faint);font-size:var(--fs-2);font-weight:700;cursor:pointer;padding:6px}
.job-add{display:flex;gap:8px;padding:12px 13px;border-top:1px solid var(--line);background:var(--soft)}
.muted{color:var(--muted);font-size:var(--fs-3)}
.sp{font-size:10px;font-weight:700;color:var(--faint);margin-left:6px}
.apv-info{display:flex;flex-direction:column;gap:6px;border:1px solid var(--line);border-radius:var(--r-md);padding:10px 12px;background:var(--soft)}
.apv-info div{display:flex;gap:10px;font-size:var(--fs-3)}
.apv-info b{min-width:56px;color:var(--muted);font-weight:700}
.apv-info span{flex:1;min-width:0;word-break:break-word}
/* 1.1.0 UI simplify: ONE bottom bar (status + Save + Excel) instead of a button row + floating pill */
.actbar{position:fixed;left:0;right:0;bottom:0;z-index:50;background:var(--card);border-top:1px solid var(--border);box-shadow:0 -6px 20px rgba(0,0,0,.08);padding:10px 16px calc(10px + env(safe-area-inset-bottom))}
.actbar>div{max-width:640px;margin:0 auto;display:flex;align-items:center;gap:8px}
.actbar .st{flex:1;min-width:0;font-size:var(--fs-3);font-weight:650;color:var(--muted);display:flex;align-items:center;gap:7px}
.actbar .st::before{content:'';width:8px;height:8px;border-radius:50%;flex:0 0 auto;background:var(--good)}
.actbar .st.dirty::before{background:var(--warn);box-shadow:0 0 0 3px var(--warn-wash)}
.actbar .btn{padding:11px 16px}
.job-form{padding:14px;display:flex;flex-direction:column;gap:10px}
.job-form .ts-lbl{margin-bottom:0}
.linkdel{align-self:center;background:none;border:none;color:var(--danger);font-weight:700;font-size:var(--fs-3);padding:6px;cursor:pointer}
button.job-row{width:100%;background:none;border:none;border-top:1px solid var(--line);text-align:left;cursor:pointer;font-family:inherit}
button.job-row:first-child{border-top:none}
button.job-row:active{background:var(--soft)}
.job-row .nm{white-space:normal;line-height:1.3}
.job-row .ed{font-size:var(--fs-2);font-weight:700;color:var(--faint)}
.wait{display:flex;flex-direction:column;gap:12px;align-items:center;text-align:center}
.wait .dot{width:12px;height:12px;border-radius:50%;background:var(--warn);animation:pulse 1.2s ease-in-out infinite}
@keyframes pulse{50%{opacity:.3;transform:scale(.7)}}
