/* ==========================================================================
   Pensy.Work design system.
   Two brand colours out of the logo — navy #002269 and teal #00CCA0 — carry
   the whole palette. Dark is the designed default, so the bare :root holds it
   and the light theme is layered on top. Three viewer states are covered: an
   explicit data-theme wins in both directions, and an un-stamped document
   follows prefers-color-scheme.
   ========================================================================== */

:root {
  color-scheme: dark;

  /* Ground and surfaces: the brand navy pushed dark, so the logo sits at home.
     `canvas` is the page behind the phone-width app on a wide screen. */
  --canvas:      #03091C;
  --bg:          #05102B;
  --surface:     #0C1B3D;
  --surface-2:   #091634;
  --input:       #091634;
  --line:        #1E2E58;
  --line-soft:   #16234A;
  --line-strong: #2C3F70;

  /* Type: a paragraph, a form label and a section label are three different greys. */
  --text:        #FFFFFF;
  --text-2:      #C4CEE6;
  --text-3:      #8494B8;
  --text-label:  #B4C0DA;
  --text-section:#E6EBF7;

  /* Two brand colours and nothing else. Teal carries every action; a teal fill
     takes a navy label, which is the logo's own pairing and passes at 7:1. */
  --brand:       #FFFFFF;
  --accent:      #00CCA0;
  --accent-hi:   #22DCB2;
  --on-accent:   #002269;
  --accent-text: #2ADFB4;
  --accent-code: #2ADFB4;
  --lime:        #2ADFB4;
  --accent-ring: #10513F;
  --accent-wash: #06251E;
  --pill-bg:     #06291F;
  --pill-line:   #10513F;
  --pill-fg:     #4FE8C2;

  /* The edge a time box wears against the clock: late, running, still to come. */
  --due-late:  #E0605A;
  --due-now:   #00CCA0;
  --due-soon:  #E0A93B;

  /* Chat: the veil behind a panel, and the ground a quoted message sits on. */
  --scrim:         rgba(2, 8, 11, .6);
  --quote-bg:      rgba(255, 255, 255, .06);
  --quote-bg-mine: rgba(0, 34, 105, .12);

  /* Semantic */
  --danger:      #D3453F;
  --danger-hi:   #E05650;
  --danger-text: #FF9A95;
  --danger-wash: #2A0F0E;
  --warn:        #F2A32B;
  --warn-wash:   #2A1C06;

  /* Logo artwork, swapped per theme like any other token. */
  --logo-lockup: url("/brand/lockup-reversed.png");
  --logo-mark:   url("/brand/mark-reversed.png");
  /* Light artwork already reads on this ground, so it needs nothing behind it. */
  --logo-plate-dark: transparent;

  /* Avatars: the brand's two hues plus one, lightness set per theme. */
  --av-l: 32%;
  --av-fg: #FFFFFF;

  --shadow-1: 0 1px 2px rgba(0,0,0,.4);
  --shadow-2: 0 10px 30px -12px rgba(0,0,0,.72);
  --r-sm: 8px;
  --r:    10px;
  --r-lg: 16px;
  --tap: 48px;
}

@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) {
    color-scheme: light;
    --canvas:      #E8EEF7;
    --bg:          #F5F8FC;
    --surface:     #FFFFFF;
    --surface-2:   #EDF2FA;
    --input:       #F3F7FC;
    --line:        #D7E0EF;
    --line-soft:   #E4EAF4;
    --line-strong: #BECBE2;
    --text:        #061A45;
    --text-2:      #3B4C74;
    --text-3:      #5D6E93;
    --text-label:  #4A5B82;
    --text-section:#04143A;
    --brand:       #002269;
    --accent:      #00CCA0;
    --accent-hi:   #00B58E;
    --on-accent:   #002269;
    --accent-text: #00745F;
    --accent-code: #00745F;
    --lime:        #0A6B55;
    --accent-ring: #9FE3CE;
    --accent-wash: #E9FAF4;
    --pill-bg:     #E4F8F0;
    --pill-line:   #A8E4D0;
    --pill-fg:     #00614F;
    --due-late:  #D2403A;
    --due-now:   #00B58E;
    --due-soon:  #D9A21C;
  --scrim:         rgba(6, 26, 69, .42);
    --quote-bg:      rgba(6, 26, 69, .05);
    --quote-bg-mine: rgba(0, 34, 105, .10);
    --danger:      #C5312C;
    --danger-hi:   #A8231F;
    --danger-text: #A8231F;
    --danger-wash: #FCEDEC;
    --warn:        #A9660A;
    --warn-wash:   #FDF4E4;
    --logo-lockup: url("/brand/lockup.png");
    --logo-mark:   url("/brand/mark.png");
    --logo-plate-dark: #0B1B3F;
    --av-l: 38%;
    --av-fg: #FFFFFF;
    --shadow-1: 0 1px 2px rgba(6,26,69,.07);
    --shadow-2: 0 10px 30px -14px rgba(6,26,69,.3);
  }
}

:root[data-theme="light"] {
  color-scheme: light;
  --canvas:      #E8EEF7;
  --bg:          #F5F8FC;
  --surface:     #FFFFFF;
  --surface-2:   #EDF2FA;
  --input:       #F3F7FC;
  --line:        #D7E0EF;
  --line-soft:   #E4EAF4;
  --line-strong: #BECBE2;
  --text:        #061A45;
  --text-2:      #3B4C74;
  --text-3:      #5D6E93;
  --text-label:  #4A5B82;
  --text-section:#04143A;
  --brand:       #002269;
  --accent:      #00CCA0;
  --accent-hi:   #00B58E;
  --on-accent:   #002269;
  --accent-text: #00745F;
  --accent-code: #00745F;
  --lime:        #0A6B55;
  --accent-ring: #9FE3CE;
  --accent-wash: #E9FAF4;
  --pill-bg:     #E4F8F0;
  --pill-line:   #A8E4D0;
  --pill-fg:     #00614F;
  --due-late:  #D2403A;
  --due-now:   #00B58E;
  --due-soon:  #D9A21C;
  --scrim:         rgba(6, 26, 69, .42);
  --quote-bg:      rgba(6, 26, 69, .05);
  --quote-bg-mine: rgba(0, 34, 105, .10);
  --danger:      #C5312C;
  --danger-hi:   #A8231F;
  --danger-text: #A8231F;
  --danger-wash: #FCEDEC;
  --warn:        #A9660A;
  --warn-wash:   #FDF4E4;
  --logo-lockup: url("/brand/lockup.png");
  --logo-mark:   url("/brand/mark.png");
  --logo-plate-dark: #0B1B3F;
  --av-l: 38%;
  --av-fg: #FFFFFF;
  --shadow-1: 0 1px 2px rgba(6,26,69,.07);
  --shadow-2: 0 10px 30px -14px rgba(6,26,69,.3);
}

/* ---------- reset ---------- */
*, *::before, *::after { box-sizing: border-box; }
html, body { height: 100%; }
body {
  margin: 0;
  background: var(--canvas);
  color: var(--text);
  font-family: Roboto, -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
  font-size: 16px;
  line-height: 1.45;
  -webkit-font-smoothing: antialiased;
  -webkit-text-size-adjust: 100%;
}
h1, h2, h3 { margin: 0; font-weight: 700; letter-spacing: -.018em; text-wrap: balance; }
p { margin: 0; }
button, input, textarea, select { font: inherit; color: inherit; }
button { background: none; border: 0; padding: 0; cursor: pointer; color: inherit; }
/* Every icon in the app is stroke-drawn; `.dot` opts a shape into a solid fill. */
svg { fill: none; stroke: currentColor; stroke-width: 1.8; }
svg .dot { fill: currentColor; stroke: none; }
a { color: var(--accent-text); text-decoration: none; }
:focus-visible { outline: 2px solid var(--accent-text); outline-offset: 2px; border-radius: 6px; }
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .001ms !important; transition-duration: .001ms !important; }
}
.sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

/* ---------- app frame ----------
   Phone-first. On a wide screen the app keeps its phone measure and sits on the
   canvas, which is what the design assumes. */
#root { min-height: 100%; }
.app {
  min-height: 100vh;
  min-height: 100dvh;
  max-width: 430px;
  margin: 0 auto;
  background: var(--bg);
  display: flex;
  flex-direction: column;
  position: relative;
}
@media (min-width: 500px) {
  .app { min-height: calc(100dvh - 48px); margin: 24px auto; border-radius: 22px;
         box-shadow: var(--shadow-2); overflow: hidden; }
}
.screen {
  flex: 1;
  padding: 8px 16px calc(28px + env(safe-area-inset-bottom));
  display: flex;
  flex-direction: column;
}
.screen.center { justify-content: flex-start; }

/* ---------- top bar ---------- */
.topbar {
  display: flex; align-items: center; gap: 8px;
  min-height: 56px; padding: 12px 16px 4px;
}
.topbar .spacer { flex: 1; }
.iconbtn {
  width: 40px; height: 40px; flex: none;
  display: grid; place-items: center;
  border-radius: 999px; color: var(--text);
}
.iconbtn:hover { background: var(--surface-2); }
.iconbtn svg { width: 22px; height: 22px; }
.iconbtn[data-act="menu"], .iconbtn[data-act="rowmenu"] { color: var(--text-3); }
.iconbtn[data-act="menu"]:hover, .iconbtn[data-act="rowmenu"]:hover { color: var(--text); }
.topbar-title { font-size: 17px; font-weight: 500; }
.topbar .brand { position: absolute; left: 50%; transform: translateX(-50%); }

/* ---------- wordmark and logo artwork ---------- */
/* "pensy" is set heavier than "work", split by the teal dot, as the logo does. */
.brand {
  font-family: Poppins, Roboto, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  font-size: 22px; font-weight: 400; letter-spacing: -.005em;
  color: var(--brand); white-space: nowrap;
}
.brand b { font-weight: 600; }
.brand em { font-style: normal; font-weight: 600; font-size: 1.16em; color: var(--accent); }
.brand.lg { font-size: 30px; }

/* A team's own mark in place of ours. The plate class is decided at upload
   time by measuring the artwork, so any logo stays legible on both grounds. */
.teamlogo { display: flex; align-items: center; height: 32px; max-width: 176px; min-width: 0; flex: none; }
.teamlogo img { height: 100%; max-width: 100%; object-fit: contain; display: block; }
.teamlogo.plate-light { background: #FFFFFF; padding: 3px 7px; border-radius: 7px; }
.teamlogo.plate-dark { background: var(--logo-plate-dark); padding: 3px 7px; border-radius: 7px; }
.teamlogo.plate-none img { border-radius: 5px; box-shadow: 0 0 0 1px var(--line); }
.teamlogo.big { height: 52px; max-width: 240px; }

/* The drawn logo, as background art so the light and reversed files swap with
   the theme through a token rather than through a rule inside a theme block. */
.lockup, .markimg { background: var(--logo-lockup) center / contain no-repeat; }
.markimg { background-image: var(--logo-mark); display: inline-block; }
.lockup { display: block; width: 212px; height: 108px; margin: 0 auto; }
.markimg { width: 104px; height: 42px; }
.markimg.hero { display: block; width: 168px; height: 68px; margin: 0 auto; }

/* ---------- headings ---------- */
.h1 { font-size: 28px; font-weight: 700; line-height: 1.18; margin-bottom: 10px; }
.h1.sm { font-size: 25px; }
.h2 { font-size: 21px; font-weight: 700; line-height: 1.25; }
.lead { font-size: 14.5px; color: var(--text-2); line-height: 1.5; }
.lead.tight { line-height: 1.45; }
.section-label { font-size: 13.5px; font-weight: 500; color: var(--text-section); margin-bottom: 8px; }
.stack { display: flex; flex-direction: column; }
.gap-8 { gap: 8px; } .gap-12 { gap: 12px; } .gap-16 { gap: 16px; } .gap-20 { gap: 20px; } .gap-24 { gap: 24px; }
.mt-8 { margin-top: 8px; } .mt-12 { margin-top: 12px; } .mt-16 { margin-top: 16px; }
.mt-20 { margin-top: 20px; } .mt-24 { margin-top: 24px; } .mt-28 { margin-top: 28px; } .mt-auto { margin-top: auto; }
.center-text { text-align: center; }

/* ---------- hero badge (sign in, invite welcome) ---------- */
.badge-ring {
  width: 104px; height: 104px; margin: 0 auto;
  border: 2px solid var(--accent); border-radius: 999px;
  background: var(--accent-wash);
  display: grid; place-items: center;
}
.badge-ring svg { width: 46px; height: 46px; stroke: var(--accent-text); fill: none; stroke-width: 2.4; }

/* ---------- fields ---------- */
.field { display: flex; flex-direction: column; gap: 8px; }
.field > label { font-size: 13.5px; font-weight: 500; color: var(--text-label); }
.field .hint { font-size: 12.5px; color: var(--text-3); margin-top: -2px; }
.input {
  width: 100%; min-height: var(--tap);
  padding: 12px 14px;
  background: var(--input);
  border: 1px solid var(--line);
  border-radius: 10px;
  color: var(--text);
  font-size: 15px;
}
.input::placeholder { color: var(--text-3); }
.input:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-wash); }
textarea.input { min-height: 132px; resize: vertical; line-height: 1.55; }
.input.err { border-color: var(--danger); }
.pw { position: relative; display: flex; }
.pw .input { padding-right: 46px; }
.pw .eye {
  position: absolute; right: 4px; top: 50%; transform: translateY(-50%);
  width: 38px; height: 38px; display: grid; place-items: center;
  color: var(--text-3); border-radius: 8px;
}
.pw .eye:hover { color: var(--text-2); }
.pw .eye svg { width: 20px; height: 20px; stroke: currentColor; fill: none; stroke-width: 1.7; }

/* ---------- checkbox ---------- */
.checkrow { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.check { display: inline-flex; align-items: center; gap: 9px; font-size: 13.5px; color: var(--text-2); cursor: pointer; }
.check input { position: absolute; opacity: 0; width: 0; height: 0; }
.check .box {
  width: 18px; height: 18px; flex: none;
  border: 1.5px solid var(--line); border-radius: 4px;
  background: var(--input);
  display: grid; place-items: center;
}
.check .box svg { width: 12px; height: 12px; stroke: var(--on-accent); fill: none; stroke-width: 3; opacity: 0; }
.check input:checked + .box { background: var(--accent); border-color: var(--accent); }
.check input:checked + .box svg { opacity: 1; }
.check input:focus-visible + .box { outline: 2px solid var(--accent-text); outline-offset: 2px; }
.linkbtn { font-size: 13.5px; font-weight: 500; color: var(--accent-text); }
.linkbtn:hover { text-decoration: underline; }

/* ---------- buttons ---------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 10px;
  min-height: var(--tap); padding: 12px 18px;
  border-radius: 10px; border: 1px solid transparent;
  font-size: 15.5px; font-weight: 500; line-height: 1.2;
  background: var(--surface-2); color: var(--text); border-color: var(--line);
}
.btn:hover { border-color: var(--text-3); }
.btn:disabled { opacity: .55; cursor: default; }
.btn.full { width: 100%; }
.btn svg { width: 21px; height: 21px; stroke: currentColor; fill: none; stroke-width: 1.7; flex: none; }
.btn.primary { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.btn.primary:hover { background: var(--accent-hi); border-color: var(--accent-hi); }
.btn.danger { background: var(--danger); border-color: var(--danger); color: #FFFFFF; }
.btn.danger:hover { background: var(--danger-hi); border-color: var(--danger-hi); }
.btn.ghost { background: transparent; border-color: var(--line); }
.btn.outline-accent { background: transparent; border-color: var(--accent); color: var(--accent-text); }
.btn.sm { min-height: 38px; padding: 8px 13px; font-size: 13.5px; border-radius: var(--r-sm); }
.btnrow { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
/* A destructive confirmation leans on the safe choice being the smaller one. */
.btnrow.weighted { grid-template-columns: 1fr 1.7fr; }

/* ---------- or divider ---------- */
.or { display: flex; align-items: center; gap: 14px; color: var(--text-3); font-size: 13.5px; }
.or::before, .or::after { content: ""; flex: 1; height: 1px; background: var(--line); }

/* ---------- info box ---------- */
.infobox {
  display: flex; gap: 11px; align-items: center;
  padding: 13px 14px;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r);
  font-size: 13px; color: var(--text-3); line-height: 1.45;
}
.infobox svg { width: 24px; height: 24px; flex: none; stroke: var(--text-3); fill: none; stroke-width: 1.4; margin-top: 1px; }
.footnote {
  display: flex; align-items: center; justify-content: center; gap: 7px;
  font-size: 12.5px; color: var(--text-3);
}
.footnote svg { width: 13px; height: 13px; stroke: currentColor; fill: none; stroke-width: 1.8; }

/* ---------- invite code box ---------- */
.codebox {
  border: 1px dashed var(--accent-ring); border-radius: var(--r);
  background: var(--accent-wash);
  padding: 20px 16px 18px; text-align: center;
}
.codebox .code {
  font-size: 34px; font-weight: 600; letter-spacing: .1em;
  color: var(--accent-code); line-height: 1.1;
  font-variant-numeric: tabular-nums;
}
.codebox .url { margin-top: 8px; font-size: 14px; color: var(--text-2); word-break: break-all; }

/* ---------- avatars ---------- */
.av {
  --h: 111; --s: 43%;
  width: 40px; height: 40px; flex: none; border-radius: 999px;
  display: grid; place-items: center;
  background: hsl(var(--h) var(--s) var(--av-l));
  color: var(--av-fg);
  font-size: 17px; font-weight: 500; line-height: 1;
}
.av.lg { width: 52px; height: 52px; font-size: 22px; }
.av.xl { width: 76px; height: 76px; font-size: 31px; }
.av.sm { width: 30px; height: 30px; font-size: 13px; }
.av.xs { width: 26px; height: 26px; font-size: 11.5px; }
.av.a0 { --h: 167; --s: 78%; }
.av.a1 { --h: 222; --s: 70%; }
.av.a2 { --h: 268; --s: 42%; }
/* Your own face, wherever it is a way through to changing it. */
.avbtn { border: 0; background: none; padding: 0; cursor: pointer; display: block; border-radius: 999px; }
.avbtn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.avstack { display: flex; }
.avstack .av { margin-left: -6px; box-shadow: 0 0 0 2px var(--surface); }
.avstack .av:first-child { margin-left: 0; }

/* A photo covers the initial rather than replacing it, so a broken load falls
   back to the letter underneath. */
.av { position: relative; overflow: hidden; }
.av img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block; }

/* ---------- list card ---------- */
.card {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r); overflow: hidden;
}
.row {
  display: flex; align-items: center; gap: 12px;
  padding: 12px 14px;
  border-top: 1px solid var(--line-soft);
  width: 100%; text-align: left;
}
.row:first-child { border-top: 0; }
.row .body { flex: 1; min-width: 0; }
.row .name { font-size: 15.5px; color: var(--text); line-height: 1.3; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.row .sub { font-size: 13px; color: var(--text-3); margin-top: 1px;
             overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.row .acts { display: flex; align-items: center; gap: 6px; flex: none; }
.row .acts .btn { white-space: nowrap; }
.row .chev { color: var(--text-3); flex: none; }
.row .chev svg { width: 22px; height: 22px; stroke: currentColor; fill: none; stroke-width: 2; }

/* The roster draws each person as their own card rather than as rows in one. */
.rowlist { display: flex; flex-direction: column; gap: 10px; }
.rowlist .row {
  border: 1px solid var(--line); border-radius: var(--r);
  background: var(--surface); padding: 11px 12px; gap: 10px;
}
.rowlist .row .name { font-size: 17px; }
.rowlist .row .sub { font-size: 12.5px; }
.rowlist .row .acts { gap: 4px; }
.rowlist .row .acts .btn.sm { font-size: 12px; padding: 6px 9px; min-height: 32px; }

/* A screen whose title is the heading, not a small bar label. */
.pagehead { display: flex; align-items: flex-start; gap: 12px; padding: 4px 0 0; }
.pagehead h1 { flex: 1; font-size: 28px; font-weight: 700; letter-spacing: -.018em; }

/* pick rows (claim your name) sit apart as individual cards */
.pickrow {
  display: flex; align-items: center; gap: 12px; width: 100%;
  padding: 11px 14px; min-height: 62px;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r);
  text-align: left; font-size: 15.5px;
}
.pickrow:hover:not(:disabled) { border-color: var(--accent); }
.pickrow:disabled { cursor: default; opacity: .55; }
.pickrow .name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pickrow .chev { color: var(--text-3); flex: none; display: flex; }
.pickrow .chev svg { width: 20px; height: 20px; stroke-width: 2; }
.pickrow.dashed { border-style: dashed; color: var(--text-2); }
.pickrow.dashed .plus {
  width: 40px; height: 40px; flex: none; border-radius: 999px;
  display: grid; place-items: center; color: var(--text-3);
}
.pickrow.dashed .plus svg { width: 22px; height: 22px; stroke: currentColor; fill: none; stroke-width: 2; }

/* ---------- pills ---------- */
.pill {
  font-size: 11.5px; font-weight: 500; line-height: 1;
  padding: 5px 9px; border-radius: 6px;
  border: 1px solid var(--line); background: var(--surface-2); color: var(--text-3);
  white-space: nowrap;
}
.pill.quiet { background: transparent; border-color: transparent; padding-left: 0; padding-right: 0; }
.pill.on { color: var(--pill-fg); border-color: var(--pill-line); background: var(--pill-bg); }

/* ---------- warning banner ---------- */
.warnrow { display: flex; gap: 12px; align-items: center; }
.warnrow svg { width: 44px; height: 44px; flex: none; stroke: var(--warn); fill: none; stroke-width: 1.9; }
.warnrow p { font-size: 14px; color: var(--text-2); line-height: 1.45; }

/* ---------- kebab menu ---------- */
.menu-wrap { position: relative; }
.menu {
  position: absolute; right: 0; top: 44px; z-index: 40; min-width: 208px;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r); box-shadow: var(--shadow-2); padding: 6px;
}
.menu button {
  display: flex; align-items: center; gap: 10px; width: 100%;
  padding: 10px 11px; border-radius: var(--r-sm);
  font-size: 14.5px; color: var(--text); text-align: left;
}
.menu button:hover { background: var(--surface-2); }
.menu button svg { width: 18px; height: 18px; stroke: currentColor; fill: none; stroke-width: 1.7; flex: none; }
.menu .sep { height: 1px; background: var(--line); margin: 5px 0; }
.menu button.danger { color: var(--danger-text); }

/* ---------- board ---------- */
.boardbar {
  display: flex; align-items: center; gap: 10px;
  padding: 14px 16px 10px;
}
.boardbar .teampick { display: flex; align-items: center; gap: 6px; min-width: 0; }
/* The face sits at the end of the bar, and the menu opens under it. */
.boardbar .menu-wrap { display: flex; align-items: center; }
.boardbar .teampick svg { width: 16px; height: 16px; stroke: var(--text-3); fill: none; stroke-width: 2.2; flex: none; }
/* The week strip is a ribbon that snaps a week at a time. What is on screen is
   the same seven days it always was; the scroll is the only new thing, so a day
   two months out is reachable without a control being added to the design.
   The padding lives out here because the today pill overhangs its row, and an
   overflow container would clip it. */
.weeks {
  display: flex; overflow-x: auto; overflow-y: hidden;
  scroll-snap-type: x mandatory; overscroll-behavior-x: contain;
  padding: 4px 0 14px; border-bottom: 1px solid var(--line);
  scrollbar-width: none; -ms-overflow-style: none;
}
.weeks::-webkit-scrollbar { display: none; }
.week {
  /* Snapping keeps it resting on a clean seven days; not stopping at every
     one lets a flick carry several weeks, which is what reaching two months
     out has to feel like. */
  flex: 0 0 100%; scroll-snap-align: start;
  display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 3px;
  padding: 0 12px;
}
.day {
  border-radius: 10px; padding: 8px 2px 9px; text-align: center;
  border: 1px solid transparent;
}
.day .dw { font-size: 12px; color: var(--text-3); line-height: 1.2; }
.day .dn { font-size: 17px; font-weight: 500; line-height: 1.25; font-variant-numeric: tabular-nums; }
.day .dl { font-size: 10px; color: var(--text-3); line-height: 1.2; }
.day.today { background: var(--accent); padding-bottom: 13px; margin: -3px 0 -8px; position: relative; z-index: 1; }
.day.today .dw, .day.today .dn, .day.today .dl { color: var(--on-accent); }
.day.sel:not(.today) { border-color: var(--accent); }
.boardmeta {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 14px 16px 10px; font-size: 13.5px; color: var(--text-3);
}
.blocks { display: flex; flex-direction: column; gap: 10px; padding: 4px 16px 96px; }
.block {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r);
  padding: 14px 14px 12px;
  display: grid; grid-template-columns: minmax(0,1fr) 34px; gap: 12px;
  align-items: start; width: 100%; text-align: left;
}
.block .when {
  display: flex; align-items: baseline; gap: 8px;
  font-size: 12.5px; color: var(--text-3); margin-bottom: 3px;
  font-variant-numeric: tabular-nums;
}
.block .when .state { font-weight: 500; }
.block .ttl { font-size: 18px; color: var(--text); line-height: 1.3; }
.block .det { font-size: 13.5px; color: var(--text-3); margin-top: 3px; line-height: 1.45; }
.block .live { font-size: 12.5px; color: var(--lime); margin-top: 6px; }
.block .foot { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-top: 10px; }
.block .foot > span:first-child { min-width: 0; flex-shrink: 3; }
.block .cmt { display: flex; align-items: center; gap: 6px; font-size: 12.5px; color: var(--text-3); white-space: nowrap; }
.block .cmt svg { width: 14px; height: 14px; stroke: currentColor; fill: none; stroke-width: 1.8; }
.block .who { display: flex; align-items: center; gap: 8px; min-width: 0; flex-shrink: 1; }
.block .who .names {
  font-size: 12.5px; color: var(--text-3);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* Where the box sits against the clock. A slight border is enough: the card is
   already carrying a title, a time, its people and a checkbox. */
.block.s-overdue { border-color: var(--due-late); }
.block.s-overdue .when .state { color: var(--danger-text); }
.block.s-now { border-color: var(--due-now); }
.block.s-now .when .state { color: var(--accent-text); }
.block.s-upcoming { border-color: var(--due-soon); }
/* Work that happened is not late, whenever it ran, so it keeps the plain edge. */
.block.s-done { border-color: var(--line); }
.livenow { color: var(--accent-text); font-weight: 500; }

/* The line under the last thing still to do. */
.blockrule {
  display: flex; align-items: center; gap: 10px;
  margin: 8px 2px 2px; color: var(--text-3); font-size: 12px;
}
.blockrule::before, .blockrule::after { content: ""; height: 1px; background: var(--line); flex: 1; }
.tick {
  width: 34px; height: 34px; flex: none; border-radius: var(--r-sm);
  border: 1.5px solid var(--line); display: grid; place-items: center;
  background: transparent;
}
.tick svg { width: 19px; height: 19px; stroke: var(--text-3); fill: none; stroke-width: 2.8;
            stroke-linecap: butt; stroke-linejoin: miter; opacity: 0; }
.tick:hover svg { opacity: .45; }
.tick.on { background: var(--accent); border-color: var(--accent); }
.tick.on svg, .tick.on:hover svg { stroke: var(--on-accent); opacity: 1; }
.tick:disabled { cursor: default; }
/* Not yours to tick: on someone else, or on a day you are not in. It stays
   tappable so the reason can be said out loud rather than silently ignored. */
.tick.locked { border-style: dashed; border-color: var(--line); opacity: .45; }
.tick.locked:hover svg { opacity: 0; }

/* Whether the person reading is in today, above their day's work. */
.shiftbar {
  display: flex; align-items: center; gap: 7px;
  margin: 0 16px 4px; padding: 7px 11px;
  border-radius: 9px; border: 1px solid var(--pill-line); background: var(--pill-bg);
  font-size: 12.5px; color: var(--pill-fg);
}
.shiftbar.off { border-color: var(--line); background: var(--surface-2); color: var(--text-3); }
.shiftbar svg { width: 15px; height: 15px; flex: none; stroke: currentColor; fill: none; stroke-width: 1.8; }

/* One weekday in the shift editor. */
.shiftrow {
  display: flex; align-items: center; gap: 12px;
  padding: 9px 0; border-top: 1px solid var(--line-soft);
}
.shiftrow:first-child { border-top: 0; }
.shiftrow .dayname { font-size: 14.5px; color: var(--text); width: 42px; flex: none; }
.shiftrow .hours { display: flex; align-items: center; gap: 8px; flex: 1; justify-content: flex-end; }
.shiftrow .hours .input { padding: 7px 10px; font-size: 13.5px; width: auto; min-width: 0; }
.shiftrow .off { font-size: 13px; color: var(--text-3); }

/* When somebody is in, under their name on the roster. */
.row .sub.shifts { display: flex; align-items: center; gap: 6px; }
.row .sub.shifts svg { width: 13px; height: 13px; flex: none; stroke: currentColor; fill: none; stroke-width: 1.8; }
.fab {
  position: fixed; z-index: 30;
  left: 50%; transform: translateX(-50%);
  bottom: calc(18px + env(safe-area-inset-bottom));
  width: min(390px, calc(100vw - 40px));
  box-shadow: var(--shadow-2);
}

/* ---------- photos ---------- */
.pgrid {
  display: grid; gap: 6px;
  grid-template-columns: repeat(auto-fill, minmax(104px, 1fr));
}
.pcell {
  position: relative; aspect-ratio: 1; overflow: hidden;
  border-radius: var(--r-sm); border: 1px solid var(--line);
  background: var(--surface-2); padding: 0; display: block; width: 100%;
}
.pcell img { width: 100%; height: 100%; object-fit: cover; display: block; }
.pcell:hover { border-color: var(--accent); }
.pcap {
  position: absolute; left: 0; right: 0; bottom: 0;
  padding: 14px 7px 6px; font-size: 11.5px; line-height: 1.25; color: #FFFFFF;
  background: linear-gradient(to top, rgba(0,10,26,.82), rgba(0,10,26,0));
  text-align: left; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.pfull {
  width: 100%; max-height: 62vh; object-fit: contain;
  border-radius: var(--r); background: var(--surface-2); display: block;
}
/* the strip of thumbnails inside a time box */
.pstrip { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 10px; }
.pstrip .pthumb {
  width: 62px; height: 62px; border-radius: var(--r-sm); overflow: hidden;
  border: 1px solid var(--line); background: var(--surface-2); padding: 0; flex: none;
}
.pstrip .pthumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.photobadge {
  display: inline-flex; align-items: center; gap: 5px; white-space: nowrap;
  font-size: 12.5px; color: var(--text-3);
}
.photobadge svg { width: 14px; height: 14px; stroke: currentColor; fill: none; stroke-width: 1.8; }

/* ---------- switch ---------- */
.switchrow {
  display: flex; align-items: center; justify-content: space-between; gap: 14px;
  padding: 13px 0; border-top: 1px solid var(--line-soft);
}
.switchrow:first-of-type { border-top: 0; }
.switchrow .lbl { font-size: 15.5px; }
.switchrow .sub { font-size: 13px; color: var(--text-3); margin-top: 2px; }
.switch { position: relative; flex: none; width: 46px; height: 28px; }
.switch input { position: absolute; opacity: 0; width: 100%; height: 100%; margin: 0; cursor: pointer; }
.switch .track {
  position: absolute; inset: 0; border-radius: 999px;
  background: var(--surface-2); border: 1px solid var(--line); transition: background .15s ease;
  pointer-events: none;
}
.switch .track::after {
  content: ""; position: absolute; top: 3px; left: 3px; width: 20px; height: 20px;
  border-radius: 999px; background: var(--text-3); transition: transform .15s ease, background .15s ease;
}
.switch input:checked + .track { background: var(--accent); border-color: var(--accent); }
.switch input:checked + .track::after { transform: translateX(18px); background: var(--on-accent); }
.switch input:focus-visible + .track { outline: 2px solid var(--accent-text); outline-offset: 2px; }
/* The two-column settings grid wants a smaller one. */
.switch.sm { width: 38px; height: 23px; }
.switch.sm .track::after { top: 2px; left: 2px; width: 17px; height: 17px; }
.switch.sm input:checked + .track::after { transform: translateX(15px); }

/* ---------- notification settings ----------
   One row per thing a person would say out loud, with a column for the phone
   and a column for the inbox. */
.notifyhead {
  display: grid; grid-template-columns: 1fr 58px 58px; gap: 8px;
  padding: 0 14px 6px; font-size: 11.5px; color: var(--text-3); text-align: center;
}
.notifyhead span:first-child { text-align: left; }
.notifyrow {
  display: grid; grid-template-columns: 1fr 58px 58px; gap: 8px; align-items: center;
  padding: 12px 0; border-top: 1px solid var(--line-soft);
}
.notifyrow:first-child { border-top: 0; }
.notifyrow .what { min-width: 0; }
.notifyrow .col { display: flex; justify-content: center; }
.notifyrow .dash { color: var(--text-3); font-size: 13px; }
.switch.off { opacity: .4; }

/* ---------- empty state ---------- */
.empty {
  border: 1px dashed var(--line); border-radius: var(--r);
  padding: 28px 20px; text-align: center; color: var(--text-3); font-size: 14px;
}
.empty .t { font-size: 16px; color: var(--text); margin-bottom: 5px; font-weight: 500; }

/* ---------- sheet / modal ---------- */
.scrim {
  position: fixed; inset: 0; z-index: 60;
  background: var(--scrim);
  display: flex; align-items: flex-end; justify-content: center;
  padding: 0;
}
@media (min-width: 500px) { .scrim { align-items: center; padding: 24px; } }
.sheet {
  width: 100%; max-width: 430px; max-height: 88vh; overflow-y: auto;
  background: var(--bg); border: 1px solid var(--line);
  border-radius: var(--r-lg) var(--r-lg) 0 0;
  padding: 20px 20px calc(24px + env(safe-area-inset-bottom));
  box-shadow: var(--shadow-2);
}
@media (min-width: 500px) { .sheet { border-radius: var(--r-lg); } }

/* ---------- messages ---------- */
.alert {
  display: flex; gap: 10px; align-items: flex-start;
  padding: 11px 13px; border-radius: 10px;
  font-size: 13.5px; line-height: 1.45;
  border: 1px solid var(--danger); background: var(--danger-wash); color: var(--danger-text);
}
.alert.ok { border-color: var(--accent-ring); background: var(--accent-wash); color: var(--accent-text); }
.alert svg { width: 17px; height: 17px; flex: none; stroke: currentColor; fill: none; stroke-width: 1.8; margin-top: 1px; }
.toast {
  position: fixed; left: 50%; bottom: calc(24px + env(safe-area-inset-bottom));
  transform: translateX(-50%); z-index: 80;
  background: var(--surface); color: var(--text);
  border: 1px solid var(--line); border-radius: 999px;
  padding: 10px 18px; font-size: 14px; box-shadow: var(--shadow-2);
  max-width: min(92vw, 400px); text-align: center;
}
.spinner {
  width: 18px; height: 18px; border-radius: 999px;
  border: 2px solid var(--line); border-top-color: var(--accent-text);
  animation: spin .7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }
.loading { display: flex; align-items: center; justify-content: center; gap: 10px;
           padding: 60px 0; color: var(--text-3); font-size: 14px; }

/* ---------- workspace chat ----------
   Slides in over the schedule from the right. The wrapper lives outside the app
   shell, so a board refresh cannot replay the slide or scroll the room. Closed,
   it is out of the accessibility tree; the visibility delay lets the panel
   finish sliding out before it disappears. */
.chatwrap {
  position: fixed; inset: 0; z-index: 70;
  visibility: hidden;
  transition: visibility 0s .26s;
}
.chatwrap.open { visibility: visible; transition-delay: 0s; }

.chatscrim {
  position: absolute; inset: 0;
  background: var(--scrim);
  opacity: 0; transition: opacity .26s ease;
}
.chatwrap.open .chatscrim { opacity: 1; }

.chatpanel {
  position: absolute; top: 0; right: 0; bottom: 0;
  width: min(430px, 100%);
  display: flex; flex-direction: column;
  background: var(--bg);
  border-left: 1px solid var(--line);
  box-shadow: var(--shadow-2);
  transform: translateX(100%);
  transition: transform .26s cubic-bezier(.4, 0, .2, 1);
}
.chatwrap.open .chatpanel { transform: none; }
@media (prefers-reduced-motion: reduce) {
  .chatpanel, .chatscrim { transition: none; }
}
@media (min-width: 500px) {
  .chatpanel { top: 24px; bottom: 24px; right: max(24px, calc(50% - 454px));
               border: 1px solid var(--line); border-radius: 22px; overflow: hidden; }
}

.chathead {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 14px 14px 12px calc(18px + env(safe-area-inset-left));
  border-bottom: 1px solid var(--line); flex: none;
}
.chathead .ttl { font-size: 16.5px; font-weight: 700; color: var(--text); }
.chathead .sub { font-size: 12.5px; color: var(--text-3); margin-top: 1px; }

.chatlog {
  flex: 1; overflow-y: auto; overscroll-behavior: contain;
  padding: 12px 14px 4px;
  display: flex; flex-direction: column; gap: 2px;
}
.chatmore { text-align: center; padding: 4px 0 10px; }

.chatday {
  display: flex; align-items: center; gap: 10px;
  margin: 14px 0 8px; color: var(--text-3); font-size: 12px;
}
.chatday::before, .chatday::after { content: ""; height: 1px; background: var(--line); flex: 1; }

/* A message: someone else's on the left, mine on the right. */
.msgrow { display: flex; gap: 8px; align-items: flex-end; margin-top: 10px; }
.msgrow.runon { margin-top: 2px; }
.msgrow.mine { flex-direction: row-reverse; }
.msgav { flex: none; align-self: flex-end; }
.msgav.blank { width: 30px; }
.msgcol { min-width: 0; max-width: 78%; display: flex; flex-direction: column; }
.msgrow.mine .msgcol { align-items: flex-end; }
.msgwho { font-size: 12px; color: var(--text-3); margin: 0 0 3px 12px; }

.bubble {
  padding: 8px 12px 6px;
  border-radius: 16px 16px 16px 4px;
  background: var(--surface); border: 1px solid var(--line);
  color: var(--text); font-size: 14.5px; line-height: 1.45;
  word-break: break-word; overflow-wrap: anywhere; white-space: pre-wrap;
}
.msgrow.mine .bubble {
  border-radius: 16px 16px 4px 16px;
  background: var(--accent); border-color: var(--accent); color: var(--on-accent);
}
.bubble .meta { display: flex; justify-content: flex-end; margin-top: 2px; }
.bubble .when { font-size: 11px; color: var(--text-3); white-space: nowrap; }
.msgrow.mine .bubble .when { color: var(--on-accent); opacity: .68; }
.msgrow.flash .bubble { outline: 2px solid var(--accent-text); outline-offset: 2px; }

/* The quoted message a reply hangs off. */
.quote {
  display: block; width: 100%; text-align: left;
  border: 0; border-left: 3px solid var(--accent-text);
  background: var(--quote-bg);
  border-radius: 6px; padding: 5px 8px; margin: 0 0 5px;
  cursor: pointer; font: inherit;
}
.msgrow.mine .quote { border-left-color: var(--on-accent); background: var(--quote-bg-mine); }
.quote .who { display: block; font-size: 12px; font-weight: 500; color: var(--accent-text); }
.msgrow.mine .quote .who { color: var(--on-accent); }
.quote .txt { display: block; font-size: 12.5px; color: var(--text-3);
              white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.msgrow.mine .quote .txt { color: var(--on-accent); opacity: .75; }

/* Reactions and the reply handle sit under the bubble. */
.msgacts { display: flex; align-items: center; gap: 4px; margin: 3px 2px 0; flex-wrap: wrap; }
.msgrow.mine .msgacts { flex-direction: row-reverse; }
.react {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 2px 7px; border-radius: 999px;
  border: 1px solid var(--line); background: var(--surface-2);
  font-size: 11.5px; color: var(--text-3); cursor: pointer;
}
.react.on { border-color: var(--pill-line); background: var(--pill-bg); color: var(--pill-fg); }
.react .emoji { font-size: 12.5px; line-height: 1; }
.addreact {
  border: 0; background: none; cursor: pointer; padding: 1px 3px;
  font-size: 13px; line-height: 1; opacity: .38;
}
.addreact:hover, .addreact:focus-visible { opacity: 1; }
.linkbtn.tiny { font-size: 11.5px; padding: 0 4px; }

/* Compose. */
.chatcompose {
  flex: none; border-top: 1px solid var(--line);
  padding: 10px 14px calc(12px + env(safe-area-inset-bottom));
  background: var(--bg);
}
.replybar {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  border-left: 3px solid var(--accent-text); background: var(--quote-bg);
  border-radius: 6px; padding: 6px 8px; margin-bottom: 8px; min-width: 0;
}
.replybar .who { display: block; font-size: 12px; font-weight: 500; color: var(--accent-text); }
.replybar .txt { display: block; font-size: 12.5px; color: var(--text-3);
                 white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.composerow { display: flex; align-items: flex-end; gap: 8px; }
.composerow textarea.input {
  flex: 1; min-height: 44px; max-height: 132px; resize: none;
  padding: 11px 14px; border-radius: 22px; line-height: 1.4;
}
.btn.send { flex: none; width: 44px; height: 44px; padding: 0; border-radius: 999px; }
.btn.send svg { width: 19px; height: 19px; }

/* The header's chat button carries the unread count. */
.chatbtn { position: relative; }
.chatbtn .unread {
  position: absolute; top: -4px; right: -4px; min-width: 17px; height: 17px;
  padding: 0 4px; border-radius: 999px;
  background: var(--accent); color: var(--on-accent);
  font-size: 10.5px; font-weight: 700; line-height: 17px; text-align: center;
}

/* new build */
body { outline: 3px solid #FF00AA; }

/* new build */
body { outline: 3px solid #FF00AA; }
