/* =====================================================================
   Vardiya Planlayıcı — dense, spreadsheet-grade weekly shift planner
   ===================================================================== */
:root{
  /* shift colours — fixed by spec, do not soften.
     These are the four cell fills and they are identical on screen, in the
     .xlsx, in the PNG snapshot and in print. The dark theme below restyles the
     *chrome* around them only. */
  --green-bg:#7dc67d; --green-fg:#1b3d1b;
  --orange-bg:#f5a623; --orange-fg:#4a2f00;
  --red-bg:#e05c4a;    --red-fg:#ffffff;
  --grey-bg:#bfbfbf;   --grey-fg:#4a4a4a;

  /* leave colours — same parity rule as the four above: identical in both
     themes, in print and in every export. Deliberately paler and less
     saturated, so an absence never reads as a worked shift. */
  --sick-bg:#eeaaa2;   --sick-fg:#6d2019;
  --unpaid-bg:#e8b6dd; --unpaid-fg:#5f1f4d;
  --annual-bg:#a9cdee; --annual-fg:#17395c;

  /* chrome — dark theme. @media print resets all of these back to light. */
  --ink:#eaeef7;           /* primary text */
  --ink-2:#a3aec4;         /* secondary */
  --ink-3:#6d7891;         /* tertiary / labels */
  --paper:#151924;         /* card + cell surface */
  --canvas:#0c0f16;        /* app background */
  --raised:#1d2331;        /* buttons, inputs, chips */
  --raised-2:#262d3e;      /* their hover */
  --hair:#222839;          /* inner grid hairline */
  --edge:#39415a;          /* structural separator */
  --head:#1a1f2c;
  --head-we:#20273a;
  --name-tint:#2b2038;     /* name column wash */
  --f-no-bg:#12161f;
  --f-hover:#1e2432;
  --foot:#191d29;
  --foot-strong:#2a2517;
  /* These two were per-theme literals until the PNG snapshot needed them: the
     canvas reads the token set off :root, so anything it paints has to BE a
     token or it silently falls back to the other theme's colour. */
  --cell-we:#191e2c;       /* empty cell on a weekend */
  --total-bg:#1b2130;      /* weekly-total column */
  --total-over-ink:#ff9a8d;/* weekly total past the contract limit */
  --grand-ink:#ffd88a;     /* the footer grand total */
  --pill-bg:var(--raised); --pill-bd:var(--hair); --pill-ink:var(--ink-2);
  --pill-pt-bg:#3a2a12; --pill-pt-bd:#5c4520; --pill-pt-ink:#f0b970;
  --fill-hi:rgba(255,255,255,.28); /* top highlight on a shift fill */
  /* The ⚠ sitting ON a shift fill. Keyed off the fill, which is the same hex in
     both themes, so these two are deliberately NOT overridden below. */
  --warn-fill-dark:#ffe9a8;   /* on the red fill  */
  --warn-fill-light:#6b5000;  /* on grey / leave  */
  --accent:#6b8cff;
  --accent-soft:#1e2848;
  --accent-ink:#c3d2ff;
  /* The selected subbox fill: a translucent accent wash over the cell, with a
     same-hue soft ring, plus the ink to read ON that wash. The wash REPLACES
     the cell's background, so the cell's own status ink no longer sits on its
     status fill - it sits on the wash, and dark green on a dark wash is 1.15.
     The focus surface therefore carries its own ink, and it must contrast the
     wash in both themes (the light wash is near-white, the dark wash near-
     black), never the spec fill. Tokens, so the guard test can compute the
     pair; the PNG snapshot reads them, and the canvas never paints focus. */
  --focus-fill:rgba(107,140,255,.16);
  --focus-glow:rgba(107,140,255,.28);
  --focus-ink:#eaeef7;
  --on-accent:#0d1220;   /* text on an accent-filled button */
  --danger:#ff6f5e;
  --danger-soft:#3a1d1c;
  --danger-edge:#6e3a35;
  --warn-ink:#ffc978;
  --ok:#6bd6a0;            /* save-status chip, "saved" */
  /* The hovered state of a toolbar control. These were per-rule literals until
     the branch picker became the third control needing them; a literal is wrong
     in one of the four contexts by the project's own rule, and this pair was
     already wrong in light theme for every rule that copied it. */
  --ctl-hover-bd:#4a5573;
  --ctl-hover-ink:#fff;
  /* Surfaces the PNG snapshot never paints, so they need no print entry (the
     same reason --ok carries none): .pop/.menu/.toast are display:none on
     paper. The toast stays dark in BOTH themes on purpose, like before. */
  --pop-bg:#1a1f2c;
  --toast-bg:#1b1e24; --toast-ink:#fff;
  --toast-btn:rgba(255,255,255,.15); --toast-btn-hi:rgba(255,255,255,.26);
  --shadow-1:0 1px 2px rgba(0,0,0,.4);
  --shadow-2:0 18px 44px -16px rgba(0,0,0,.75);

  /* One structural colour separates all seven days — the rule down each day's
     left edge and the bar under its header. This was seven distinct hues; the
     user asked for a professional table rather than a rainbow, so the whole set
     collapsed to a single neutral. Print has always done exactly this. */
  --day-line:#39415a;

  --w-no:34px; --w-name:130px; --w-durum:96px; --w-dep:88px;
  --w-in:47px; --w-out:47px; --w-pntj:47px; --w-total:64px;
  --off-name:34px; --off-durum:164px; --off-dep:260px; --frozen:348px;
  --row-h:28px; --hh1:48px; --hh2:26px; --foot-h:40px;

  --mono:ui-monospace,SFMono-Regular,"SF Mono",Menlo,Consolas,"Liberation Mono",monospace;
  --sans:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue","Noto Sans",Arial,sans-serif;
}
/* ---- light theme -----------------------------------------------------
   The toolbar ☾/☀ button stamps data-theme on <html>; state.ui.theme persists
   it. Only chrome tokens change — the four shift fills are shared, so a shift
   is the same colour in either theme and in every export.
   @media print re-applies this same palette regardless of the active theme. */
:root[data-theme="light"]{
  --ink:#14161a; --ink-2:#4a5058; --ink-3:#5c6470;
  --paper:#ffffff; --canvas:#eef0f4; --raised:#f5f7fa; --raised-2:#e8ecf2;
  --hair:#e4e7ec; --edge:#cfd4dc;
  --head:#f8f9fb; --head-we:#eef2f8;
  --name-tint:#f4dcf2; --f-no-bg:#fcfcfd; --f-hover:#f7f9fc;
  --foot:#fdf6e3; --foot-strong:#f8e6b0;
  --cell-we:#fafbfd; --total-bg:#f4f6f9;
  --total-over-ink:#9c2318; --grand-ink:#4a2f00;
  --pill-pt-bg:#fdf0e2; --pill-pt-bd:#f0d5b4; --pill-pt-ink:#8a5218;
  --fill-hi:transparent;
  --accent:#3457d5; --accent-soft:#e8ecfb; --accent-ink:#22337e; --on-accent:#fff;
  /* Light value of the same wash: deepened for white paper. */
  --focus-fill:rgba(52,87,213,.12);
  --focus-glow:rgba(52,87,213,.26);
  --focus-ink:#14161a;
  --danger:#c0392b; --danger-soft:#fdeceb; --warn-ink:#8a4b00; --ok:#1d7a4d;
  --danger-edge:#e3aaa3;
  --shadow-1:0 1px 2px rgba(16,20,28,.05);
  --shadow-2:0 10px 30px -14px rgba(16,20,28,.28);
  --day-line:#cfd4dc;
  --ctl-hover-bd:#bfc6d1; --ctl-hover-ink:var(--ink);
  /* Same surface in light: --paper, since the canvas never paints popovers. */
  --pop-bg:var(--paper);
}
:root[data-theme="light"] .toolbar{background:linear-gradient(180deg,#fbfcfe 0%,var(--paper) 100%)}
:root[data-theme="light"] .brand .dot{box-shadow:0 0 8px 1px rgba(59,98,216,.4)}
:root[data-theme="light"] .btn:active{background:#e3e8f0}
:root[data-theme="light"] td.g,:root[data-theme="light"] td.o,
:root[data-theme="light"] td.r,:root[data-theme="light"] td.y,
:root[data-theme="light"] td.sk,:root[data-theme="light"] td.up,
:root[data-theme="light"] td.an{box-shadow:none}

/* the per-theme values for these now live in the token block above, so the PNG
   snapshot can read them off :root like everything else it paints */
:root[data-theme="light"] select.durum.pt:hover{background:#fae4cd}
:root[data-theme="light"] select.durum option,
:root[data-theme="light"] .menu select option{background:#fff;color:var(--ink)}
:root[data-theme="light"] .pop,:root[data-theme="light"] .menu{background:var(--pop-bg)}
:root[data-theme="light"] .fset{background:#fcfcfd}
:root[data-theme="light"] .grip{color:#b6bcc6}
:root[data-theme="light"] .row-acts button{color:#9aa1ac}
:root[data-theme="light"] .sw{border-color:rgba(0,0,0,.22)}
:root[data-theme="light"] .backdrop{background:rgba(18,21,26,.2)}
:root[data-theme="light"] input.nm::placeholder,
:root[data-theme="light"] input.dp::placeholder{color:#a9b0ba}
:root[data-theme="light"] .pop-row input[type=time],
:root[data-theme="light"] .frow input{color-scheme:light}
:root[data-theme="light"] input.ced.bad{color:#8c1d10}

*{box-sizing:border-box}
html,body{height:100%}
body{
  margin:0; background:var(--canvas); color:var(--ink);
  font:13px/1.35 var(--sans);
  display:flex; flex-direction:column; overflow:hidden;
  -webkit-text-size-adjust:100%;
  -webkit-font-smoothing:antialiased;
  /* Restrained theme cross-fade: tokens swap on <html>, this eases the canvas
     behind them. Killed under prefers-reduced-motion below. */
  transition:background-color .25s ease,color .25s ease;
}
::selection{background:var(--accent-soft)}
.num,.mono{font-family:var(--mono);font-variant-numeric:tabular-nums;font-feature-settings:"tnum" 1}
button,input,select{font:inherit;color:inherit}
:focus-visible{outline:2px solid var(--accent);outline-offset:1px}

/* ------------------------------------------------------------ toolbar */
.toolbar{
  flex:none; display:flex; align-items:center; gap:8px; flex-wrap:wrap;
  row-gap:8px;
  padding:9px 14px; color:var(--ink);
  background:linear-gradient(180deg,#1b2130 0%,var(--paper) 100%);
  border-bottom:1px solid var(--edge);
  box-shadow:0 1px 0 rgba(255,255,255,.03) inset, 0 6px 18px -10px rgba(0,0,0,.9);
  position:relative; z-index:20;
}
.brand{
  font-weight:680; font-size:12px; letter-spacing:.11em; color:var(--ink);
  white-space:nowrap; padding-right:2px;
}
.brand .dot{
  display:inline-block;width:7px;height:7px;border-radius:2px;margin-right:7px;vertical-align:1px;
  background:linear-gradient(135deg,var(--accent),var(--accent-ink));
  box-shadow:0 0 10px 1px rgba(107,140,255,.65);
}
.tb{display:flex;align-items:center;gap:5px;flex-wrap:wrap;min-width:0}
/* ONE ROW AT 1440. A branch manager's toolbar - week, the editing group, the
   file menu and the personal controls - needs about 1450px with the wordmark,
   so below 1600 the wordmark steps aside and the mark alone stays (its name is
   the brand's tooltip). The phone rule further down has its own layout. */
@media (max-width:1600px) and (min-width:641px){
  .brand-tx{display:none}
  .brand .dot{width:10px;height:10px;border-radius:3px;margin:0 4px 0 2px}
}
.sep{width:1px;height:24px;background:var(--hair)}
.spacer{flex:1}

.btn{
  height:32px; padding:0 11px; background:var(--raised); border:1px solid var(--edge);
  border-radius:8px; cursor:pointer; white-space:nowrap; display:inline-flex;
  align-items:center; justify-content:center; gap:6px; font-size:12.5px; font-weight:500;
  color:var(--ink); transition:background .12s ease,border-color .12s ease,color .12s ease;
}
/* display:inline-flex above outranks the hidden attribute's default
   display:none, so a `hidden` button would render anyway. #toast button
   already carried a narrower version of this fix; #authBtn ships hidden and
   is revealed by app.js, so it needs the general one. */
.btn[hidden]{display:none}
.btn:hover{background:var(--raised-2);border-color:var(--ctl-hover-bd);color:var(--ctl-hover-ink)}
.btn:active{background:#161b27}
.btn.icon{width:34px;padding:0;font-size:14.5px}
.btn.ghost{border-color:transparent;background:transparent;color:var(--ink-2)}
.btn.ghost:hover{background:var(--raised);border-color:transparent;color:var(--ink)}

/* segmented control */
.seg{display:inline-flex;border:1px solid var(--edge);border-radius:8px;overflow:hidden;background:var(--raised)}
.seg button{
  height:32px;padding:0 11px;border:0;background:transparent;cursor:pointer;font-size:12.5px;
  font-weight:500;color:var(--ink-2);border-right:1px solid var(--hair);
}
.seg button:last-child{border-right:0}
.seg button:hover{background:var(--raised-2);color:var(--ink)}
.seg button[aria-pressed="true"]{background:var(--accent-soft);color:var(--accent-ink);font-weight:640}
.seg.lang button{min-width:42px;letter-spacing:.04em;font-family:var(--mono);font-size:11.5px}

/* branch picker */
/* Styled off .btn, not off select.durum: the grid pill binds its height to
   --row-h and paints with the pill tokens because it lives in a cell. This is
   toolbar chrome, so it takes the toolbar's own 32px height, 8px radius and
   --raised/--edge pair and reads as native beside the buttons it sits next to.
   Tokens only. A literal would be wrong in at least one of dark, light and
   print, and invisible to shotPalette(), which reads the resolved set off :root.
   No @media print entry is needed and adding one would be a dead selector:
   .toolbar is already display:none there, which removes its whole subtree. That
   hide list names OVERLAYS - .pop, .menu, .panel, .authwrap, #toast - because
   those are children of <body>, not of the header. */
.branchpick{display:inline-flex;align-items:center;gap:5px}
/* display:inline-flex above outranks the hidden attribute's own display:none,
   exactly as .btn, .savestat, .panel, .pop and .authwrap all had to learn. The
   wrapper ships hidden and only syncBranchPicker() reveals it, so without this
   rule every single-branch manager gets a picker. */
.branchpick[hidden]{display:none}
/* Positioning context for the caret. It is the SELECT's own wrapper rather than
   .branchpick so the caret cannot land on #branchRetry when that is revealed. */
.branchsel-w{position:relative;display:inline-flex;min-width:0}
.branchsel{
  height:32px; max-width:190px; padding:0 26px 0 10px;
  background:var(--raised); border:1px solid var(--edge); border-radius:8px;
  color:var(--ink); font-size:12.5px; font-weight:500; cursor:pointer;
  white-space:nowrap; text-overflow:ellipsis; outline:0;
  -webkit-appearance:none; appearance:none;
  transition:background .12s ease,border-color .12s ease,color .12s ease;
}
.branchsel:hover{background:var(--raised-2);border-color:var(--ctl-hover-bd);color:var(--ctl-hover-ink)}
.branchsel:focus-visible{border-color:var(--accent)}
/* Dead for the round trip of a switch: a second pick while one is in flight is
   defect (a)'s trigger, and Store resolves only the newest. */
.branchsel:disabled{cursor:default;color:var(--ink-3);opacity:1}
/* appearance:none removes the native caret, so draw one. pointer-events:none
   keeps the click on the select underneath. */
.branchsel-w::after{
  content:"▾"; position:absolute; right:10px; top:50%; transform:translateY(-50%);
  font-size:10px; color:var(--ink-2); pointer-events:none;
}
/* The caret has to travel with the text it belongs to. Left on --ink-2 it stays
   dim while the branch name lifts to --ctl-hover-ink, which reads as a caret
   belonging to some other control. */
.branchsel-w:hover::after{color:var(--ctl-hover-ink)}
/* The dropdown list is painted by the OS, so it needs the tokens named on the
   options themselves. select.durum nearby hard-codes a dark literal here; that
   is an existing wart and is wrong in light theme - do not copy it. */
.branchsel option{background:var(--raised);color:var(--ink)}
/* The retry is revealed only after a switch has failed, so it is an error
   affordance rather than a spare button - it takes --danger for the same reason
   the save chip's error state does. An id outranks .btn.ghost:hover, so the
   hover state keeps the colour without a second rule. */
#branchRetry{color:var(--danger)}

.wk{display:flex;flex-direction:column;justify-content:center;min-width:184px;padding:0 2px}
.wk b{font-size:12.5px;font-weight:640;letter-spacing:.01em;font-variant-numeric:tabular-nums}
.wk span{font-size:10.5px;color:var(--ink-3);letter-spacing:.04em;text-transform:uppercase}

/* --------------------------------------------------------------- grid */
.stage{flex:1;min-height:0;padding:12px 14px 14px;display:flex}
.card{
  flex:1; min-width:0; background:var(--paper); border:1px solid var(--edge);
  border-radius:12px; overflow:auto; position:relative;
  box-shadow:var(--shadow-1),var(--shadow-2);
}
/* --table-w is the exact sum of the column widths (applyMetrics writes it).
   Without it the table is width:auto, so `table-layout:fixed` shrink-to-fits it
   into the card and squeezes every column proportionally — which is why the
   numbers never got the room their configured widths asked for. Setting the
   width explicitly makes the card scroll horizontally instead. */
table{border-collapse:separate;border-spacing:0;table-layout:fixed;width:var(--table-w);min-width:100%}
  col.k-no{width:var(--w-no)} col.k-name{width:var(--w-name)} col.k-durum{width:var(--w-durum)}
  col.k-dep{width:var(--w-dep)} col.k-in{width:var(--w-in)} col.k-out{width:var(--w-out)}
  col.k-pntj{width:var(--w-pntj)} col.k-total{width:var(--w-total)}

/* ----------------------------------------------------------- overview */
/* A view, not an overlay: .stage and .ovw are siblings and body.ovw-on swaps
   them. .ovw sets a display, so it needs its own [hidden] rule - see
   .branchpick, .panel, .pop, .authwrap, .savestat, .btn, all of which had to
   learn this. Every colour here is a token: a literal is wrong in one of the
   four contexts and invisible to shotPalette().

   THE BODY CLASS IS `ovw-on`, NOT `ovw`, and that is not a typo to tidy up. A
   <body class="ovw"> would itself match `.ovw`, `.ovw h2` and the @media print
   hide list below - so the body would take the section's padding and gap, the
   settings panel's <h2> would take the section heading's style, and printing
   with the overview open would hide the whole page. The two names must differ. */
.ovw{flex:1;min-height:0;padding:12px 14px 14px;display:flex;flex-direction:column;gap:10px;overflow:auto}
.ovw[hidden]{display:none}
body.ovw-on .stage{display:none}
.ovw h2{margin:0;font-size:12px;font-weight:650;letter-spacing:.08em;text-transform:uppercase;color:var(--ink-2)}
/* THE BOARD. One card per branch in a grid that fills the width at a 318px
   minimum - four across at 1440, one column on a phone - so 8 or 15+ branches
   keep the same shape and simply scroll. Every fill is the grid's own token
   pair, so a count reads in the colour its shifts wear on the branch's grid. */
.ovw-hd{display:flex;align-items:center;gap:8px 16px;flex-wrap:wrap}
.ovw-ttl{display:flex;align-items:baseline;gap:6px 12px;flex-wrap:wrap;margin-right:auto;min-width:0}
.ovw-sub{font-size:12.5px;color:var(--ink-3)}
.ovw-sub .num{color:var(--ink-2)}
.ovw-warnc{color:var(--warn-ink)}
.ovw-leg{display:inline-flex;align-items:center;font-size:11.5px;color:var(--ink-2);white-space:nowrap}
.ovw-leg .lg{display:inline-block;width:10px;height:10px;border-radius:3px;margin:0 6px 0 14px}
.ovw-leg .lg:first-child{margin-left:0}
.ovw-leg .lg.g{background:var(--green-bg)}
.ovw-leg .lg.o{background:var(--orange-bg)}
.ovw-leg .lg.r{background:var(--red-bg)}
.ovw-list{list-style:none;margin:0;padding:0;display:grid;grid-template-columns:repeat(auto-fill,minmax(318px,1fr));gap:12px}
.ovw-card{
  display:flex;flex-direction:column;min-width:0;padding:6px 12px 11px;cursor:pointer;
  background:var(--paper);border:1px solid var(--edge);border-radius:12px;box-shadow:var(--shadow-1);
  transition:border-color .15s ease;
}
.ovw-card:hover{border-color:var(--ctl-hover-bd)}
.ovw-card.has-gap{border-color:var(--danger-edge)}
.ovw-card:has(.ovw-row[aria-current="true"]){border-color:var(--accent)}
.ovw-top{display:flex;align-items:center;gap:8px;height:36px;min-width:0}
/* The name is the card's keyboard handle - the whole card opens on a click, and
   this button is what Tab reaches. Transparent, so the card is the surface. */
.ovw-row{
  flex:1;min-width:0;display:flex;align-items:center;height:30px;margin:0 -6px;padding:0 6px;
  border:0;border-radius:8px;background:none;color:var(--ink);text-align:left;cursor:pointer;font:inherit;
}
.ovw-row:hover{background:var(--raised);color:var(--ink)}
.ovw-row[aria-current="true"]{color:var(--accent-ink)}
.ovw-nm{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:15px;font-weight:650;letter-spacing:.005em}
.ovw-go{flex:none;color:var(--ink-3);font-size:14px;transition:transform .15s ease,color .15s ease}
.ovw-card:hover .ovw-go{color:var(--accent-ink);transform:translateX(2px)}
.ovw-retry{flex:none;width:28px;height:28px;font-size:15px;color:var(--accent-ink)}
.ovw-figs{display:flex;align-items:baseline;flex-wrap:wrap;gap:0 5px;font-size:12px;color:var(--ink-3);margin:1px 0 9px}
.ovw-figs b{font-size:14px;font-weight:600;color:var(--ink)}
.ovw-dot{margin:0 3px}
.ovw-away{display:inline-flex;align-items:baseline;gap:5px;cursor:help}
.ovw-wk{border-collapse:separate;border-spacing:3px;table-layout:fixed;margin:0 -3px;width:calc(100% + 6px)}
.ovw-wk th,.ovw-wk td{position:static;background:none;border:0;box-shadow:none;padding:0;overflow:hidden}
.ovw-wk th{height:auto;font-size:10px;font-weight:600;letter-spacing:.06em;text-transform:uppercase;color:var(--ink-3);text-align:center;padding:0 0 2px}
.ovw-wk thead th:first-child,.ovw-wk tbody th{width:58px}
.ovw-wk tbody th{text-align:left;font-size:10.5px;letter-spacing:.02em;text-transform:none;color:var(--ink-2);font-weight:500;white-space:nowrap;text-overflow:ellipsis}
.ovw-wk thead th.tdy{color:var(--accent-ink)}
.ovw-wk thead th.tdy::after{content:"";display:block;height:2px;border-radius:1px;margin:2px 6px 0;background:var(--accent)}
.ovw-wk td{height:22px;border-radius:4px;text-align:center;font-family:var(--mono);font-size:11.5px;font-weight:650}
.ovw-wk td.g{background:var(--green-bg);color:var(--green-fg)}
.ovw-wk td.o{background:var(--orange-bg);color:var(--orange-fg)}
.ovw-wk td.r{background:var(--red-bg);color:var(--red-fg)}
.ovw-wk td.z{background:var(--raised);color:var(--ink-3);font-weight:400}
.ovw-wk td.gap{background:var(--danger-soft);color:var(--danger);box-shadow:inset 0 0 0 1px var(--danger)}
.ovw-iss{list-style:none;margin:8px 0 0;padding:0;display:flex;flex-wrap:wrap;gap:4px 12px;font-size:11.5px;min-height:17px}
.ovw-iss li{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}
.ovw-iss .ok{color:var(--ok)}
.ovw-iss .gap{color:var(--danger)}
.ovw-iss .wn{color:var(--warn-ink)}
.ovw-iss .more{color:var(--ink-3);cursor:help}
/* flex:0 1 auto and not flex:none: a long branch name keeps its room and the
   badge ellipsises rather than pushing the arrow out of the card. */
.ovw-flag{
  flex:0 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  font-size:10.5px;letter-spacing:.03em;padding:3px 9px;border-radius:999px;
  color:var(--danger);background:var(--danger-soft);border:1px solid var(--danger);
}
/* The same badge, as the control that repairs what it reports. It is a <button>
   only when this account may actually add a manager (Store.canAddBranch()), so
   the pill a branch manager sees stays inert text - a control that does nothing
   is a defect here. Everything but the affordance is inherited from .ovw-flag
   above, which is why this rule sets no colour of its own. */
button.ovw-flag{cursor:pointer; font:inherit; font-size:10.5px}
button.ovw-flag:hover{background:var(--danger); color:var(--on-accent)}
.ovw-dim .ovw-figs b{color:var(--ink-3)}
/* The editing group has no meaning while the grid is hidden: it would mutate and
   flush the branch nobody can see. Same shape as the body.ro pair above, and for
   the same reason - hiding the four buttons alone would strand their separator.
   Ctrl+Z bypasses CSS entirely, so undo() carries the same guard.
   The Workers door goes with them, NOT with body.ro: the panel acts on the
   SELECTED branch, and on the overview the selection is not what is on show. */
body.ovw-on #editSep,body.ovw-on #editTools,body.ovw-on #workerTools{display:none}

th,td{
  border-right:1px solid var(--hair); border-bottom:1px solid var(--hair);
  padding:0 3px; text-align:center; overflow:hidden; background:var(--paper);
  print-color-adjust:exact; -webkit-print-color-adjust:exact;
}
/* head */
thead th{
  position:sticky; z-index:4; background:var(--head);
  font-size:10px; font-weight:660; letter-spacing:.075em; color:var(--ink-2);
  text-transform:uppercase; border-bottom:1px solid var(--edge);
}
thead tr.h1 th{height:var(--hh1);top:0}
thead tr.h2 th{height:var(--hh2);top:var(--hh1);font-size:9.5px;letter-spacing:.09em;color:var(--ink-3)}
thead th.frz{top:0;z-index:6}
thead th.day.we,thead th.sub.we{background:var(--head-we)}
.d-name{font-size:11.5px;font-weight:660;letter-spacing:.055em;color:var(--ink)}
.d-date{font-size:10px;font-weight:500;letter-spacing:.02em;color:var(--ink-3);margin-top:2px;text-transform:none;font-family:var(--mono)}
thead th.k-totalh{font-size:9px;line-height:1.25;white-space:normal;padding:0 4px;letter-spacing:.055em}

/* ---- day separation --------------------------------------------------
   A 3px bar under each day's header and a 2px rule down its left edge, both in
   one neutral, so the seven day blocks read as structure rather than colour.
   There is no per-day keying left to get wrong — every day uses --day-line, so
   hiding a frozen column cannot shift anything (the old hue set was keyed off
   data-day, never nth-child, for exactly that reason).                       */
thead tr.h1 th.day{position:sticky;box-shadow:inset 0 -3px 0 var(--day-line)}

/* the 2px rule that opens each day group */
thead tr.h1 th.day,
thead tr.h2 th.sub:nth-child(3n+1),
tbody td.cell[data-part="in"],
tfoot td.dt{border-left:2px solid var(--day-line)}
/* fence the weekly-total column off from Sunday */
thead tr.h1 th.k-totalh,tbody td.total,tfoot td.grand{border-left:2px solid var(--edge)}
thead th{position:sticky}
/* .rz only needs to be a containing block for .rz-h; `sticky` already is one.
   Using `relative` here silently outranked `.frz{position:sticky}` (0,1,1 vs 0,1,0)
   and turned the frozen columns' `left` offsets into a visible displacement. */
th.rz{position:sticky}
/* Resize handles must sit ENTIRELY inside their cell: th/td are overflow:hidden,
   so any part poking outside (the old right:-3px / bottom:-3px) is clipped away
   and unhittable — which left a ~3px target and made resizing feel impossible. */
.rz-h{
  position:absolute;top:0;bottom:0;right:0;width:9px;cursor:col-resize;z-index:9;
  touch-action:none;
}
.rz-h::after{content:"";position:absolute;top:22%;bottom:22%;right:1px;width:2px;background:transparent;border-radius:1px}
.rz-h:hover::after,.rz-h.on::after{background:var(--accent)}
/* Day-scale handle: same 9px inside-edge target as .rz-h (default right:0
   already puts it on the day header's right edge). Taller bar so a day edge
   reads differently from a sub-column edge at a glance. */
.rz-day::after{top:12%;bottom:12%}
/* Week handle: the Sunday end of the grid, i.e. the weekly-total header's
   LEFT edge. An .rz-h, so the @media print hide list covers it by name. */
.rz-week{right:auto;left:0}

td{height:var(--row-h);font-size:13px}

/* frozen columns */
/* Every offset comes from applyMetrics(), which sums only the VISIBLE columns in
   the user's order — so whichever column is first gets --off-*:0 automatically.
   Never hard-code `left:0` onto a specific column again. */
.frz{position:sticky;z-index:3}
.f-no{left:var(--off-no)}
.f-name{left:var(--off-name)}
.f-durum{left:var(--off-durum)}
.f-dep{left:var(--off-dep)}
/* the structural rule between the frozen block and the days rides on whichever
   column is last, not on `dep` */
.frz-last,thead th.frz-last,tfoot td.frz-last{border-right:1px solid var(--edge)}

/* NB: no `position:relative` here — these cells carry .frz and must stay sticky.
   Sticky is itself a containing block for .row-acts / .rowh-h. */
tbody td.f-no{background:var(--f-no-bg)}
tbody td.f-name{background:var(--name-tint);text-align:left;padding:0}
tbody td.f-durum{background:var(--paper);padding:0}
tbody td.f-dep{background:var(--paper);text-align:left;padding:0}
tbody tr:hover td.f-no,tbody tr:hover td.f-durum,tbody tr:hover td.f-dep{background:var(--f-hover)}
tbody tr.sel td.f-no{box-shadow:inset 3px 0 0 var(--accent)}

.no-in{display:flex;align-items:center;justify-content:center;gap:1px;height:100%}
/* Every child of the frozen cells must fit inside --row-h at its 28px minimum,
   or the table row floors above the height the user set. This grip's fixed
   8px padding alone made 28px unreachable. */
.grip{
  cursor:grab;color:#4d5771;font-size:11px;line-height:1;touch-action:none;user-select:none;
  padding:3px 1px;border-radius:3px;
}
.grip:hover{color:var(--ink-2);background:var(--raised-2)}
/* used when the S.NO column is hidden and the drag grip has to ride along the
   left edge of whichever column is first, without disturbing its content */
.grip.float{position:absolute;left:0;top:50%;transform:translateY(-50%);z-index:2;opacity:.55}
.grip.float:hover{opacity:1}
.grip:active{cursor:grabbing}
.sno{font-family:var(--mono);font-size:11px;color:var(--ink-3);min-width:14px}
.rowh-h{position:absolute;left:0;right:0;bottom:0;height:8px;cursor:row-resize;z-index:8;touch-action:none}
.rowh-h:hover{background:linear-gradient(to bottom,transparent 30%,var(--accent) 30%,var(--accent) 70%,transparent 70%)}
tr.dragging{opacity:.5}
tr.dragging td{background:var(--accent-soft) !important}
tr.drop-mark td{box-shadow:inset 0 -2px 0 var(--accent)}

input.nm,input.dp{
  width:100%;height:calc(var(--row-h) - 2px);border:0;background:transparent;padding:0 7px;
  font-size:12.5px;outline:0;font-weight:600;letter-spacing:.005em;color:var(--ink);
  /* The compact name column is narrower than a 16-char name, so the overflow is
     marked with an ellipsis rather than a char cut mid-stroke. Focus reveals the
     whole value (the caret scrolls); an input shows the ellipsis only unfocused. */
  text-overflow:ellipsis;
}
input.nm{padding-right:16px}  /* clears the absolutely positioned row warning */
/* The row actions are hidden by default and carry their own fade-out backdrop,
   so the text no longer has to reserve 50px it almost never needs. */
input.dp{font-weight:450;padding-right:10px;color:var(--ink-2)}
input.nm::placeholder,input.dp::placeholder{color:#5b657e;font-weight:450}
input.nm:focus,input.dp:focus{background:var(--raised);box-shadow:inset 0 0 0 2px var(--accent)}

.durum-wrap{display:flex;align-items:center;justify-content:center;height:100%;padding:0 5px}
select.durum{
  width:100%;height:clamp(18px,calc(var(--row-h) - 8px),30px);
  border:1px solid var(--pill-bd);border-radius:7px;background:var(--pill-bg);
  padding:0 4px;font-size:10.5px;font-weight:640;letter-spacing:.055em;outline:0;cursor:pointer;
  -webkit-appearance:none;appearance:none;text-align:center;text-align-last:center;color:var(--pill-ink);
}
select.durum:hover{background:var(--raised-2);color:var(--ink)}
select.durum:focus{border-color:var(--accent);background:var(--raised-2)}
select.durum.pt{background:var(--pill-pt-bg);border-color:var(--pill-pt-bd);color:var(--pill-pt-ink)}
select.durum.pt:hover{background:#4a361a}
select.durum option{background:#1d2331;color:var(--ink)}

/* ALWAYS THERE. These used to wait for the pointer to rest on the row for three
   seconds — a delay nobody discovers, and one a touch screen cannot perform at
   all. They stay quiet grey until pointed at, so the affordance is the hover
   colour rather than the appearance. The gradient is kept so a long value under
   them never looks as if it ended mid-word, and .frz-last reserves the room
   below. `visibility` is still what makes them unclickable when read-only
   hides them — a dead target is worse than a missing one.

   THE FOOTPRINT IS PART OF THE COLUMN ARITHMETIC: two 18px buttons with no gap
   or padding is 36px, plus a 1px right inset, and the reservation below adds one
   more pixel of clearance (38). DEFAULT_COLS.dep is sized against that number —
   widening a button here silently eats a department name there. */
.row-acts{
  position:absolute;right:1px;top:50%;transform:translateY(-50%);display:flex;gap:0;
  visibility:visible;opacity:1;
  padding-left:0;border-radius:6px;
}
tbody tr:hover td.frz .row-acts,
tbody tr.sel td.frz .row-acts{
  background:var(--f-hover);
}
/* The row's last frozen cell hosts them, and its input is full-width: without
   the reservation the value runs underneath the buttons. 38 = the lane's 36px,
   the 1px inset and a 1px gap. */
tbody td.frz-last input{padding-right:38px}
.row-acts button{
  width:18px;height:24px;border:0;background:transparent;cursor:pointer;color:#5b657e;
  font-size:13px;line-height:1;padding:0;border-radius:5px;
}
.row-acts button:hover{background:var(--raised-2);color:var(--ink)}
.row-acts button.del:hover{background:var(--danger-soft);color:var(--danger)}

/* ---- the add row ----------------------------------------------------
   The table's last body row IS the add control: a manager adding somebody is
   looking at the list of people, and on a phone it is the only add control that
   survives the toolbar overflowing. It wears the table's own cells — one frozen,
   one spanning the days — so the button stays reachable while the week scrolls
   under it without becoming a floating element of its own. */
tbody tr.addrow td{padding:0;background:var(--paper);border-bottom:0}
tbody tr.addrow td.addcell{padding:0}
.addbtn{
  display:flex;align-items:center;gap:7px;width:100%;height:100%;min-height:28px;
  border:0;border-radius:0;background:transparent;color:var(--accent-ink);
  cursor:pointer;font:inherit;font-size:12.5px;font-weight:560;padding:0 8px;text-align:left;
}
.addbtn:hover{background:var(--accent-soft)}
.addbtn .plus{font-size:14px;line-height:1}
/* The row turns red while its remove question is open, so there is never any
   doubt WHICH row the card is about. */
tbody tr.removing td.frz{background:var(--danger-soft)}
tbody tr.removing td.frz input{color:var(--danger)}

/* ---- the remove card ------------------------------------------------- */
.confirmcard{
  position:fixed;z-index:60;width:300px;max-width:calc(100vw - 20px);
  padding:13px 14px 12px;background:var(--pop-bg);border:1px solid var(--edge);
  border-radius:12px;color:var(--ink);box-shadow:var(--shadow-1),var(--shadow-2);
}
.confirmcard[hidden]{display:none}
.cf-q{margin:0 0 6px;font-size:13px;font-weight:650;color:var(--ink)}
.cf-b{margin:0;font-size:12px;line-height:1.45;color:var(--ink-2)}
.cf-act{display:flex;justify-content:flex-end;gap:6px;margin-top:12px}
/* The destructive action is filled, and it is the SECOND button: the safe
   choice is where the pointer already is. */
.btn.danger{background:var(--danger);border-color:var(--danger);color:var(--on-accent);font-weight:600}
.btn.danger:hover{background:var(--danger);border-color:var(--danger);color:var(--on-accent);filter:brightness(1.08)}

/* day cells */
td.cell{
  position:relative;cursor:pointer;user-select:none;
  scroll-margin-left:var(--frozen);scroll-margin-top:76px;scroll-margin-bottom:48px;
}
/* The four spec fills, unchanged. On the dark canvas they now carry the whole
   colour story, so they get a soft top highlight to read as solid chips. */
td.g{background:var(--green-bg);color:var(--green-fg)}
td.o{background:var(--orange-bg);color:var(--orange-fg)}
td.r{background:var(--red-bg);color:var(--red-fg)}
td.y{background:var(--grey-bg);color:var(--grey-fg)}
td.sk{background:var(--sick-bg);color:var(--sick-fg)}
td.up{background:var(--unpaid-bg);color:var(--unpaid-fg)}
td.an{background:var(--annual-bg);color:var(--annual-fg)}
td.g,td.o,td.r,td.y,td.sk,td.up,td.an{box-shadow:inset 0 1px 0 var(--fill-hi)}
td.e{background:var(--paper)}
td.cell.we.e{background:var(--cell-we)}
td.time,td.pntj{font-family:var(--mono);font-variant-numeric:tabular-nums;font-size:13px;font-weight:560;letter-spacing:.005em}
td.pntj{font-weight:700}
td.word{font-weight:700;font-size:12px;letter-spacing:.13em}
td.cell:focus{outline:none}
/* The selected subbox fills ENTIRELY (tint + soft ring) instead of just an
   outline, in both themes via tokens. Wrapped in @media screen so paper is
   untouched: a background here would print over the shift fills (the print
   block's box-shadow:none could not undo a background). The fc-a/fc-z edge
   lines survive as the active day-group's end marks, now in the glow hue.
   THE INK MUST COME WITH THE FILL. `background` is the shorthand and it WIPES
   the status fill, so the cell's own status ink ends up on the wash instead:
   in dark theme green on the wash measured 1.15, orange 1.13, OFF 1.57 - the
   DEFECT this rule exists to avoid. The focused cell therefore takes --focus-ink
   (the wash's own ink, themed), and the ⚠ rides it too - on the focused red
   cell its --warn-fill-dark glyph is light-on-light in the light theme. */
@media screen{
td.cell.fc{background:var(--focus-fill) !important;color:var(--focus-ink) !important;
  box-shadow:inset 0 0 0 2px var(--focus-glow),0 0 10px var(--focus-glow)}
td.cell.fc .warn{color:var(--focus-ink)}
td.cell.fc.fc-a{box-shadow:inset 0 0 0 2px var(--focus-glow),inset 2px 0 0 var(--focus-glow),0 0 10px var(--focus-glow)}
td.cell.fc.fc-z{box-shadow:inset 0 0 0 2px var(--focus-glow),inset -2px 0 0 var(--focus-glow),0 0 10px var(--focus-glow)}
}

.warn{
  position:absolute;top:1px;right:2px;font-size:10px;line-height:1;color:var(--warn-ink);
  cursor:help;padding:1px;filter:saturate(1.2);
}
/* The row warning in the name cell must NOT be in flow: input.nm is width:100%,
   so an inline sibling wrapped onto a second line and grew the row. That is why
   "fill week" appeared to ignore the row height — filling a week trips the
   weekly-limit warning, the warning wrapped, and every warned row got taller. */
.warn.inl{position:absolute;right:3px;top:50%;transform:translateY(-50%);margin:0}
td.r .warn{color:var(--warn-fill-dark)}
td.y .warn,td.sk .warn,td.up .warn,td.an .warn{color:var(--warn-fill-light)}

td.total{
  font-weight:700;background:var(--total-bg);color:var(--ink);font-family:var(--mono);
  font-variant-numeric:tabular-nums;position:relative;font-size:14px;
}
td.total.over{background:var(--danger-soft);color:var(--total-over-ink)}

tfoot td{
  position:sticky;bottom:0;z-index:5;background:var(--foot);font-weight:700;color:var(--ink);
  border-top:1px solid var(--edge);height:var(--foot-h);
}
tfoot td.frz{z-index:7}
tfoot td.dt{font-family:var(--mono);font-variant-numeric:tabular-nums;font-size:13.5px}
tfoot td.grand{background:var(--foot-strong);color:var(--grand-ink);font-family:var(--mono);font-variant-numeric:tabular-nums;font-size:14.5px}
tfoot td.flab{text-align:right;padding-right:10px;font-size:10px;letter-spacing:.08em;text-transform:uppercase;color:var(--ink-2)}

.blank{padding:40px 18px;color:var(--ink-3);font-size:13px;text-align:center}
.blank b{color:var(--ink)}

/* cell editor */
input.ced{
  position:absolute;left:0;top:0;height:100%;z-index:9;border:2px solid var(--accent);
  background:var(--paper);color:var(--ink);text-align:center;padding:0 2px;border-radius:2px;
  font-family:var(--mono);font-size:12.5px;outline:none;
}
input.ced{background:var(--raised)}
input.ced.bad{border-color:var(--danger);background:var(--danger-soft);color:#ffb3a8}
td.cell.bad{box-shadow:inset 0 0 0 2px var(--danger) !important}

/* ------------------------------------------------------ popovers/menus */
.pop,.menu{
  position:fixed;z-index:60;background:var(--pop-bg);border:1px solid var(--edge);color:var(--ink);
  border-radius:12px;box-shadow:0 2px 8px rgba(0,0,0,.5),0 24px 56px -16px rgba(0,0,0,.85);
  padding:9px;max-width:calc(100vw - 20px);
}
.pop[hidden],.menu[hidden]{display:none}
.pop-hd{font-size:10.5px;color:var(--ink-3);font-weight:660;letter-spacing:.07em;margin:1px 3px 8px;text-transform:uppercase}
.pop-grid{display:grid;grid-template-columns:1fr 1fr;gap:7px}
.pop-btn{
  min-height:48px;min-width:112px;border:1px solid rgba(0,0,0,.1);border-radius:8px;
  cursor:pointer;font-weight:660;font-size:13px;padding:0 8px;letter-spacing:.02em;
}
.pop-btn:hover{filter:brightness(.96)}
.pop-btn.pg{background:var(--green-bg);color:var(--green-fg)}
.pop-btn.po{background:var(--orange-bg);color:var(--orange-fg)}
.pop-btn.pk{background:var(--red-bg);color:var(--red-fg)}
.pop-btn.px{background:var(--grey-bg);color:var(--grey-fg)}
.pop-btn.pi{background:#e9eaec;color:#4a4a4a}
.pop-btn.pn{background:var(--raised);border-color:var(--edge);color:var(--ink-2)}
.pop-btn.pr{background:var(--sick-bg);color:var(--sick-fg)}
.pop-btn.pu{background:var(--unpaid-bg);color:var(--unpaid-fg)}
.pop-btn.py{background:var(--annual-bg);color:var(--annual-fg)}
.pop-row{display:flex;gap:7px;align-items:center;margin-top:8px}
/* Three across in the width two .pop-btn minimums occupy, so the popover does
   not get wider. ÜCRETSİZ is the longest label and has to fit — check it. */
.pop-row.leaves .pop-btn{flex:1;min-width:0;min-height:40px;font-size:11px;padding:0 4px;letter-spacing:.01em}
.pop-row input[type=time]{
  height:44px;flex:1;min-width:98px;border:1px solid var(--edge);border-radius:8px;
  padding:0 7px;font-family:var(--mono);text-align:center;background:var(--raised);
  color-scheme:dark;
}
.pop-row input[type=time]:focus{border-color:var(--accent);outline:none}
.pop-row .dash{color:var(--ink-3)}
.pop-tip{font-size:10.5px;color:var(--ink-3);margin:9px 2px 1px;text-align:center;line-height:1.4}
.pop-tip b{font-family:var(--mono);color:var(--ink-2);font-weight:600}

.menu{padding:5px;min-width:236px}
.menu button{
  display:flex;align-items:center;gap:9px;width:100%;min-height:38px;padding:0 10px;border:0;
  background:transparent;text-align:left;cursor:pointer;border-radius:7px;font-size:12.5px;color:var(--ink);
}
.menu button:hover{background:var(--raised-2)}
.menu button.danger{color:var(--danger)}
.menu button.danger:hover{background:var(--danger-soft)}
.menu hr{border:0;border-top:1px solid var(--hair);margin:5px 3px}
#fileMenu{min-width:260px}
.menu .mi{width:16px;text-align:center;color:var(--ink-2);flex:none}
.btn .caret{font-size:9px;color:var(--ink-3);margin-left:-1px}
.menu .mlab{font-size:9.5px;color:var(--ink-3);padding:5px 10px 3px;font-weight:660;letter-spacing:.08em;text-transform:uppercase}
.menu select{
  width:calc(100% - 14px);margin:0 7px 7px;height:34px;border:1px solid var(--edge);
  border-radius:7px;padding:0 6px;background:var(--raised);color:var(--ink);
}
.menu select option{background:#1d2331;color:var(--ink)}
.sw{width:16px;height:16px;border-radius:4px;border:1px solid rgba(255,255,255,.28);flex:none}
.kbd{
  margin-left:auto;font-family:var(--mono);font-size:10px;color:var(--ink-3);
  background:var(--raised);border:1px solid var(--edge);border-radius:4px;padding:1px 5px;
}

/* --------------------------------------------------------------- panel */
.panel{
  position:fixed;top:0;right:0;bottom:0;width:352px;max-width:94vw;background:var(--paper);
  z-index:70;border-left:1px solid var(--edge);box-shadow:-8px 0 32px -12px rgba(16,20,28,.34);
  display:flex;flex-direction:column;
}
.panel[hidden]{display:none}
.panel-hd{display:flex;align-items:center;justify-content:space-between;padding:11px 13px;border-bottom:1px solid var(--hair)}
.panel-hd h2{margin:0;font-size:11px;letter-spacing:.1em;text-transform:uppercase;color:var(--ink-2)}
.panel-bd{padding:13px;overflow:auto;flex:1}
.fset{border:1px solid var(--hair);border-radius:9px;padding:4px 11px 12px;margin-bottom:13px;background:#12161f}
.fset legend{font-size:9.5px;font-weight:680;letter-spacing:.09em;color:var(--ink-3);padding:0 5px;text-transform:uppercase}
.frow{display:flex;align-items:center;justify-content:space-between;gap:9px;margin-top:8px}
.frow label{font-size:12px;color:var(--ink-2)}
.frow input,.frow select{
  width:106px;height:33px;border:1px solid var(--edge);border-radius:7px;padding:0 7px;
  font-family:var(--mono);text-align:center;background:var(--raised);color:var(--ink);
  color-scheme:dark;
}
.frow input:focus,.frow select:focus{border-color:var(--accent);outline:none}
.frow select option{background:var(--raised);color:var(--ink)}
/* column order / visibility editor in Settings → Appearance */
.collab{font-size:12px;color:var(--ink-2);margin-top:12px}
.cols{list-style:none;margin:7px 0 0;padding:0;display:flex;flex-direction:column;gap:5px}
.cols li{
  display:flex;align-items:center;gap:6px;height:34px;padding:0 5px 0 8px;
  border:1px solid var(--hair);border-radius:8px;background:var(--raised);
}
.cols li.off{opacity:.5}
.cols .cname{flex:1;min-width:0;font-size:11.5px;letter-spacing:.05em;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cols button{
  width:26px;height:24px;border:1px solid transparent;border-radius:6px;background:transparent;
  color:var(--ink-2);cursor:pointer;font-size:12px;line-height:1;padding:0;flex:none;
}
.cols button:hover:not(:disabled){background:var(--raised-2);color:var(--ink)}
.cols button:disabled{opacity:.25;cursor:default}
.cols button.eye[aria-pressed="true"]{color:var(--accent-ink);background:var(--accent-soft)}
.panel .btn.wide{width:100%;margin-top:9px;height:35px}
.hint{font-size:11.5px;color:var(--ink-3);margin:0;line-height:1.5}

/* ------------------------------------------------------- workers panel */
/* The same .panel / .fset / .btn shell as Settings, one hand wider: the rows
   carry a name, a department, a contract and a week's hours, and at 352px the
   contract wrapped onto a line of its own. */
.wk-panel{width:384px}
.wk-add{padding-bottom:13px}
.wk-lab{display:block;font-size:11.5px;color:var(--ink-2);margin:9px 0 5px}
.wk-in{
  width:100%;height:34px;border:1px solid var(--edge);border-radius:7px;padding:0 9px;
  background:var(--raised);color:var(--ink);font:inherit;font-size:13px;color-scheme:dark;
}
:root[data-theme="light"] .wk-in{color-scheme:light}
.wk-in:focus{border-color:var(--accent);outline:none}
.wk-two{display:grid;grid-template-columns:1fr auto;gap:10px;align-items:end}
.wk-seg button{font-family:var(--mono);font-size:11.5px;letter-spacing:.04em;min-width:56px}
.wk-go{width:100%;margin:13px 0 9px;height:35px}
.wk-ro{font-size:12px;color:var(--ink-2);background:var(--raised);border:1px solid var(--hair);border-radius:9px;padding:10px 12px;margin:0 0 6px}
.wk-sec{display:flex;align-items:center;gap:7px;margin:16px 2px 8px;font-size:10.5px;font-weight:680;letter-spacing:.09em;text-transform:uppercase;color:var(--ink-3)}
.wk-sec span{font-family:var(--mono);letter-spacing:0;padding:1px 7px;border-radius:9px;background:var(--raised);border:1px solid var(--hair);color:var(--ink-2)}
.wk-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:5px}
.wk-li{display:flex;align-items:center;gap:10px;min-height:46px;padding:6px 7px 6px 9px;border:1px solid var(--hair);border-radius:9px;background:var(--raised)}
.wk-av{flex:none;width:28px;height:28px;border-radius:50%;display:grid;place-items:center;font-size:12px;font-weight:650;background:var(--accent-soft);color:var(--accent-ink)}
.wk-txt{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}
.wk-txt b{font-size:13px;font-weight:600;color:var(--ink);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.wk-txt > span{font-size:11.5px;color:var(--ink-3);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.wk-new{font-style:normal;font-size:10px;font-weight:650;letter-spacing:.03em;padding:1px 6px;border-radius:9px;background:var(--accent-soft);color:var(--accent-ink);vertical-align:1px}
.wk-rm{height:28px;padding:0 10px;font-size:12px;color:var(--ink-2);background:transparent}
.wk-rm:hover{color:var(--danger);border-color:var(--danger);background:var(--danger-soft)}
.wk-gone .wk-av{background:var(--raised-2);color:var(--ink-3)}
.wk-gone .btn{height:28px;padding:0 10px;font-size:12px}
.wk-empty{font-size:11.5px;color:var(--ink-3);padding:2px}
/* The inline remove question. Its text is the same sentence the grid's card
   carries, so the two doors ask in exactly the same words. */
.wk-ask{flex-direction:column;align-items:stretch;gap:9px;padding:10px 11px;border-color:var(--danger);background:var(--danger-soft)}
.wk-ask .wk-txt b{white-space:normal}
.wk-ask .wk-txt > span{white-space:normal;color:var(--ink-2);line-height:1.45}
.wk-acts{display:flex;justify-content:flex-end;gap:6px}
.wk-acts .btn{height:30px;font-size:12px}
.wk-foot{margin-top:14px}

/* ------------------------------------------------- unsent-work offer */
/* Its own dimmer rather than the shared #backdrop: this is one question with
   two answers, it appears once per sign-in, and it must sit above the grid
   without taking part in the backdrop's overlay-stack of branches. */
.syncwrap{
  position:fixed;inset:0;z-index:80;display:grid;place-items:center;padding:16px;
  background:rgba(0,0,0,.55);
}
:root[data-theme="light"] .syncwrap{background:rgba(18,21,26,.32)}
.syncwrap[hidden]{display:none}
.synccard{
  width:min(420px,100%);padding:22px 22px 18px;background:var(--pop-bg);color:var(--ink);
  border:1px solid var(--edge);border-radius:14px;box-shadow:var(--shadow-1),var(--shadow-2);
}
.synccard h2{margin:0 0 8px;font-size:14px;font-weight:650;letter-spacing:.01em}
.synccard p{margin:0;font-size:12.5px;line-height:1.5;color:var(--ink-2)}
.syncact{display:flex;justify-content:flex-end;gap:8px;margin-top:18px}
.syncact .btn{height:35px}
.backdrop{position:fixed;inset:0;background:rgba(0,0,0,.55);z-index:65}
.backdrop[hidden]{display:none}
/* The account dialog frosts the grid behind it; the settings drawer keeps the
   plain dim, because it sits beside the table you are configuring and blurring
   what you are looking at would be worse. A browser without backdrop-filter
   simply gets the dim. */
.backdrop.blur{
  background:rgba(6,8,13,.62);
  -webkit-backdrop-filter:blur(14px) saturate(.85);
  backdrop-filter:blur(14px) saturate(.85);
}
:root[data-theme="light"] .backdrop.blur{background:rgba(228,232,239,.5)}
/* ------------------------------------------------------- login gate */
/* body.gate-on is written by syncGate() in js/app.js when no session exists.
   The app shell - toolbar, grid, overview, settings, branch card, popups and
   menus - is inert behind the login, so the one expression below names every
   control the gate covers rather than trusting each control to hide itself.
   Only the account card, the toast, and the login note reach the screen; print
   carries no entry because the authwrap hide rule already covers the wall.
   Colours come from tokens alone, so the wall reads identically in both
   themes, and the gate note is message text with no colour of its own. */
body.gate-on #toolbar,body.gate-on .stage,body.gate-on #overview,body.gate-on #settings,body.gate-on #branchPanel,body.gate-on #cellPop,body.gate-on #colorMenu,body.gate-on #rowMenu,body.gate-on #backdrop{display:none !important}
body.gate-on #authPanel{position:fixed; inset:0; z-index:70; display:grid; place-items:center; padding:24px; overflow:auto}
body.gate-on #closeAuth{display:none}
/* ------------------------------------------------------- account dialog */
/* A centred card, not a drawer: this is the one surface a first-time user
   meets before anything else, so it reads as a standard login screen rather
   than as another settings pane. display:grid outranks the hidden attribute,
   hence the [hidden] rule — the same trap .btn and .savestat hit. */
.authwrap{
  position:fixed; inset:0; z-index:70; display:grid; place-items:center;
  padding:24px; overflow:auto;
}
.authwrap[hidden]{display:none}
.authcard{
  position:relative; width:400px; max-width:100%;
  background:var(--paper); border:1px solid var(--edge); border-radius:16px;
  padding:34px 34px 26px; box-shadow:var(--shadow-2);
}
.authx{
  position:absolute; top:12px; right:12px; width:30px; height:30px; padding:0;
  border:0; border-radius:8px; background:transparent; color:var(--ink-3);
  cursor:pointer; font-size:13px; line-height:1;
}
.authx:hover{background:var(--raised-2); color:var(--ink)}
.authbrand{
  display:flex; align-items:center; gap:8px; margin-bottom:22px;
  font-weight:680; font-size:11px; letter-spacing:.11em; color:var(--ink-2);
}
.authbrand .dot{
  width:7px; height:7px; border-radius:2px; flex:none;
  background:linear-gradient(135deg,var(--accent),var(--accent-ink));
  box-shadow:0 0 10px 1px rgba(107,140,255,.65);
}
.authtitle{margin:0; font-size:21px; font-weight:640; letter-spacing:-.01em; color:var(--ink)}
.authsub{margin:6px 0 22px; font-size:12.5px; line-height:1.5; color:var(--ink-3)}
/* Stacked label-over-field, full width — the settings .frow layout puts a
   106px centred monospace box beside its label, which is right for "Rounding"
   and wrong for an email address. */
.fld{display:flex; flex-direction:column; gap:6px; margin-bottom:13px}
/* The class sets a display, so the hidden attribute does NOTHING without this -
   the pair .btn, .savestat, .panel, .pop, .authwrap, .branchpick and .ovw all
   had to learn, twice by shipping broken. It is live: the branch dialog hides
   its name field with `hidden` in "add a manager" mode, where the branch is the
   line that was clicked. */
.fld[hidden]{display:none}
.fld label{font-size:12px; font-weight:500; color:var(--ink-2)}
.fld input{
  width:100%; height:42px; padding:0 12px;
  border:1px solid var(--edge); border-radius:9px;
  background:var(--raised); color:var(--ink); font-size:13.5px; color-scheme:dark;
  transition:border-color .12s ease, box-shadow .12s ease;
}
.fld input::placeholder{color:var(--ink-3); opacity:.75}
.fld input:focus{border-color:var(--accent); outline:none; box-shadow:0 0 0 3px var(--accent-soft)}
:root[data-theme="light"] .fld input{color-scheme:light}
.btn.primary{
  background:var(--accent); border-color:var(--accent); color:var(--on-accent); font-weight:640;
}
.btn.primary:hover{background:var(--accent-ink); border-color:var(--accent-ink); color:var(--on-accent)}
.btn.primary:active{background:var(--accent); border-color:var(--accent)}
.authgo{width:100%; height:44px; margin-top:20px; font-size:13.5px}
.authalt{
  margin:18px 0 0; padding-top:17px; border-top:1px solid var(--hair);
  text-align:center; font-size:12.5px; color:var(--ink-3);
}
.linkbtn{
  border:0; background:transparent; padding:0 0 0 4px; cursor:pointer;
  font-size:12.5px; font-weight:600; color:var(--accent-ink); text-decoration:underline;
  text-underline-offset:2px;
}
:root[data-theme="light"] .linkbtn{color:var(--accent)}
.linkbtn:hover{color:var(--ink)}
.authcard .btn.wide{width:100%; height:42px; margin-top:18px}
/* --------------------------------------------- manage logins (head office) */
/* Inside the account card, so it inherits the card's width and needs no chrome
   of its own beyond the section heading. Every colour is a token: a literal is
   wrong in at least one of dark, light and print, and invisible to
   shotPalette(), which reads the resolved set off :root. No @media print entry
   is needed and one would be a dead selector - .authwrap is already named in
   the hide list, which removes this whole subtree with it. */
.authsec{
  margin:24px 0 10px; font-size:11px; font-weight:650; letter-spacing:.08em;
  text-transform:uppercase; color:var(--ink-2);
}
.mgr-list{list-style:none; margin:0; padding:0; display:flex; flex-direction:column; gap:6px}
/* Stacked, not one flex line: a branch name, a full email address and two
   actions do not fit across a 400px card, and an email that ellipsises to
   "kayas…" names no login anybody could check. The head row carries the
   identity, the tail row the actions. */
.mgr-li{
  display:flex; flex-direction:column; gap:7px; padding:9px 10px;
  border:1px solid var(--hair); border-radius:10px; background:var(--raised);
}
.mgr-nm{font-size:12.5px; font-weight:560; color:var(--ink)}
/* The email is the whole reason this section exists, so it wraps rather than
   truncates - break-all because an address has no spaces to break at. */
.mgr-em{font-size:11.5px; color:var(--ink-3); word-break:break-all}
/* The "no manager" state, in the same token pair the overview's badge uses, so
   the two screens report the same fact in the same colour. */
.mgr-none{font-size:11.5px; color:var(--danger)}
.mgr-acts{display:flex; flex-wrap:wrap; gap:6px; justify-content:flex-end}
.mgr-act{height:28px; padding:0 10px; font-size:11.5px}
/* (0,2,0) on purpose: .authnote is declared BELOW this block and would
   otherwise win the tie and re-centre the line. */
.authcard .mgr-note{margin:10px 0 0; text-align:left}
.authnote{margin:20px 0 0; font-size:11px; line-height:1.5; color:var(--ink-3); text-align:center}
/* The branch dialog's inline failure. Tokens, never literals - --danger and
   --danger-soft are the pair the overview's badge already uses, so this reads
   the same in light, in dark and on paper. No display of its own: a <p> is
   already block, so the hidden attribute needs no [hidden] companion here, and
   adding one would be a dead rule. */
.autherr{
  margin:0 0 4px; padding:9px 11px; border-radius:9px; font-size:12px; line-height:1.45;
  color:var(--danger); background:var(--danger-soft); border:1px solid var(--danger);
}

/* --------------------------------------------------------------- toast */
#toast{
  position:fixed;left:50%;bottom:24px;transform:translateX(-50%);z-index:90;
  background:var(--toast-bg);color:var(--toast-ink);padding:0 8px 0 15px;border-radius:9px;font-size:12.5px;
  box-shadow:0 10px 30px -8px rgba(0,0,0,.5);opacity:0;transition:opacity .15s ease;
  pointer-events:none;max-width:82vw;display:flex;align-items:center;gap:11px;height:42px;
}
#toast.show{opacity:1;pointer-events:auto}
#toast span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
#toast button{
  height:28px;padding:0 11px;border:0;border-radius:6px;background:var(--toast-btn);
  color:var(--toast-ink);cursor:pointer;font-size:12px;font-weight:600;flex:none;
}
#toast button:hover{background:var(--toast-btn-hi)}
#toast button[hidden]{display:none}

/* ------------------------------------------------- responsive */
/* The ~560px toolbar overflow is the known gap: the header already wraps, but
   at phone widths the groups themselves clipped instead of stacking. Below
   640px the week label takes its own full row (order moves it under the week
   stepper), the spacer collapses, and both button groups spread edge to edge.
   Nothing here touches the grid: the card scrolls horizontally on its own. */
@media (max-width:640px){
  .toolbar{gap:8px;padding:8px 10px}
  .brand{font-size:11px;letter-spacing:.08em}
  .wk{order:3;flex:1 1 100%;min-width:0;padding:0 2px}
  .spacer{display:none}
  .tb{flex:1 1 auto}
  .branchpick{flex:1 1 100%}
  .branchsel{max-width:100%;flex:1;min-width:0}
  .card{border-radius:10px}
  .stage{padding:8px 8px 10px}
  .ovw{padding:8px 8px 10px}
  .ovw-list{grid-template-columns:1fr}
  /* The chip's word would push the last toolbar button onto a row of its own;
     its colour-coded dot says the same, and the word is its title. */
  .toolbar .savestat{font-size:0;gap:0;padding:0;width:26px;justify-content:center}
  .authcard{padding:26px 20px 20px}
  .panel{width:min(352px,100vw)}
  .wk-panel{width:min(384px,100vw)}
}
/* Premium motion: one shared restrained language. Theme cross-fade lives on
   body above; here the interactive lift (buttons, rows, popover buttons) plus
   dialog entrances. Durations stay <= .25s, easing stays ease-out, no bounce.
   The suite's token guards only constrain COLOURS, so transitions are free. */
.btn,.seg button,.branchsel,.menu button,.pop-btn{transition:background-color .15s ease,border-color .15s ease,color .15s ease,transform .15s ease-out,box-shadow .2s ease-out}
.btn:hover{transform:translateY(-1px)}
.pop-btn:hover{transform:translateY(-1px)}
.authcard{animation:auth-in .22s ease-out}
.panel:not([hidden]){animation:panel-in .22s ease-out}
#toast.show{animation:toast-in .22s ease-out}
@keyframes auth-in{from{opacity:0;transform:translateY(8px) scale(.985)}to{opacity:1;transform:none}}
@keyframes panel-in{from{opacity:0;transform:translateX(16px)}to{opacity:1;transform:none}}
@keyframes toast-in{from{opacity:0;transform:translate(-50%,6px)}to{opacity:1;transform:translate(-50%,0)}}
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation:none !important;transition:none !important;scroll-behavior:auto !important}
}

/* --------------------------------------------------------------- print */
/* Save status. Existing tokens only — a literal colour here would be wrong in
   at least one of dark, light and print, and invisible to the PNG snapshot,
   which reads the resolved token set off :root. --ok is new and is declared in
   BOTH palettes; it needs no @media print entry because the whole toolbar is
   display:none on paper. */
.savestat{
  display:inline-flex; align-items:center; gap:6px;
  padding:0 10px; height:26px; border-radius:13px;
  font-size:11px; letter-spacing:.04em; white-space:nowrap;
  background:var(--raised); color:var(--ink-3);
  border:1px solid var(--edge);
}
.savestat[hidden]{display:none}
.savestat::before{
  content:""; width:7px; height:7px; border-radius:50%;
  background:currentColor;
}
.savestat[data-stat="saving"]{ color:var(--ink-3); }
.savestat[data-stat="saved"]{ color:var(--ok); }
.savestat[data-stat="offline"]{ color:var(--warn-ink); }
.savestat[data-stat="error"]{ color:var(--danger); }
/* --ink-2, not --ink-3: --ink-3 is what "saving" uses, and the ::before dot is
   background:currentColor, so the two states would have been pixel-identical
   apart from the word - and "saving" is the state every cloud boot starts in.
   A heavier neutral rather than --warn-ink, which "offline" already owns. */
.savestat[data-stat="readonly"]{ color:var(--ink-2); }

/* ------------------------------------------------------- read-only mode */
/* body.ro is written by syncEditable() in js/app.js when the signed-in account
   cannot edit the selected branch. Everything here is COSMETIC: the permission
   is can_edit() in Postgres, and the app-layer enforcement is the guard at the
   top of commit(). Hiding a button is not a permission.
   What must stay live is as important as what goes: theme, language, row height,
   column widths, column order and visibility are all state.ui, never leave this
   browser, and head office needs them like anyone else - so .rz-h, .rowh-h, the
   Görünüm fieldset, #resetCols and #colList are deliberately absent below. So
   are every export and print: reading is the point of the account.
   No @media print entry is needed - .toolbar, .panel, .row-acts and .grip are
   already in the hide list there, and this task adds no overlay. */
body.ro #editSep,body.ro #editTools,body.ro #importJson{display:none}
/* The drag grip reorders the roster, so it goes; the row-height handle beside it
   in the same cell stays. .row-acts is absolutely positioned and contributes no
   layout, so display:none costs nothing there - and it must be display, since
   :focus-within reveals it too. The in-flow grip is different: .no-in is a
   centred flex row, so removing it from the flow shifts the S.NO digit a few
   pixels off where a manager sees it, and this grid is meant to read identically
   for both accounts. visibility keeps the 7px and is just as unclickable. */
body.ro .row-acts,body.ro .grip.float{display:none}
body.ro .grip{visibility:hidden}
/* The five shared fieldsets hold state.settings, which is team data on the
   server. Marked in the markup rather than by :nth-child, so adding a fieldset
   cannot silently move the line. */
body.ro .fset.shared{display:none}
body.ro .edit-only{display:none}
.ro-only{display:none}
body.ro .ro-only{display:block}
/* A dead field must not look editable: the name and department inputs carry
   readonly (emitted by render(), because CSS cannot make an input readonly), so
   drop the focus affordance that says "type here". */
body.ro input.nm:focus,body.ro input.dp:focus{background:transparent;box-shadow:none}
body.ro select.durum{cursor:default}
select.durum:disabled{opacity:1}
/* The signup-only rows are hidden while the panel is in sign-in mode. */
#authPanel.mode-in .signup-only{ display:none; }

@media print{
  @page{size:A4 landscape;margin:6mm}
  /* Paper is light. Reset the chrome tokens whichever theme is active; the four
     shift fills above are deliberately NOT touched, so print matches the .xlsx
     and the PNG. The :root[data-theme] half is needed to outrank the light
     theme block's own (0,2,0) specificity. */
  :root,:root[data-theme]{
    --ink:#14161a; --ink-2:#4a5058; --ink-3:#5c6470;
    --paper:#ffffff; --canvas:#ffffff; --raised:#ffffff; --raised-2:#f2f4f8;
    --hair:#c9ced7; --edge:#8c939c;
    --head:#eef0f4; --head-we:#e4e9f2;
    --name-tint:#f4dcf2; --f-no-bg:#fcfcfd; --f-hover:#ffffff;
    --foot:#fdf6e3; --foot-strong:#f8e6b0;
    --accent:#3457d5; --accent-soft:#e8ecfb; --accent-ink:#22337e; --on-accent:#fff;
    --danger:#c0392b; --danger-soft:#fdeceb; --warn-ink:#8a4b00;
    --day-line:#8c939c;
  }
  html,body{height:auto;overflow:visible;background:#fff}
  body{display:block;font-size:7pt}
  .toolbar{background:#fff !important;box-shadow:none !important}
  td.g,td.o,td.r,td.y,td.sk,td.up,td.an{box-shadow:none !important}
  td.total{background:var(--total-bg) !important;color:#14161a !important}
  td.total.over{background:#fdeceb !important;color:#9c2318 !important}
  tfoot td.grand{color:#4a2f00 !important}
  thead tr.h1 th.day{box-shadow:none !important}
  thead tr.h1 th.day .d-name{color:#14161a}
  thead tr.h1 th.day,thead tr.h2 th.sub:nth-child(3n+1),
  tbody td.cell[data-part="in"],tfoot td.dt,
  thead tr.h1 th.k-totalh,tbody td.total,tfoot td.grand{border-left:1px solid #8c939c !important}
  td.time,td.pntj{font-size:7pt}
  td.cell.we.e{background:var(--cell-we) !important}
  .toolbar,.pop,.menu,.panel,.authwrap,.backdrop,#toast,.ovw,.row-acts,.grip,.rz-h,.rowh-h,.confirmcard,.syncwrap{display:none !important}
  .stage{padding:0;display:block}
  /* Paper is always the SELECTED branch's grid, never the overview. The
     body.ovw-on .stage{display:none} rule outside this block is (0,2,0) and
     would otherwise win here, printing a blank page whenever the overview
     happens to be the view on screen. */
  body.ovw-on .stage{display:block}
  .card{border:0;border-radius:0;box-shadow:none;overflow:visible}
  table{width:100%;table-layout:fixed}
  th,td{position:static !important;box-shadow:none !important;padding:0 1px;border-color:#b9bec6}
  /* position:static above is what unfreezes the sticky columns for paper, but
     it also removed the containing block every .warn is positioned against, so
     all seven ⚠ markers escaped their cells and stacked in the page's top-right
     corner. Hand the hosting cell a containing block back, and zero the inset:
     a frozen cell carries left:var(--off-*), and re-activating that offset is
     exactly bug #1 (freezing turned into visible displacement). That is why
     this is scoped to the cells that host a marker rather than to td. */
  td:has(.warn){position:relative !important;inset:auto !important}
  td{height:auto}
  tbody td{height:15pt}
  thead th{background:#eef0f4 !important;border-bottom:1px solid #8c939c}
  thead th.day.we,thead th.sub.we{background:var(--head-we) !important}
  td.f-name{background:var(--name-tint) !important}
  input.nm,input.dp{height:auto;font-size:7pt;padding:0 2px;font-weight:600}
  input.dp{font-weight:400;padding-right:2px}
  select.durum{height:auto;font-size:6.5pt;background:transparent !important;border:0;-webkit-appearance:none;appearance:none}
  .durum-wrap{padding:0}
  td.cell,td.total,tfoot td{font-size:7pt}
  tfoot td{background:var(--foot) !important}
  tfoot td.grand{background:var(--foot-strong) !important}
  /* Frozen columns take their print width from the inline --pw that render()
     computes, normalised across the VISIBLE ones — so hiding a column no longer
     strands its percentage (these used to sum to ~106% and relied on the
     browser rescaling). Day + total percentages are fixed and always present. */
  col.k-no,col.k-name,col.k-durum,col.k-dep{width:var(--pw)}
  col.kd{width:3.5% !important} col.k-total{width:6%}
  thead th.k-totalh{font-size:5.6pt}
  .d-name{font-size:7pt} .d-date{font-size:5.6pt}
  tr,td,th{break-inside:avoid}
}
