/*
 * МузА — internal tool styling.
 *
 * The brief was "clean, clear, extremely easy to understand", and explicitly not
 * the current house style of AI-generated interfaces. So, deliberately absent:
 * gradients, glass, blur, oversized hero type, pill-shaped everything, drop
 * shadows used as decoration, and colour used where a word would do.
 *
 * What it is instead: a printed document that happens to be on a screen. One
 * warm paper background, near-black ink, hairline rules, and a real typographic
 * scale doing the work that decoration usually pretends to do. Tables look like
 * tables. Dense where density helps — this is a tool people use all day, not a
 * page they visit once.
 *
 * Every colour is also stated in words somewhere in the markup, because a
 * significant share of any workforce cannot rely on hue alone.
 *
 * ── Brand ──────────────────────────────────────────────────────────────────
 *
 * The palette and display face now come from МузА's actual identity guideline
 * ("Руководство по использованию элементов фирменного стиля") rather than being
 * invented here. That book specifies exactly two brand hues — PANTONE 7502C
 * gold and PANTONE 5405C blue-grey — and permits only gold-on-white,
 * blue-on-white, white-on-blue and gold-on-blue on any one surface.
 *
 * The division of labour between them is forced by contrast, not taste: the
 * gold sits at 1.8:1 against white, so it can never carry text or a button. It
 * is the brand's *presence* — the letterhead band, the wordmark rule, today's
 * date on the calendar. The blue-grey clears 5.5:1, so it carries every
 * interactive thing: links, primary buttons, focus rings, the active nav mark.
 *
 * The status triad (late / soon / good) is not in the book — it is a print
 * identity with no interface in it — so it stays, muted to sit beside the two
 * brand hues without shouting over them.
 *
 * Type: the book's primary face is Constantia, with Montserrat named as the
 * sanctioned alternate "when Constantia can't be applied", explicitly including
 * digital contexts. Constantia is a Microsoft desktop font and cannot be served
 * here, so Montserrat is the correct choice by the book's own rule. It is
 * self-hosted, subsetted, and confined to the display layer — body copy stays
 * on the system stack, so the page is fully readable before (or without) it.
 */

/* Cyrillic and Latin subsets only, self-hosted rather than pulled from a CDN:
   this thing has to load over a phone connection in a bakery basement, and an
   external font host is one more way for that to fail. `swap` means the page
   never blocks on it, and the fallback stack below is metrically close enough
   that the reflow is barely visible. */
@font-face {
  font-family: 'Montserrat';
  font-style: normal;
  font-weight: 600 700;
  font-display: swap;
  src: url('/static/montserrat-cyrillic.woff2') format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: 'Montserrat';
  font-style: normal;
  font-weight: 600 700;
  font-display: swap;
  src: url('/static/montserrat-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

:root {
  /* ── Brand ─────────────────────────────────────────────────────────────
     PANTONE 7502C and 5405C, straight from the guideline book. */
  --gold: #cab892;
  --gold-wash: #f7f3e9;
  --blue: #596a84;
  --blue-deep: #45536a;
  --blue-wash: #eef0f4;

  /* Paper and ink. The book's near-white and near-black, warmed a shade so the
     gold has something to sit on that isn't clinical. */
  --paper: #faf9f6;
  --paper-raised: #fefefe;
  --paper-sunken: #f2f1ec;
  --ink: #1c1b17;
  --ink-soft: #4c4a44;
  --ink-muted: #626b77;
  --rule: #e6e5e1;
  --rule-strong: #d0cfc9;
  /* The edge of anything you can type in or press. Kept as light as WCAG's 3:1
     boundary rule allows (3.20:1 on white, 3.06:1 on paper) so a legible
     control edge doesn't cost the hairline look everywhere else. `--rule-strong`
     stays on the things that only decorate: tag outlines, dashed empty states. */
  --edge: #928f89;

  /* Everything interactive. Aliased to the blue so the whole sheet can be
     re-pointed at another hue from one line. */
  --accent: var(--blue);
  --accent-hover: var(--blue-deep);
  --accent-wash: var(--blue-wash);

  --late: #9c2019;
  --late-wash: #fbecea;
  --soon: #7c5100;
  --soon-wash: #faf2e0;
  --good: #2b6335;
  --good-wash: #edf4ee;

  --sans: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
  --display: 'Montserrat', var(--sans);
  --mono: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace;

  /* What sits on top of a filled accent button. White over the blue-grey in
     light; the dark ground over gold in dark, where white would be unreadable. */
  --on-accent: #ffffff;

  --nav-width: 232px;
  --radius: 4px;

  /* Light is the default, and the sheet below assumes it. */
  color-scheme: light;

  /* ── Motion tokens (transitions.dev shared scale) ──────────────────────
     Installed as the project's motion vocabulary so timings are named rather
     than guessed. Only the durations and easings are used below — this app is
     server-rendered with full page loads, so it has no modals, drawers or
     toasts to move; what moves is state on things you point at. */
  --duration-stagger: 40ms;
  --duration-micro: 80ms;
  --duration-quick: 150ms;
  --duration-fast: 250ms;
  --duration-medium: 350ms;
  --duration-slow: 400ms;
  --duration-very-slow: 500ms;

  --ease-smooth-out: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-in-out: ease-in-out;
  --ease-out: ease-out;
  --ease-linear: linear;
  --ease-bounce: cubic-bezier(0.34, 1.36, 0.64, 1);
  --ease-bounce-strong: cubic-bezier(0.34, 3.85, 0.64, 1);

  --distance-micro: 4px;
  --distance-base: 8px;
  --distance-medium: 12px;
  --blur-small: 2px;
}

/* The three states a viewer can be in: no choice at all (follow the system),
   an explicit light, and an explicit dark. The palette is redefined at token
   level only — no component below ever names a colour inside a theme block,
   which is what stops one theme's text landing on the other theme's ground.

   The dark values appear twice on purpose. A media query and an attribute
   selector cannot be combined into one rule, and duplicating twenty lines is
   plainer than the indirection that would avoid it. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
  /* ── Dark ────────────────────────────────────────────────────────────
     Not a neutral black: the ground is built from the logo's own blue-grey
     (PANTONE 5405C, hue ~216°), so the dark theme is the brand colour rather
     than an absence of colour.

     And the accent flips to gold. That is not decoration — it is the one
     pairing the guideline book sanctions that light mode could never use: gold
     sits at 1.85:1 on white and cannot carry text there, but at 8.9:1 on this
     ground it carries links, buttons and focus rings comfortably. Dark mode is
     where МузА's gold finally gets to do real work. */
  --paper: #171b22;
  --paper-raised: #1f242e;
  --paper-sunken: #12151b;
  --ink: #ebe8e2;
  --ink-soft: #bcc0c8;
  --ink-muted: #949ba7;
  --rule: #2a3039;
  --rule-strong: #39414d;
  --edge: #6b7684;

  --accent: var(--gold);
  --accent-hover: #dccdad;
  --accent-wash: #2a2620;
  --on-accent: #171b22;
  --gold-wash: #2a2620;

  /* Lifted off the dark ground, and "soon" pushed towards orange so it is not
     mistaken for the gold accent sitting next to it — 28° against gold's 41°,
     and more than twice the saturation. */
  --late: #ef8f86;
  --late-wash: #33201f;
  --soon: #f0a15c;
  --soon-wash: #2e2718;
  --good: #7cc78d;
  --good-wash: #1c2a20;

  color-scheme: dark;
  }
}

:root[data-theme="dark"] {
  /* ── Dark ────────────────────────────────────────────────────────────
     Not a neutral black: the ground is built from the logo's own blue-grey
     (PANTONE 5405C, hue ~216°), so the dark theme is the brand colour rather
     than an absence of colour.

     And the accent flips to gold. That is not decoration — it is the one
     pairing the guideline book sanctions that light mode could never use: gold
     sits at 1.85:1 on white and cannot carry text there, but at 8.9:1 on this
     ground it carries links, buttons and focus rings comfortably. Dark mode is
     where МузА's gold finally gets to do real work. */
  --paper: #171b22;
  --paper-raised: #1f242e;
  --paper-sunken: #12151b;
  --ink: #ebe8e2;
  --ink-soft: #bcc0c8;
  --ink-muted: #949ba7;
  --rule: #2a3039;
  --rule-strong: #39414d;
  --edge: #6b7684;

  --accent: var(--gold);
  --accent-hover: #dccdad;
  --accent-wash: #2a2620;
  --on-accent: #171b22;
  --gold-wash: #2a2620;

  /* Lifted off the dark ground, and "soon" pushed towards orange so it is not
     mistaken for the gold accent sitting next to it — 28° against gold's 41°,
     and more than twice the saturation. */
  --late: #ef8f86;
  --late-wash: #33201f;
  --soon: #f0a15c;
  --soon-wash: #2e2718;
  --good: #7cc78d;
  --good-wash: #1c2a20;

  color-scheme: dark;
}

*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  /* Removes the 300ms wait Safari spends deciding whether a tap was a
     double-tap-to-zoom. Every button on this site feels quicker for it. */
  touch-action: manipulation;
}

body {
  margin: 0;
  /* The letterhead band. In the book every printed surface carries the brand
     colour as a flat edge rather than a logo pasted in a corner. */
  border-top: 3px solid var(--gold);
  background: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 15px;
  line-height: 1.55;
  font-feature-settings: 'tnum' 1;
}

a { color: var(--accent); text-decoration: none; transition: color var(--duration-fast) var(--ease-out); }
a:hover { text-decoration: underline; transition-duration: var(--duration-quick); }

h1, h2, h3 {
  margin: 0;
  font-family: var(--display);
  font-weight: 600;
  letter-spacing: -0.01em;
  /* Russian and Uzbek headings are long. Without this the last word regularly
     drops to a line of its own. */
  text-wrap: balance;
}
h1 { font-size: 26px; line-height: 1.25; }
h2 { font-size: 18px; line-height: 1.3; }
h3 { font-size: 15px; }

p { margin: 0 0 12px; }
small { font-size: 13px; }

.muted { color: var(--ink-muted); }
.soft { color: var(--ink-soft); }
.mono { font-family: var(--mono); font-size: 13px; }
.hidden { display: none !important; }
/* The `hidden` attribute is only a UA-stylesheet rule, so any author
   `display` — `.btn` for one — silently overrides it. */
[hidden] { display: none !important; }
.right { text-align: right; }
.nowrap { white-space: nowrap; }

/* ── Keyboard access ───────────────────────────────────────────────────── */

/* There was no visible focus anywhere except form fields, which made the whole
   site unusable by keyboard — you could tab, but never see where you were.
   One ring, everywhere, on keyboard focus only so mouse users never see it. */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 2px;
}

/* Fifteen navigation links stand between the top of every page and its
   content. Without this, that is fifteen tab stops, on every page, forever. */
.skip {
  position: absolute;
  left: 8px;
  top: -100px;
  z-index: 10;
  padding: 9px 14px;
  background: var(--paper-raised);
  border: 1px solid var(--accent);
  border-radius: var(--radius);
  color: var(--accent);
  font-weight: 600;
  transition: top var(--duration-fast) var(--ease-smooth-out);
}
.skip:focus { top: 8px; text-decoration: none; }

/* Available to screen readers, invisible on screen. Used where a control says
   something in colour or shape that it must also say in words. */
.vh {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ── Shell ─────────────────────────────────────────────────────────────── */

.shell { display: flex; min-height: calc(100vh - 3px); }

.nav {
  width: var(--nav-width);
  flex: 0 0 var(--nav-width);
  border-right: 1px solid var(--rule);
  background: var(--paper-sunken);
  padding: 20px 0 32px;
  display: flex;
  flex-direction: column;
}

.brand {
  padding: 0 20px 20px;
  border-bottom: 1px solid var(--rule);
  margin-bottom: 12px;
}
/* The gold ribbon sits above the wordmark in the book. Here it is a rule of the
   same weight, in the same place, doing the same job. */
.brand-mark { display: block; width: 26px; height: 3px; background: var(--gold); margin-bottom: 9px; }
.brand-name { font-family: var(--display); font-size: 17px; font-weight: 700; letter-spacing: 0.06em; }
.brand-sub { font-size: 12px; color: var(--ink-muted); margin-top: 3px; }

.nav-group { padding: 12px 0 4px; }
.nav-group + .nav-group { margin-top: 4px; border-top: 1px solid var(--rule); padding-top: 14px; }
.nav-group-title {
  padding: 0 20px 7px;
  font-family: var(--display);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-muted);
}

.nav a {
  display: flex;
  justify-content: space-between;
  gap: 8px;
  padding: 7px 20px;
  color: var(--ink-soft);
  border-left: 2px solid transparent;
  /* Hover-out is the slower half: the row settles rather than snapping back. */
  transition:
    background-color var(--duration-fast) var(--ease-out),
    color var(--duration-fast) var(--ease-out),
    border-left-color var(--duration-fast) var(--ease-out);
}
.nav a:hover {
  background: var(--paper);
  color: var(--ink);
  text-decoration: none;
  transition-duration: var(--duration-quick);
}
.nav a.active {
  background: var(--paper);
  color: var(--ink);
  border-left-color: var(--accent);
  font-weight: 600;
}
.nav a .count {
  font-size: 12px;
  color: var(--ink-muted);
  font-variant-numeric: tabular-nums;
}
.nav a.active .count, .nav a .count.alert { color: var(--late); font-weight: 600; }

.nav-foot { margin-top: auto; padding: 16px 20px 0; border-top: 1px solid var(--rule); font-size: 13px; }

.main { flex: 1 1 auto; min-width: 0; }

.topbar {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  padding: 22px 32px 16px;
  border-bottom: 1px solid var(--rule);
  background: var(--paper);
}
.topbar .sub { color: var(--ink-muted); font-size: 13px; margin-top: 3px; }

.content { padding: 24px 32px 64px; max-width: 1100px; }

/* ── Language switch ───────────────────────────────────────────────────── */

.langs { display: flex; gap: 2px; }
.langs a {
  padding: 4px 9px;
  font-size: 12px;
  color: var(--ink-muted);
  border: 1px solid transparent;
  border-radius: var(--radius);
  transition:
    background-color var(--duration-fast) var(--ease-out),
    border-color var(--duration-fast) var(--ease-out),
    color var(--duration-fast) var(--ease-out);
}
.langs a:hover { color: var(--ink); background: var(--paper-sunken); text-decoration: none; transition-duration: var(--duration-quick); }
.langs a.on { color: var(--ink); border-color: var(--rule-strong); background: var(--paper-raised); }

/* Three icons are rendered, one per theme; only the one matching what the
   server actually stamped on <html> is shown — same mechanism the old
   three-chip switch used, just down to a single visible icon. */
.theme-toggle {
  display: none;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  color: var(--ink-muted);
  border: 1px solid transparent;
  border-radius: var(--radius);
  transition:
    background-color var(--duration-fast) var(--ease-out),
    border-color var(--duration-fast) var(--ease-out),
    color var(--duration-fast) var(--ease-out);
}
.theme-toggle:hover { color: var(--ink); background: var(--paper-sunken); border-color: var(--rule-strong); text-decoration: none; transition-duration: var(--duration-quick); }
:root:not([data-theme]) .theme-toggle[data-theme="auto"],
:root[data-theme="light"] .theme-toggle[data-theme="light"],
:root[data-theme="dark"] .theme-toggle[data-theme="dark"] {
  display: inline-flex;
}

/* ── Sections and cards ────────────────────────────────────────────────── */

.section { margin-bottom: 32px; }
.section-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 10px;
  padding-bottom: 6px;
  border-bottom: 1px solid var(--rule);
}

.card {
  background: var(--paper-raised);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  padding: 16px 18px;
}

.grid { display: grid; gap: 12px; }
.grid-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.grid-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.grid-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }

/* Numbers that matter, stated plainly. */
.stat { background: var(--paper-raised); border: 1px solid var(--rule); border-radius: var(--radius); padding: 14px 16px; }
.stat-value { font-family: var(--display); font-size: 30px; font-weight: 600; line-height: 1.1; letter-spacing: -0.02em; }
.stat-label { font-size: 13px; color: var(--ink-muted); margin-top: 4px; }
.stat.alert .stat-value { color: var(--late); }
.stat.warn .stat-value { color: var(--soon); }

/* ── Tables ────────────────────────────────────────────────────────────── */

table { width: 100%; border-collapse: collapse; background: var(--paper-raised); }
.table-wrap { border: 1px solid var(--rule); border-radius: var(--radius); overflow-x: auto; }

th {
  text-align: left;
  font-family: var(--display);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--ink-muted);
  padding: 10px 14px;
  border-bottom: 1px solid var(--rule);
  white-space: nowrap;
}
/* A task title may be up to 400 characters and arrives from a phone keyboard,
   so it can be one unbroken word. Without this it widens the column until the
   table scrolls sideways. */
td { padding: 11px 14px; border-bottom: 1px solid var(--rule); vertical-align: top; overflow-wrap: anywhere; }
tbody tr:last-child td { border-bottom: none; }
tbody tr { transition: background-color var(--duration-fast) var(--ease-out); }
tbody tr:hover { background: var(--paper-sunken); transition-duration: var(--duration-quick); }
td.tight { width: 1%; white-space: nowrap; }

.row-late td:first-child { box-shadow: inset 3px 0 0 var(--late); }
.row-soon td:first-child { box-shadow: inset 3px 0 0 var(--soon); }
.row-done td:first-child { box-shadow: inset 3px 0 0 var(--good); }

/* ── Task list ─────────────────────────────────────────────────────────── */

/* Replaces the five-column task table. The old row lined up priority, status,
   deadline and buttons as four bordered chips, so an ordinary task looked like
   an emergency and nothing could be scanned. Here a healthy task carries no
   decoration at all: colour appears only when something is actually wrong. */

.tasks {
  list-style: none;
  margin: 0;
  padding: 0;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--paper-raised);
  overflow: hidden;
}

.task {
  position: relative;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 18px;
  padding: 12px 16px 12px 18px;
  border-bottom: 1px solid var(--rule);
  transition: background-color var(--duration-fast) var(--ease-out);
}
.task:last-child { border-bottom: none; }
.task:hover { background: var(--paper-sunken); transition-duration: var(--duration-quick); }

/* The severity rail — the only always-on colour, and it never says anything
   the words a few centimetres away do not already say. */
.task::before { content: ''; position: absolute; left: 0; top: 0; bottom: 0; width: 3px; background: transparent; }
.task.is-late::before { background: var(--late); }
.task.is-soon::before { background: var(--soon); }

.task-body { flex: 1 1 auto; min-width: 0; }
.task-title { display: block; color: var(--ink); font-weight: 500; line-height: 1.4; overflow-wrap: anywhere; }
.task-title:hover { color: var(--accent); }

/* Two lines of the detail, then it stops. The rest is on the task's own page. */
.task-detail {
  margin: 4px 0 0;
  font-size: 13px;
  line-height: 1.45;
  color: var(--ink-soft);
  overflow-wrap: anywhere;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.task-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0 7px;
  margin-top: 4px;
  font-size: 12px;
  color: var(--ink-muted);
}
/* Middots between facts, drawn by the stylesheet so the markup stays a plain
   list of spans. */
.task-meta > * + *::before { content: '·'; margin-right: 7px; color: var(--rule-strong); }

.task-flag {
  font-family: var(--display);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.07em;
  text-transform: uppercase;
}
.task-flag.is-critical, .task-flag.is-blocked { color: var(--late); }
.task-flag.is-urgent, .task-flag.is-waiting { color: var(--soon); }
.task-flag.is-review { color: var(--accent); }

.task-aside { display: flex; align-items: center; gap: 14px; flex: 0 0 auto; }
.task-due { font-size: 13px; color: var(--ink-muted); white-space: nowrap; font-variant-numeric: tabular-nums; }
.task-due.is-late { color: var(--late); font-weight: 600; }
.task-due.is-soon { color: var(--soon); }
.task-acts { display: flex; gap: 6px; }

/* ── Tags ──────────────────────────────────────────────────────────────── */

.tag {
  display: inline-block;
  padding: 1px 7px;
  font-size: 12px;
  line-height: 1.6;
  border: 1px solid var(--rule-strong);
  border-radius: var(--radius);
  color: var(--ink-soft);
  background: var(--paper);
  white-space: nowrap;
}
.tag.late { color: var(--late); border-color: var(--late); background: var(--late-wash); }
.tag.soon { color: var(--soon); border-color: var(--soon); background: var(--soon-wash); }
.tag.good { color: var(--good); border-color: var(--good); background: var(--good-wash); }
.tag.accent { color: var(--accent-hover); border-color: var(--accent); background: var(--accent-wash); }

/* ── Buttons and forms ─────────────────────────────────────────────────── */

.btn {
  display: inline-block;
  padding: 8px 14px;
  font-family: inherit;
  font-size: 14px;
  font-weight: 500;
  color: var(--ink);
  background: var(--paper-raised);
  border: 1px solid var(--edge);
  border-radius: var(--radius);
  cursor: pointer;
  text-decoration: none;
  transition:
    background-color var(--duration-fast) var(--ease-out),
    border-color var(--duration-fast) var(--ease-out);
}
.btn:hover { background: var(--paper-sunken); text-decoration: none; transition-duration: var(--duration-quick); }
.btn-primary { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.btn-primary:hover { background: var(--accent-hover); border-color: var(--accent-hover); }
.btn-danger { color: var(--late); border-color: var(--edge); }
.btn-sm { padding: 5px 10px; font-size: 13px; }
.btn-row { display: flex; flex-wrap: wrap; gap: 8px; }

label { display: block; font-size: 13px; font-weight: 600; margin: 0 0 5px; }
.field { margin-bottom: 16px; }
.field .hint { font-size: 12px; color: var(--ink-muted); margin-top: 4px; }

input[type=text], input[type=url], input[type=date], input[type=time], input[type=number], select, textarea {
  width: 100%;
  padding: 8px 10px;
  font-family: inherit;
  font-size: 15px;
  color: var(--ink);
  background: var(--paper-raised);
  border: 1px solid var(--edge);
  border-radius: var(--radius);
  transition: border-color var(--duration-quick) var(--ease-out);
}
textarea { resize: vertical; min-height: 90px; line-height: 1.5; }
input:focus, select:focus, textarea:focus { outline: 2px solid var(--accent); outline-offset: -1px; border-color: var(--accent); }

.check { display: flex; align-items: center; gap: 8px; font-weight: 400; margin-bottom: 8px; }
.check input { width: 17px; height: 17px; accent-color: var(--accent); }

.inline-form { display: inline; }

/* ── Readiness ─────────────────────────────────────────────────────────── */

/* Three squares: text, media, approval. Readable at a glance, and every one is
   also spelled out in a screen-reader-only sentence beside it, because three
   squares alone are a puzzle and a `title` attribute reaches neither a keyboard
   nor most screen readers. */
.ready { display: inline-flex; gap: 3px; vertical-align: middle; }
.ready i {
  width: 11px; height: 11px;
  border: 1px solid var(--rule-strong);
  border-radius: 2px;
  background: var(--paper);
  display: block;
}
.ready i.on { background: var(--good); border-color: var(--good); }

/* ── Calendar ──────────────────────────────────────────────────────────── */

.cal { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 1px; background: var(--rule); border: 1px solid var(--rule); border-radius: var(--radius); overflow: hidden; }
.cal-head { background: var(--paper-sunken); padding: 8px; font-family: var(--display); font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.07em; color: var(--ink-muted); text-align: center; }
.cal-day { background: var(--paper-raised); min-height: 108px; padding: 7px 8px; }
.cal-day.other { background: var(--paper-sunken); }
/* Today is the one place the gold carries meaning rather than decoration — and
   the date itself is still marked in words, so the tint is never the only cue. */
.cal-day.today { background: var(--gold-wash); box-shadow: inset 0 2px 0 var(--gold); }
.cal-date { font-size: 12px; font-weight: 600; color: var(--ink-muted); margin-bottom: 5px; }
.cal-day.today .cal-date { color: var(--ink); }
.cal-today {
  font-family: var(--display);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  margin-left: 4px;
}
.cal-item {
  display: block;
  font-size: 12px;
  line-height: 1.35;
  padding: 4px 5px;
  margin-bottom: 3px;
  border-radius: 3px;
  border-left: 3px solid var(--rule-strong);
  background: var(--paper-sunken);
  color: var(--ink);
  transition: background-color var(--duration-fast) var(--ease-out);
}
.cal-item:hover { text-decoration: none; background: var(--paper); transition-duration: var(--duration-quick); }
.cal-item.late { border-left-color: var(--late); }
.cal-item.ready { border-left-color: var(--good); }
.cal-item.published { border-left-color: var(--good); opacity: 0.65; }
.cal-item .t { font-variant-numeric: tabular-nums; color: var(--ink-muted); }

/* ── The team tree ─────────────────────────────────────────────────────── */

/* Native <details>, so it opens and closes with scripting off and announces
   itself as a disclosure widget without a line of ARIA. */

.tree { border: 1px solid var(--rule); border-radius: var(--radius); background: var(--paper-raised); overflow: hidden; }

.tree-dept { border-bottom: 1px solid var(--rule); }
.tree-dept:last-child { border-bottom: none; }

.tree summary {
  display: flex;
  align-items: baseline;
  gap: 10px;
  padding: 11px 14px;
  cursor: pointer;
  list-style: none;
  transition: background-color var(--duration-fast) var(--ease-out);
}
.tree summary::-webkit-details-marker { display: none; }
.tree summary:hover { background: var(--paper-sunken); transition-duration: var(--duration-quick); }

/* The triangle is drawn here rather than inherited from the browser, because
   the native marker differs per engine and cannot be animated. */
.tree summary::before {
  content: '';
  flex: 0 0 auto;
  width: 0; height: 0;
  border-left: 5px solid var(--ink-muted);
  border-top: 4px solid transparent;
  border-bottom: 4px solid transparent;
  transform-origin: 25% 50%;
  transition: transform var(--duration-fast) var(--ease-smooth-out);
}
.tree details[open] > summary::before { transform: rotate(90deg); }

.tree-dept > summary {
  background: var(--paper-sunken);
  font-family: var(--display);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.tree-person > summary { padding-left: 32px; }
.tree-leaf { display: flex; align-items: baseline; gap: 10px; padding: 9px 14px 9px 45px; }

.tree-name { font-weight: 500; }
.tree-people { margin-left: auto; font-size: 12px; color: var(--ink-muted); white-space: nowrap; }
.tree-idle { font-size: 12px; color: var(--ink-muted); }

.tree-counts { display: flex; flex-wrap: wrap; gap: 0 9px; font-size: 12px; color: var(--ink-muted); font-variant-numeric: tabular-nums; }
.tree-n.is-late { color: var(--late); font-weight: 600; }
.tree-n.is-soon { color: var(--soon); }
.tree-n.is-review { color: var(--accent); }

/* Inside a branch the task list is already framed by the tree. */
.tree-person .tasks { border: none; border-radius: 0; background: transparent; }
.tree-person .task { padding-left: 45px; }
.tree-person .task::before { left: 32px; }

/* Smooth disclosure, wherever the browser can do it without JavaScript.
   `::details-content` with `interpolate-size` animates a native <details> from
   nothing to its own height — no measuring, no wrapper element, and no change
   whatsoever in browsers that lack it. Durations come from the shared motion
   scale, so a branch opens on the same beat as everything else on the site. */
@supports (interpolate-size: allow-keywords) and selector(details::details-content) {
  :root { interpolate-size: allow-keywords; }

  .tree details::details-content,
  .vtree details::details-content {
    height: 0;
    overflow: hidden;
    opacity: 0;
    filter: blur(var(--blur-small));
    transition:
      height var(--duration-fast) var(--ease-smooth-out),
      content-visibility var(--duration-fast) var(--ease-smooth-out),
      opacity var(--duration-fast) var(--ease-smooth-out),
      filter var(--duration-fast) var(--ease-smooth-out);
    transition-behavior: allow-discrete;
  }
  .tree details[open]::details-content,
  .vtree details[open]::details-content { height: auto; opacity: 1; filter: blur(0); }
}

/* ── The detached window ───────────────────────────────────────────────── */

/* A window a manager parks on a second screen is a different object from a
   page they browse: no navigation, no language switch, no page furniture —
   a title strip, the counts, when it last refreshed, and the tree. */

.win { display: flex; flex-direction: column; height: calc(100vh - 3px); background: var(--paper); }

.win-bar {
  flex: 0 0 auto;
  display: flex;
  align-items: baseline;
  gap: 10px;
  padding: 10px 14px;
  border-bottom: 1px solid var(--rule);
  background: var(--paper-sunken);
}
.win-title { font-family: var(--display); font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.08em; }
.win-counts { font-size: 12px; color: var(--ink-muted); font-variant-numeric: tabular-nums; }
.win-stamp {
  margin-left: auto;
  font-size: 11px;
  color: var(--ink-muted);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  transition: color var(--duration-fast) var(--ease-out);
}
/* A poll that failed. The tree on screen is still true, just older than it
   looks, so it stays put and only the stamp says so. */
.win-stamp.is-stale { color: var(--late); }

.win-btn {
  flex: 0 0 auto;
  font: inherit;
  font-size: 11px;
  padding: 4px 9px;
  color: var(--ink-soft);
  background: var(--paper-raised);
  border: 1px solid var(--edge);
  border-radius: var(--radius);
  cursor: pointer;
  transition: background-color var(--duration-fast) var(--ease-out);
}
.win-btn:hover { background: var(--paper-sunken); transition-duration: var(--duration-quick); }

.win-body { flex: 1 1 auto; overflow-y: auto; overscroll-behavior: contain; padding: 12px; }
/* In a window the tree is the entire content and needs no frame of its own. */
.win-body .tree { border: none; border-radius: 0; }
.win-body .notice { margin: 0 0 10px; }

/* The refresh swap. Most of the tree is unchanged between polls, so it resolves
   back in from a soft blur rather than flashing from nothing. */
#tree-root.is-fresh { animation: tree-in var(--duration-slow) var(--ease-in-out) both; }
@keyframes tree-in {
  from { opacity: 0.4; filter: blur(var(--blur-small)); }
  to { opacity: 1; filter: none; }
}

/* ── The branching view ────────────────────────────────────────────────── */

/* A visibly-a-choice segmented control, not two loose links: this is the one
   toggle on the page that changes what the whole page looks like. */
.view-switch {
  display: inline-flex;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  overflow: hidden;
}
.view-switch a {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 6px 12px;
  font-size: 13px;
  color: var(--ink-muted);
  background: var(--paper-raised);
  transition:
    background-color var(--duration-fast) var(--ease-out),
    color var(--duration-fast) var(--ease-out);
}
.view-switch a:not(:last-child) { border-right: 1px solid var(--rule); }
.view-switch a:hover { color: var(--ink); text-decoration: none; }
.view-switch a.on { color: var(--ink); background: var(--accent-soft, var(--paper-sunken)); font-weight: 500; }

/* The same three levels drawn as an actual tree. Each item paints its own elbow
   and, unless it is the last of its siblings, the length of trunk below it —
   so nothing is masked with a background colour and the lines survive both
   themes, any hover, and a collapsed branch. */

.vtree, .vtree ul { list-style: none; margin: 0; padding: 0; }
.vtree {
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--paper-raised);
  padding: 10px 14px 14px;
}

/* Each level steps in and gets visibly quieter — the "pyramid" reads from
   sheer width and weight before anyone notices the guide lines at all. */
.vtree > li { --depth: 0; }
.vtree ul { padding-left: 19px; }
.vtree ul > li { position: relative; padding-left: 19px; --depth: calc(var(--depth, 0) + 1); }
.vtree ul > li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0;
  width: 13px;
  height: 17px;
  border-left: 1.5px solid var(--rule-strong);
  border-bottom: 1.5px solid var(--rule-strong);
  border-bottom-left-radius: 5px;
}
.vtree ul > li:not(:last-child)::after {
  content: '';
  position: absolute;
  left: 0;
  top: 17px;
  bottom: 0;
  border-left: 1.5px solid var(--rule-strong);
}

/* The row highlights edge-to-edge on hover, not just the text — the negative
   margin lets it bleed past the item's own padding so it reads as a lit row
   rather than a lit label. */
.vtree summary, .twig {
  border-radius: var(--radius);
  margin: 0 -8px;
  padding: 5px 8px;
}
.vtree summary {
  display: flex;
  align-items: baseline;
  gap: 9px;
  cursor: pointer;
  list-style: none;
  transition: background-color var(--duration-quick) var(--ease-out);
}
.vtree summary:hover, .twig:hover { background: var(--paper-sunken); }
.vtree summary::-webkit-details-marker { display: none; }
.vtree summary::before {
  content: '';
  flex: 0 0 auto;
  width: 0; height: 0;
  border-left: 5px solid var(--ink-muted);
  border-top: 4px solid transparent;
  border-bottom: 4px solid transparent;
  transform-origin: 25% 50%;
  transition: transform var(--duration-fast) var(--ease-smooth-out);
}
.vtree details[open] > summary::before { transform: rotate(90deg); }
.vtree summary:hover .node-name { color: var(--accent); }

.node-name { font-weight: 500; font-size: 13.5px; }
.node-name.is-dept {
  font-family: var(--display);
  font-size: 13px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.07em;
}
/* One rule under each department's own row — never under its children —
   marking where one branch of the pyramid ends and the next begins. */
.vtree > li:not(:last-child) > details > summary {
  border-bottom: 1px solid var(--rule);
  border-radius: var(--radius) var(--radius) 0 0;
  margin-bottom: 6px;
  padding-bottom: 9px;
}

.twig {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  transition: background-color var(--duration-quick) var(--ease-out);
}
.twig.is-quiet { color: var(--ink-muted); font-size: 13.5px; }
.twig-title { color: var(--ink); overflow-wrap: anywhere; font-size: 13px; }
.twig-title:hover { color: var(--accent); }
.twig-side { display: flex; align-items: center; gap: 10px; flex: 0 0 auto; }

/* ── One task ──────────────────────────────────────────────────────────── */

/* No rules, no boxes — the labels are small caps and the values are not, which
   is enough separation without drawing a table around eight short facts. */
.facts { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 16px 22px; margin: 0; }
.fact dt {
  font-family: var(--display);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--ink-muted);
}
.fact dd { margin: 4px 0 0; font-size: 14px; }

.prose { font-size: 15px; line-height: 1.6; max-width: 70ch; overflow-wrap: anywhere; }

.log { border-left: 2px solid var(--rule); padding-left: 14px; }
.log-line { font-size: 13px; color: var(--ink-soft); padding: 3px 0; font-variant-numeric: tabular-nums; }

/* ── The activity feed ────────────────────────────────────────── */

.filters { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-bottom: 22px; }
.filters select { width: auto; min-width: 150px; }

.feed-day { margin-bottom: 26px; }
.feed-date {
  display: flex;
  align-items: baseline;
  gap: 9px;
  font-family: var(--display);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--ink-muted);
  padding-bottom: 6px;
  margin: 0 0 4px;
  border-bottom: 1px solid var(--rule);
}
.feed-count { font-family: var(--mono); font-size: 11px; letter-spacing: 0; }

.feed-list { list-style: none; margin: 0; padding: 0; }

/* A five-column grid rather than a table: the columns line up down the page,
   and on a phone the whole thing folds into two readable lines. */
.feed-item {
  display: grid;
  grid-template-columns: 3.4em 11em auto 1fr auto;
  align-items: baseline;
  gap: 0 12px;
  padding: 6px 0;
  border-bottom: 1px solid var(--rule);
  font-size: 14px;
}
.feed-item:last-child { border-bottom: none; }
.feed-time { font-variant-numeric: tabular-nums; color: var(--ink-muted); font-size: 13px; }
.feed-who { font-weight: 500; overflow-wrap: anywhere; }
.feed-verb { color: var(--ink-muted); font-size: 13px; white-space: nowrap; }
.feed-verb.is-review { color: var(--accent); }
.feed-verb.is-good { color: var(--good); }
.feed-task { color: var(--ink); overflow-wrap: anywhere; }
.feed-task:hover { color: var(--accent); }
.feed-code { color: var(--ink-muted); font-size: 12px; white-space: nowrap; }

/* ── Notices ───────────────────────────────────────────────────────────── */

.notice { padding: 11px 14px; border: 1px solid var(--rule-strong); border-left-width: 3px; border-radius: var(--radius); background: var(--paper-raised); margin-bottom: 16px; font-size: 14px; }
.notice.alert { border-left-color: var(--late); background: var(--late-wash); }
.notice.warn { border-left-color: var(--soon); background: var(--soon-wash); }
.notice.ok { border-left-color: var(--good); background: var(--good-wash); }
.notice.info { border-left-color: var(--accent); background: var(--accent-wash); }

/* Only the notice that just appeared because of something you did animates in.
   A standing explanatory notice is part of the page and should already be
   there when the page arrives. */
.notice.flash { animation: notice-in var(--duration-slow) var(--ease-smooth-out) both; }
@keyframes notice-in {
  from { opacity: 0; transform: translateY(calc(var(--distance-medium) * -1)); filter: blur(var(--blur-small)); }
  to { opacity: 1; transform: none; filter: none; }
}

.empty { padding: 40px 20px; text-align: center; color: var(--ink-muted); border: 1px dashed var(--rule-strong); border-radius: var(--radius); }

/* ── Login ─────────────────────────────────────────────────────────────── */

.login { min-height: calc(100vh - 3px); display: flex; align-items: center; justify-content: center; padding: 24px; }
.login-card { width: 100%; max-width: 420px; background: var(--paper-raised); border: 1px solid var(--rule); border-radius: var(--radius); padding: 34px 32px; }
.login-card .brand-mark { width: 34px; height: 4px; margin-bottom: 14px; }
.login-card h1 { margin-bottom: 6px; letter-spacing: 0.06em; font-weight: 700; }
.login-widget { margin: 24px 0 8px; min-height: 44px; }

/* ── Reduced motion ────────────────────────────────────────────────────── */

/* Vestibular disorders are common enough that this is not a nicety. Everything
   above degrades to an instant state change, which is exactly how the site
   behaved before any of it was added. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* ── Print: the calendar goes on a wall ────────────────────────────────── */

@media print {
  .nav, .topbar .langs, .btn, .skip, .no-print { display: none !important; }
  body { background: #fff; font-size: 11pt; border-top: none; }
  .content { padding: 0; max-width: none; }
  .cal-day { min-height: 90px; }
  a { color: inherit; text-decoration: none; }
}

/* ── Narrow screens ────────────────────────────────────────────────────── */

/* The whole tool has to work from a phone — half these people never sit at a
   desk. Two breakpoints: 900px turns the side rail into a scrolling top bar,
   640px turns every side-by-side pairing into stacked blocks. */

@media (max-width: 900px) {
  .shell { display: block; }
  .nav {
    width: auto;
    flex: none;
    border-right: none;
    border-bottom: 1px solid var(--rule);
    padding: 8px 0;
    flex-direction: row;
    flex-wrap: nowrap;
    align-items: center;
    gap: 2px;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  .nav::-webkit-scrollbar { display: none; }
  .brand, .nav-group-title { display: none; }
  .nav-group { display: contents; }
  .nav a { border-left: none; border-bottom: 2px solid transparent; padding: 9px 12px; white-space: nowrap; }
  .nav a.active { border-left: none; border-bottom-color: var(--accent); }

  /* This block used to be `display: none` here, and it is the only place the
     sign-out link exists — so nobody could sign out from a phone. It now rides
     along at the end of the scrolling bar. */
  .nav-foot {
    margin: 0 0 0 auto;
    padding: 0 14px 0 16px;
    border-top: none;
    border-left: 1px solid var(--rule);
    display: flex;
    align-items: center;
    gap: 12px;
    white-space: nowrap;
  }
  .nav-foot > div { margin: 0 !important; }
  .nav-foot .muted { display: none; }

  .topbar { flex-wrap: wrap; padding: 16px 16px 12px; }
  .content { padding: 18px 16px 56px; }
  .grid-3, .grid-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .cal { grid-template-columns: 1fr; }
  .cal-head { display: none; }
  .cal-day { min-height: 0; }
  .cal-day:empty { display: none; }
  .cal-item { padding: 8px 9px; font-size: 13px; }
}

@media (max-width: 640px) {
  .grid-3, .grid-4, .grid-2 { grid-template-columns: 1fr; }

  /* A task stops being a row and becomes two stacked blocks: what it is, then
     when it is due and what you can do about it. */
  .task { flex-direction: column; align-items: stretch; gap: 10px; }
  .task-aside { width: 100%; justify-content: space-between; }

  /* Thumbs, not cursors. */
  .btn { padding: 10px 15px; }
  .btn-sm { padding: 8px 12px; font-size: 13px; }
  .nav a { padding: 10px 13px; }

  /* On a 360px screen the tree's indentation was eating a third of the width. */
  .tree-person > summary { padding-left: 26px; }
  .tree-leaf { padding-left: 34px; }
  .tree-person .task { padding-left: 30px; }
  .tree-person .task::before { left: 18px; }
  .tree-people { display: none; }

  .vtree { padding: 8px 10px 12px; }
  .vtree ul { padding-left: 12px; }
  .vtree ul > li { padding-left: 14px; }
  .twig { flex-direction: column; align-items: stretch; gap: 5px; padding: 6px 0; }
  .twig-side { justify-content: space-between; }

  /* Time and who on the first line, verb and task on the second. */
  .feed-item { grid-template-columns: 3.4em 1fr auto; padding: 8px 0; }
  .feed-task { grid-column: 1 / -1; padding-left: calc(3.4em + 12px); }
  .feed-code { display: none; }
  .filters select { min-width: 0; flex: 1 1 130px; }

  .facts { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px 16px; }
  .section-head { flex-wrap: wrap; }
  .topbar h1 { font-size: 22px; }
  .login-card { padding: 26px 20px; }
}
