/* ==========================================================================
   Design direction: dark-first, one disciplined accent, bento-grid Dashboard.
   Rebuilt from a generic light-first admin-panel template after direct
   feedback that the previous pass (functional Phase 1/2 work) didn't change
   the actual visual language. Grounded in how Linear/Vercel/Supabase design
   the tools people use all day: dark is the primary surface (not an inverted
   afterthought), hierarchy comes from a stepped lightness ladder + low-
   opacity borders rather than flat panels, and ONE accent hue carries all
   interactive/brand meaning -- the categorical chart palette (--cat-1..6)
   stays strictly reserved for data, never for general UI chrome, so color
   keeps meaning something.
   ========================================================================== */
:root{
  /* Dark is the base identity now, not a media-query override. */
  --bg:#0A0A0F; --surface:#13131A; --surface-2:#1B1B24; --border:rgba(255,255,255,.08);
  --ink:#F2F2F5; --ink-2:#A8A8B5; --ink-3:#7C7C8C;
  --accent:#8D89F7; --accent-hover:#A6A3FA; --accent-ink:#13102B; --accent-wash:#211F3B;
  /* Dark surfaces barely show a drop shadow -- elevation instead comes from a
     faint inset top highlight (light catching the card's edge) plus a soft
     dark falloff, the standard dark-UI substitute for a visible shadow. */
  --shadow-1: 0 1px 0 rgba(255,255,255,.05) inset, 0 10px 30px rgba(0,0,0,.45);
  --cat-1:#3987e5; --cat-2:#d95926; --cat-3:#199e70; --cat-4:#c98500; --cat-5:#d55181; --cat-6:#179236;
  --status-good:#0ca30c; --status-warn:#d99a2b; --status-critical:#d03b3b;
  --font-ui:'Inter',-apple-system,BlinkMacSystemFont,'Segoe UI',Arial,sans-serif;
  --font-mono:'IBM Plex Mono',ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
}
/* Light is the secondary variant: only a system preference or the Phase-1
   toggle's explicit [data-theme="light"] switches to it. */
@media (prefers-color-scheme: light){
  :root{
    --bg:#F3F5F7; --surface:#FFFFFF; --surface-2:#F8F9FB; --border:#E1E6EC;
    --ink:#16202B; --ink-2:#55606B; --ink-3:#8993A0;
    --accent:#5750D6; --accent-hover:#4740B8; --accent-ink:#FFFFFF; --accent-wash:#EEEDFC;
    --shadow-1: 0 1px 2px rgba(16,32,45,.07), 0 1px 1px rgba(16,32,45,.05);
    --cat-1:#2a78d6; --cat-2:#eb6834; --cat-3:#1baf7a; --cat-4:#eda100; --cat-5:#e87ba4; --cat-6:#008300;
    --status-warn:#c98500;
  }
}
/* Manual theme override (Phase 1 item 6) -- takes precedence over the OS
   preference above regardless of source order, since an attribute selector
   on :root is more specific than a bare :root inside a media query. No
   data-theme attribute set = follow the OS preference (dark unless the OS
   says otherwise), same "system" semantics as before this toggle existed. */
:root[data-theme="dark"]{
  --bg:#0A0A0F; --surface:#13131A; --surface-2:#1B1B24; --border:rgba(255,255,255,.08);
  --ink:#F2F2F5; --ink-2:#A8A8B5; --ink-3:#7C7C8C;
  --accent:#8D89F7; --accent-hover:#A6A3FA; --accent-ink:#13102B; --accent-wash:#211F3B;
  --shadow-1: 0 1px 0 rgba(255,255,255,.05) inset, 0 10px 30px rgba(0,0,0,.45);
  --cat-1:#3987e5; --cat-2:#d95926; --cat-3:#199e70; --cat-4:#c98500; --cat-5:#d55181; --cat-6:#179236;
  --status-warn:#d99a2b;
}
:root[data-theme="light"]{
  --bg:#F3F5F7; --surface:#FFFFFF; --surface-2:#F8F9FB; --border:#E1E6EC;
  --ink:#16202B; --ink-2:#55606B; --ink-3:#8993A0;
  --accent:#5750D6; --accent-hover:#4740B8; --accent-ink:#FFFFFF; --accent-wash:#EEEDFC;
  --shadow-1: 0 1px 2px rgba(16,32,45,.07), 0 1px 1px rgba(16,32,45,.05);
  --cat-1:#2a78d6; --cat-2:#eb6834; --cat-3:#1baf7a; --cat-4:#eda100; --cat-5:#e87ba4; --cat-6:#008300;
  --status-warn:#c98500;
}
*{box-sizing:border-box;}
html,body{height:100%;}
body{background:var(--bg); color:var(--ink); font-family:var(--font-ui); font-weight:500; margin:0;}
h1,h2,h3,h4{font-family:var(--font-ui); margin:0; letter-spacing:-.01em;}
table{border-collapse:collapse;}
a{color:var(--accent);}
.num{font-family:var(--font-mono); font-variant-numeric:tabular-nums;}
[hidden]{display:none !important;}

/* ---------- Login ---------- */
.loginScreen{min-height:100vh; display:flex; align-items:center; justify-content:center; padding:24px;}
.loginCard{background:var(--surface); border:1px solid var(--border); border-radius:14px; box-shadow:var(--shadow-1); padding:36px; width:100%; max-width:360px;}
/* The mark is the icon itself, in the one accent color -- no colored chip,
   no gradient. A single bold shape reads clearly at any size, including a
   16x16 favicon, which a filled chip-plus-glyph composition does not. */
.loginCard .brand-mark{width:34px; height:34px; color:var(--accent); display:flex; align-items:center; justify-content:center; margin-bottom:16px;}
.loginCard .brand-mark svg{width:100%; height:100%;}
.loginCard h1{font-size:20px; font-weight:700; letter-spacing:-.015em; margin-bottom:4px;}
.loginCard p.sub{color:var(--ink-3); font-size:13px; margin:0 0 22px;}
.loginCard label{display:block; font-size:12px; font-weight:600; color:var(--ink-2); margin-bottom:6px; margin-top:14px;}
.loginCard input{width:100%; font-family:var(--font-ui); font-size:14px; padding:10px 12px; border:1px solid var(--border); border-radius:8px; background:var(--surface); color:var(--ink);}
.loginCard input:focus{outline:none; border-color:var(--accent); box-shadow:0 0 0 3px var(--accent-wash);}
.loginCard button{width:100%; margin-top:20px;}
.loginError{background:color-mix(in srgb, var(--status-critical) 14%, transparent); color:var(--status-critical); border:1px solid color-mix(in srgb, var(--status-critical) 45%, transparent); border-radius:8px; padding:9px 12px; font-size:13px; margin-top:14px;}

/* ---------- App shell ---------- */
.shell{display:flex; min-height:100vh; align-items:stretch;}
.sidebar{width:238px; flex:none; background:var(--surface); border-right:1px solid var(--border); position:sticky; top:0; height:100vh; display:flex; flex-direction:column; padding:20px 14px;}
.brand{display:flex; align-items:center; gap:10px; padding:4px 8px 18px; border-bottom:1px solid var(--border); margin-bottom:14px;}
.brand-mark{width:26px; height:26px; color:var(--accent); display:flex; align-items:center; justify-content:center; flex:none;}
.brand-mark svg{width:100%; height:100%;}
.brand-text{line-height:1.2;}
.brand-text b{display:block; font-size:14.5px; font-weight:700; letter-spacing:-.01em;}
.brand-text span{display:block; font-size:11.5px; color:var(--ink-3); text-transform:uppercase; letter-spacing:.06em;}
.nav{display:flex; flex-direction:column; gap:2px;}
.nav-item{display:flex; align-items:center; gap:10px; padding:9px 10px; border-radius:7px; cursor:pointer; font-size:14px; font-weight:500; color:var(--ink-2); border:none; background:none; text-align:left; width:100%; font-family:var(--font-ui);}
.nav-item:hover{background:var(--surface-2); color:var(--ink);}
.nav-item.active{background:var(--accent-wash); color:var(--accent);}
.nav-item .ic{width:18px; height:18px; flex:none;}
.sidebar-foot{margin-top:auto; padding:12px 10px 2px; border-top:1px solid var(--border); font-size:11.5px; color:var(--ink-3); line-height:1.5;}
.main-col{flex:1; min-width:0; display:flex; flex-direction:column;}
.topbar{position:sticky; top:0; z-index:5; display:flex; align-items:center; justify-content:space-between; gap:16px; padding:14px 28px; background:var(--bg); border-bottom:1px solid var(--border);}
.topbar h1{font-size:19px; font-weight:700; letter-spacing:-.01em;}
.topbar-right{display:flex; align-items:center; gap:10px;}
.view{padding:24px 28px 48px; max-width:1280px;}

select, input[type=text], input[type=number], input[type=date], input[type=email], input[type=password]{
  font-family:var(--font-ui); font-size:13.5px; color:var(--ink); background:var(--surface);
  border:1px solid var(--border); border-radius:7px; padding:8px 10px; outline:none;
}
select:focus, input:focus{border-color:var(--accent); box-shadow:0 0 0 3px var(--accent-wash);}
input.numinput{font-family:var(--font-mono);}
label.field{display:flex; flex-direction:column; gap:5px; font-size:12px; color:var(--ink-2); font-weight:500;}
label.field>span{text-transform:uppercase; letter-spacing:.04em; font-size:10.5px; color:var(--ink-3);}

button{font-family:var(--font-ui); cursor:pointer;}
.btn{display:inline-flex; align-items:center; gap:7px; border-radius:7px; padding:8px 14px; font-size:13.5px; font-weight:600; border:1px solid var(--border); background:var(--surface); color:var(--ink);}
.btn:hover{background:var(--surface-2);}
.btn.primary{background:var(--accent); border-color:var(--accent); color:var(--accent-ink);}
.btn.primary:hover{background:var(--accent-hover); border-color:var(--accent-hover);}
.btn.ghost{border-color:transparent; background:transparent;}
.btn.danger{color:var(--status-critical);}
.btn.danger:hover{background:color-mix(in srgb, var(--status-critical) 14%, transparent); border-color:var(--status-critical);}
.btn.sm{padding:5px 10px; font-size:12.5px;}
.btn:disabled{opacity:.5; cursor:not-allowed;}

.row{display:flex; align-items:flex-end; gap:12px; flex-wrap:wrap;}
.row.top{align-items:center;}

.card{background:var(--surface); border:1px solid var(--border); border-radius:12px; padding:20px; margin-bottom:20px; box-shadow:var(--shadow-1);}
.card h3{font-size:15px; font-weight:700; margin-bottom:2px;}
.card .hint{font-size:12.5px; color:var(--ink-3); margin-bottom:14px;}

.stat-row{display:grid; grid-template-columns:repeat(auto-fit,minmax(160px,1fr)); gap:14px; margin-bottom:20px;}
.stat-tile{background:var(--surface); border:1px solid var(--border); border-radius:12px; padding:16px 18px; box-shadow:var(--shadow-1);}
.stat-label{font-size:11px; color:var(--ink-3); text-transform:uppercase; letter-spacing:.05em; margin-bottom:6px;}
.stat-value{font-family:var(--font-mono); font-size:23px; font-weight:600; letter-spacing:-.01em; line-height:1.15;}
.stat-sub{font-size:12px; color:var(--ink-2); margin-top:3px;}

.dot{display:inline-block; width:9px; height:9px; border-radius:50%; margin-right:7px; flex:none;}
.mode-badge{font-size:11px; font-weight:700; text-transform:uppercase; letter-spacing:.04em; padding:3px 9px; border-radius:10px;}
.mode-badge.admin{background:var(--accent-wash); color:var(--accent);}
.mode-badge.member{background:var(--surface-2); color:var(--ink-2); border:1px solid var(--border);}

table.data{width:100%; font-size:13.5px;}
table.data th{text-align:left; font-size:11px; text-transform:uppercase; letter-spacing:.04em; color:var(--ink-3); padding:0 10px 8px; font-weight:600; border-bottom:1px solid var(--border);}
table.data td{padding:9px 10px; border-bottom:1px solid var(--border); vertical-align:middle;}
table.data tr:last-child td{border-bottom:none;}
table.data td.num, table.data th.num{text-align:right; font-family:var(--font-mono);}
.table-wrap{overflow-x:auto;}
.empty-row td{color:var(--ink-3); padding:16px 10px; text-align:center;}

.inline-input{border:1px solid transparent; background:transparent; border-radius:6px; padding:5px 7px; width:100%; font-size:13.5px; color:var(--ink); font-family:var(--font-ui);}
.inline-input:hover{border-color:var(--border);}
.inline-input:focus{border-color:var(--accent); background:var(--surface);}
.inline-input.numinput{font-family:var(--font-mono); text-align:right; width:78px;}

.timer-display{font-family:var(--font-mono); font-size:30px; font-weight:600; letter-spacing:-.01em; min-width:118px;}
.timer-live-dot{width:8px; height:8px; border-radius:50%; background:var(--status-good); display:inline-block; margin-right:8px; animation:pulse 1.6s infinite;}
@keyframes pulse{0%,100%{opacity:1;}50%{opacity:.35;}}
@media (prefers-reduced-motion: reduce){ .timer-live-dot{animation:none;} }

table.week th, table.week td{border:1px solid var(--border); padding:7px 9px; text-align:center; font-size:13px;}
table.week th{background:var(--surface-2); font-weight:600; color:var(--ink-2); font-size:11.5px; text-transform:uppercase;}
table.week td.proj{text-align:left; min-width:190px; font-weight:500;}
table.week td.total, table.week th.total{background:var(--surface-2); font-weight:700; font-family:var(--font-mono);}
table.week input.cell{width:56px; text-align:center; border:1px solid var(--border); border-radius:5px; padding:5px; font-family:var(--font-mono); background:var(--surface); color:var(--ink);}
table.week input.cell:disabled{background:var(--surface-2); color:var(--ink-3);}
table.week .empty-row td{border:none;}

.bar-row{margin-bottom:13px;}
.bar-row:last-child{margin-bottom:0;}
.bar-label{display:flex; justify-content:space-between; align-items:flex-start; font-size:13px; margin-bottom:5px;}
.bar-label>span:first-child{display:flex; align-items:flex-start;}
.bar-track{position:relative; height:10px; border-radius:5px; background:var(--surface-2); overflow:hidden;}
.bar-fill{height:100%; border-radius:5px; transition:width .2s;}
.bar-marker{position:absolute; top:0; bottom:0; width:2px; background:var(--status-critical); opacity:.85;}

/* Project name with its client stacked below, in both the dashboard bars
   and the Reports "by project" table -- same markup works in a flex row
   (dashboard) or a table cell (reports) since it's an inline-flex column. */
.bar-label-text{display:inline-flex; flex-direction:column; vertical-align:top; line-height:1.35;}
.bar-label-proj{color:var(--ink);}
.bar-label-client{font-size:11px; color:var(--ink-3); margin-top:1px;}

.banner{display:flex; align-items:flex-start; gap:10px; background:var(--accent-wash); border:1px solid var(--accent); color:var(--ink); border-radius:10px; padding:12px 16px; font-size:13px; margin-bottom:20px; line-height:1.5;}
.banner b{color:var(--accent);}

/* Each toast used to be position:fixed on itself, at the same bottom-right
   spot -- two at once would sit exactly on top of each other. The host is
   the fixed/positioned column now; toasts are flex children that slide in. */
#toastHost{position:fixed; bottom:20px; right:20px; z-index:200; display:flex; flex-direction:column; gap:10px; align-items:flex-end; pointer-events:none;}
.toast{position:relative; display:flex; align-items:center; gap:9px; background:var(--surface-2); border:1px solid var(--border); color:var(--ink); padding:11px 16px 13px; border-radius:9px; font-size:13px; box-shadow:var(--shadow-1); max-width:340px; pointer-events:auto; cursor:pointer; overflow:hidden; transform:translateX(16px); opacity:0; transition:transform .22s ease, opacity .22s ease;}
.toast.show{transform:translateX(0); opacity:1;}
.toast.hide{opacity:0; transform:translateX(10px);}
.toast-icon{flex:none; display:flex;}
.toast-msg{flex:1; line-height:1.4;}
.toast-bar{position:absolute; left:0; bottom:0; height:3px; background:var(--accent); opacity:.5; width:100%; animation:toastShrink linear forwards;}
.toast.toast-error{border-color:var(--status-critical);}
.toast.toast-error .toast-bar{background:var(--status-critical);}
.toast.toast-warning{border-color:var(--status-warn);}
.toast.toast-warning .toast-bar{background:var(--status-warn);}
@keyframes toastShrink{from{width:100%;} to{width:0%;}}
@media (prefers-reduced-motion: reduce){
  .toast{transition:none; transform:none; opacity:1;}
  .toast-bar{animation:none; display:none;}
}

.loadingOverlay{position:fixed; inset:0; background:var(--bg); display:flex; align-items:center; justify-content:center; font-size:14px; color:var(--ink-2); z-index:100;}

.modalOverlay{position:fixed; inset:0; background:rgba(0,0,0,.6); display:flex; align-items:center; justify-content:center; z-index:80; padding:20px;}
.modalCard{background:var(--surface); border:1px solid var(--border); border-radius:14px; box-shadow:var(--shadow-1); padding:28px; width:100%; max-width:360px;}
.modalCard label.field{margin-bottom:0;}

/* ---------- Phase 1: avatars, health badges, empty states, shortcuts, theme ---------- */
.avatar{display:inline-flex; align-items:center; justify-content:center; width:21px; height:21px; border-radius:50%; color:#fff; font-size:9.5px; font-weight:700; margin-right:7px; flex:none; vertical-align:middle; letter-spacing:.01em;}

.health-dot{display:inline-block; width:7px; height:7px; border-radius:50%; margin-left:6px; vertical-align:middle; flex:none;}
.health-dot.health-green{background:var(--status-good);}
.health-dot.health-amber{background:var(--status-warn);}
.health-dot.health-red{background:var(--status-critical);}

.empty-state{display:flex; flex-direction:column; align-items:center; justify-content:center; gap:8px; padding:22px 10px; color:var(--ink-3); text-align:center;}
.empty-state .ic{width:26px; height:26px; opacity:.55;}
.empty-state-msg{font-size:13px; color:var(--ink-2); font-weight:500;}
.empty-state-hint{font-size:12px; color:var(--ink-3); max-width:320px;}
.empty-row .empty-state{padding:10px 10px;}

.shortcut-row{display:flex; align-items:center; gap:12px; padding:6px 0; font-size:13.5px; color:var(--ink);}
.shortcut-row kbd{background:var(--surface-2); border:1px solid var(--border); border-radius:6px; padding:2px 8px; font-family:var(--font-mono); font-size:12px; min-width:22px; text-align:center; flex:none;}

.theme-toggle{width:100%; justify-content:flex-start; gap:8px; margin-top:2px;}
.theme-toggle .ic{width:14px; height:14px;}

/* ---------- Phase 2: charts ----------
   Three colors (#1baf7a / #eda100 / #e87ba4, the light-mode cat-3/4/5) sit
   below the 3:1 contrast floor against a white chart surface -- PASS overall
   per the dataviz skill's validator, but only WARN-with-relief, meaning they
   need a visible label or the table view alongside, never color alone. Every
   chart below already has one or the other: axis/tick text in an ink token
   (never the series color itself, per marks-and-anatomy.md) plus the
   existing data table it sits next to. The dark-mode cat palette was
   re-validated against this redesign's new, darker bg (#0A0A0F) and card
   surface (#13131A): every color's contrast only IMPROVED versus the old,
   lighter dark background (now 4.6-6.4:1 against the card surface, up from
   4.5-5.9:1 against the old bg) -- a darker base helps lighter chart colors
   stand out more, not less. */

.chart-card canvas{max-width:100%;}
.chart-card .hint{margin-bottom:10px;}

.chart-row{display:grid; grid-template-columns:repeat(auto-fit,minmax(280px,1fr)); gap:18px; align-items:start;}

/* Dashboard bento grid (redesign item 4): the "by project" chart is the
   single most useful glanceable metric for an admin reviewing the team's
   time, so it gets the large hero cell; the donut and trend sit stacked
   beside it at half its height each, and the heatmap runs full width below
   -- explicit column/row spans driven by actual priority, not a uniform
   row of same-size cards. Collapses to one column on narrow viewports. */
.bento-grid{display:grid; grid-template-columns:repeat(12,1fr); grid-auto-rows:minmax(190px,auto); gap:16px;}
.bento-hero{grid-column:1 / 8; grid-row:1 / 3;}
.bento-donut{grid-column:8 / 13; grid-row:1;}
.bento-trend{grid-column:8 / 13; grid-row:2;}
.bento-wide{grid-column:1 / 13;}
@media (max-width: 860px){
  .bento-grid{grid-template-columns:1fr;}
  .bento-hero, .bento-donut, .bento-trend, .bento-wide{grid-column:1; grid-row:auto;}
}

/* Donut-with-center-label: a plain CSS overlay on the canvas rather than a
   Chart.js plugin, so the "no bundler, lean deps" rule stays true. */
.donut-wrap{position:relative; max-width:220px; margin:0 auto;}
.donut-center{position:absolute; inset:0; display:flex; flex-direction:column; align-items:center; justify-content:center; pointer-events:none; text-align:center;}
.donut-center .donut-value{font-family:var(--font-mono); font-size:19px; font-weight:700; color:var(--ink);}
.donut-center .donut-label{font-size:10.5px; color:var(--ink-3); text-transform:uppercase; letter-spacing:.04em; margin-top:2px;}

/* A single series needs no legend box (marks-and-anatomy.md) -- billable vs
   non-billable is exactly two, so it gets one: a swatch + text-token label
   per entry, never the series color used as the text color itself. */
.chart-legend{display:flex; gap:16px; justify-content:center; margin-top:10px; flex-wrap:wrap; font-size:12.5px; color:var(--ink-2);}
.chart-legend .swatch{display:inline-block; width:9px; height:9px; border-radius:2px; margin-right:6px; vertical-align:middle;}

/* "Week at a glance" heatmap -- a sequential, single-hue (accent) ramp by
   design: level 0 is a neutral empty cell, levels 1-4 step the SAME hue from
   light to dark, never a second hue. Each cell's native `title` is the hover
   layer (date + hours) for this simple grid form. */
.heatmap-wrap{display:flex; gap:3px; overflow-x:auto; padding-bottom:4px;}
.heatmap-week{display:flex; flex-direction:column; gap:3px;}
.heatmap-cell{width:13px; height:13px; border-radius:3px; background:var(--surface-2); flex:none;}
.heatmap-legend{display:flex; align-items:center; gap:5px; margin-top:10px; font-size:11px; color:var(--ink-3);}
.heatmap-legend .heatmap-cell{width:11px; height:11px;}

/* Hidden on screen; shown only when printing the Reports view (Phase 2 item
   13, PDF export via the browser's own print-to-PDF rather than a new
   dependency). Printed output stays light regardless of the on-screen theme
   -- that's the conventional, expected look for a printed/PDF report. */
#printHeader{display:none;}

@media print{
  .sidebar, .topbar-right, #toastHost, #shortcutsOverlay, .row.top select,
  .row.top input, #reportFilterCard .row.top > label, .data td button,
  .data th:last-child, .data td:last-child, .inline-input{ display:none !important; }
  body, .view{padding:0; max-width:none; background:#fff; color:#111;}
  .shell{display:block;}
  .main-col{display:block;}
  .topbar{position:static; background:none; border-bottom:none;}
  .card{box-shadow:none; border:1px solid #ccc; break-inside:avoid; background:#fff; color:#111;}
  #printHeader{display:block; margin-bottom:18px;}
  #printHeader .print-title{font-size:20px; font-weight:700;}
  #printHeader .print-meta{font-size:12px; color:#555; margin-top:4px;}
}
