/*
 * Every style in the panel.
 *
 * Every class is prefixed `p-`, and that is a requirement rather than a convention:
 * assets/floor-1.svg is inlined into this document, so its seven class names (.wall,
 * .desk, .chair, .window, .door, .room-label, .desk-label) and its fifteen desk ids
 * become document-global. Rewriting the plan's own stylesheet to scope it is exactly the
 * clever thing that breaks when spec §4's real plan arrives, so the panel gets out of its
 * way instead. (The previous version of this comment named five classes that do not
 * exist and twenty-four desk ids there have never been; both were inherited from a plan
 * that was replaced.)
 *
 * The desk fills are NOT set here. They are inline styles written by floor-plan.js,
 * because stage 9's heatmap is a continuous ramp that no fixed class set can express.
 * `[data-state]` is published alongside them and is what the legend swatches use — and
 * what the plan uses to dash a released desk's stroke, so the five states survive being
 * printed, dimmed, or read by somebody colour-blind.
 *
 * **The palette is the product's icon** (`assets/biurek_icon.png`, a sleeping dog on an
 * orange desk): cream ground, dark-brown ink, amber accent, fur brown. Two rules keep it
 * honest and both were checked numerically rather than by eye:
 *
 *   - Amber is a FILL, never a text colour. `#F1800A` on cream is 2.45:1 — nowhere near
 *     readable — so text that must look accented uses `--p-accent` (#B35400, 4.58:1) and
 *     the amber survives as backgrounds, focus rings and the nav underline.
 *   - Every desk fill carries the ink at 5:1 or better, because the plan writes the desk
 *     id ON the fill.
 */

:root {
  /* Ink ------------------------------------------------------------------- */
  --p-ink: #3d1e12;          /* 13.8:1 on the ground */
  --p-dim: #7a5a46;          /*  5.7:1 — secondary text, still AA        */
  --p-line: #e8d5be;
  --p-line-strong: #d9bf9f;

  /* Ground ---------------------------------------------------------------- */
  --p-bg: #fff3e3;           /* the icon's own background, 73% of its pixels */
  --p-panel: #fffdf8;
  --p-sunk: #fbf0df;

  /* Accent ---------------------------------------------------------------- */
  --p-accent: #b35400;       /* 4.6:1 — the readable amber, for text and borders */
  --p-amber: #f1800a;        /* the icon's desk, for fills and focus rings       */
  --p-amber-soft: #fde3c2;
  --p-warn: #a3341f;
  --p-warn-bg: #fdece6;
  --p-ok: #4f7a34;

  /* Desk states — MUST stay in step with web/desk-state.js and with the MCP
     bundle's copy in src/adapters/mcp/app.py. tests/test_mcp_app.py asserts the
     bundle matches desk-state.js; these three are the same five values again,
     because the legend swatches are CSS and the plan fills are inline styles. */
  --p-free: #fbeedc;
  --p-booked: #f5a93f;
  --p-blocked: #b9afa8;
  --p-fixed: #c08a62;
  --p-released: #f0d5a4;

  /* Heatmap ramp (stage 9). Seven stops, cream → amber → deep brown. The label
     colour flips to the panel ground past --p-heat-4, which analytics.js decides
     by luminance rather than by hard-coding an index. */
  --p-heat-0: #fff7ec;
  --p-heat-1: #fbe3be;
  --p-heat-2: #f5c070;
  --p-heat-3: #ee9a2e;
  --p-heat-4: #d6720b;
  --p-heat-5: #a8500b;
  --p-heat-6: #6b3410;

  /* Scale ----------------------------------------------------------------- */
  --p-s1: 4px;
  --p-s2: 8px;
  --p-s3: 12px;
  --p-s4: 16px;
  --p-s5: 24px;
  --p-s6: 32px;
  --p-r1: 6px;
  --p-r2: 10px;
  --p-r3: 16px;
  --p-shadow: 0 1px 2px rgba(61, 30, 18, 0.06), 0 6px 18px rgba(61, 30, 18, 0.06);
  --p-shadow-lift: 0 8px 30px rgba(61, 30, 18, 0.16);
  --p-font: system-ui, -apple-system, "Segoe UI", sans-serif;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  font: 15px/1.55 var(--p-font);
  color: var(--p-ink);
  background: var(--p-bg);
  /* The plan is inlined into this document and carries no background of its own; without
     this the browser paints the canvas white behind the cream and the seam shows on a
     short page. */
  min-height: 100vh;
}

/* One focus treatment for the whole panel. There was none at all before, which on a
   keyboard made the nav, every action button and every disabled-with-a-reason control
   indistinguishable from each other. */
:focus-visible {
  outline: 3px solid var(--p-amber);
  outline-offset: 2px;
  border-radius: var(--p-r1);
}

/* Header ------------------------------------------------------------------- */

.p-header {
  display: flex;
  align-items: center;
  gap: var(--p-s4);
  /* flex-wrap is load-bearing on a phone: brand + five nav links + name + button is far
     wider than 390px, and without it the whole DOCUMENT scrolled sideways rather than
     the header wrapping. */
  flex-wrap: wrap;
  padding: var(--p-s3) var(--p-s5);
  background: var(--p-panel);
  border-bottom: 1px solid var(--p-line);
}

.p-brand {
  display: flex;
  align-items: center;
  gap: var(--p-s2);
  font-weight: 650;
  letter-spacing: -0.01em;
  white-space: nowrap;
}
/* The icon, published beside the panel by Terraform's extra_files rather than copied
   into web/ — one committed file, exactly as floor-1.svg is handled. */
.p-brand img {
  width: 30px;
  height: 30px;
  border-radius: var(--p-s2);
  display: block;
}

.p-nav {
  display: flex;
  flex-wrap: wrap;
  gap: var(--p-s1) var(--p-s4);
  flex: 1;
  min-width: 0;
}
.p-nav-link {
  color: var(--p-dim);
  text-decoration: none;
  padding: var(--p-s1) 2px;
  border-bottom: 2px solid transparent;
  white-space: nowrap;
}
.p-nav-link:hover { color: var(--p-ink); }
.p-nav-current { color: var(--p-accent); border-bottom-color: var(--p-amber); font-weight: 600; }

.p-whoami { display: flex; align-items: center; gap: var(--p-s2); flex-wrap: wrap; }

/* On a phone the three parts stack instead of competing for one row: brand, then the
   nav as a scrollable strip, then who you are. `flex: 1` on .p-nav is what pushed the
   links into a tall column beside the brand, so it is released here. */
@media (max-width: 720px) {
  .p-header { gap: var(--p-s3); padding: var(--p-s3) var(--p-s4); }
  .p-brand,
  .p-nav,
  .p-whoami { flex: 0 0 100%; }
  .p-nav { overflow-x: auto; flex-wrap: nowrap; gap: var(--p-s3); padding-bottom: 2px; }
  .p-main { padding: var(--p-s4); }
}

/* Layout ------------------------------------------------------------------- */

.p-main { max-width: 1240px; margin: 0 auto; padding: var(--p-s5); }
.p-title { font-size: 25px; line-height: 1.2; letter-spacing: -0.02em; margin: 0 0 var(--p-s1); }
.p-lede { color: var(--p-dim); margin: 0 0 var(--p-s4); max-width: 62ch; }
.p-note { color: var(--p-dim); font-size: 13.5px; margin: var(--p-s2) 0; max-width: 78ch; }
.p-warn {
  color: var(--p-warn);
  background: var(--p-warn-bg);
  border: 1px solid #f2cdc1;
  border-left: 3px solid var(--p-warn);
  padding: var(--p-s3) var(--p-s4);
  border-radius: var(--p-r1);
}
.p-dim { color: var(--p-dim); font-weight: 400; }

.p-head {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--p-s3) var(--p-s4);
  margin-bottom: var(--p-s5);
}
.p-head .p-title { margin-bottom: 0; }

.p-section {
  /* A section that holds a table IS the table's scroll box. Without this a wide table
     inside one pushes the whole document sideways on a phone instead of scrolling in
     place — which is what four of the six screens did until it was measured. */
  overflow-x: auto;
  background: var(--p-panel);
  border: 1px solid var(--p-line);
  border-radius: var(--p-r2);
  padding: var(--p-s4) var(--p-s5);
  margin-bottom: var(--p-s4);
  box-shadow: var(--p-shadow);
}
.p-section h2 { font-size: 16px; margin: 0 0 var(--p-s3); letter-spacing: -0.01em; }

/* Day screen --------------------------------------------------------------- */

/* The plan leads. It used to be the NARROW column (5fr against the table's 7fr), which
   put the one artefact worth looking at in the corner and gave the wall of buttons the
   space — the single loudest thing wrong with the old layout. */
.p-day { display: grid; grid-template-columns: minmax(0, 7fr) minmax(300px, 5fr); gap: var(--p-s5); align-items: start; }
@media (max-width: 1000px) { .p-day { grid-template-columns: 1fr; } }

.p-plan {
  background: var(--p-panel);
  border: 1px solid var(--p-line);
  border-radius: var(--p-r2);
  padding: var(--p-s4);
  box-shadow: var(--p-shadow);
}

/* Sticky ONLY inside the day screen's two-column grid, where the plan stays on screen
   while the desk list scrolls beside it — losing the picture at row four undoes the
   point. The same rule on a full-width section (the desks screen's preview, the
   analytics heatmap) would pin a tall block over everything under it. */
.p-day .p-plan { position: sticky; top: var(--p-s4); }
@media (max-width: 1000px) { .p-day .p-plan { position: static; } }

/* The desks screen shows the plan to orient somebody, not to be worked in, so it is
   capped rather than filling 1240px of section. */
.p-plan-compact { max-width: 620px; margin-inline: auto; }

.p-plan svg { width: 100%; height: auto; display: block; }
.p-plan .desk { transition: opacity 120ms ease; cursor: pointer; }
.p-plan .desk:hover { opacity: 0.82; }
.p-plan .p-selected { stroke: var(--p-amber); stroke-width: 4; }
/* Colour is not the only channel — `booked` and `blocked` are 1.09:1 apart in
   luminance, so they are near-identical in greyscale and to a deuteranope. The dashes
   that separate them are NOT here: they live in assets/floor-1.svg's own <style>,
   because the SVG travels into the MCP App bundle where this file does not exist, and
   one copy that reaches both surfaces beats two that drift. The legend swatches below
   mirror them in border-style, which is the one place CSS has to say it twice. */

.p-legend { display: flex; flex-wrap: wrap; gap: var(--p-s3) var(--p-s4); margin-top: var(--p-s4); color: var(--p-dim); font-size: 13px; }
.p-legend-item { display: flex; align-items: center; gap: var(--p-s2); }
.p-swatch {
  width: 15px;
  height: 15px;
  border-radius: var(--p-s1);
  border: 1.5px solid var(--p-ink);
  display: inline-block;
  flex: none;
}
.p-swatch[data-state="free"] { background: var(--p-free); }
.p-swatch[data-state="booked"] { background: var(--p-booked); }
.p-swatch[data-state="blocked"] { background: var(--p-blocked); border-style: dotted; }
.p-swatch[data-state="fixed"] { background: var(--p-fixed); }
.p-swatch[data-state="released"] { background: var(--p-released); border-style: dashed; }

/* Tables ------------------------------------------------------------------- */

/* Every table lives in one of these. Three of the four screens had no wrapper, so on a
   phone the table pushed the document sideways instead of scrolling inside its own box. */
.p-table-box {
  overflow-x: auto;
  background: var(--p-panel);
  border: 1px solid var(--p-line);
  border-radius: var(--p-r2);
  box-shadow: var(--p-shadow);
}
.p-table { width: 100%; border-collapse: collapse; }
.p-table th,
.p-table td { text-align: left; padding: var(--p-s3) var(--p-s4); border-bottom: 1px solid var(--p-line); vertical-align: middle; }
.p-table th {
  font-size: 11.5px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--p-dim);
  background: var(--p-sunk);
  font-weight: 650;
  white-space: nowrap;
  position: sticky;
  top: 0;
  z-index: 1;
}
.p-table tbody tr:last-child td { border-bottom: none; }
.p-table tbody tr:hover { background: var(--p-sunk); }
.p-table tr[data-state="blocked"] { background: #f4efe8; }
.p-table tr[data-state="blocked"]:hover { background: #efe8df; }

/* A dot of the desk's own colour in front of its label, so a row and the plan agree
   without the reader translating a word back into a colour. */
.p-dot {
  width: 11px;
  height: 11px;
  border-radius: 3px;
  border: 1.5px solid var(--p-ink);
  display: inline-block;
  margin-right: var(--p-s2);
  flex: none;
}
.p-dot[data-state="free"] { background: var(--p-free); }
.p-dot[data-state="booked"] { background: var(--p-booked); }
.p-dot[data-state="blocked"] { background: var(--p-blocked); }
.p-dot[data-state="fixed"] { background: var(--p-fixed); }
.p-dot[data-state="released"] { background: var(--p-released); }

.p-checkin { color: var(--p-dim); font-size: 13px; }
.p-actions { display: flex; gap: var(--p-s2); flex-wrap: wrap; }

/* The day table lives in the narrower half of a two-column screen, so it gets tighter
   rules than the full-width tables on the other screens. A desk id that wraps reads as
   two desks ("Z-" / "01"), and an actions column laid out in a row pushes the last
   button past the right edge of its own scroll box. */
.p-day .p-table th,
.p-day .p-table td { padding: var(--p-s2) var(--p-s3); }
.p-day .p-table td:first-child { white-space: nowrap; }
.p-day .p-actions { flex-direction: column; align-items: stretch; }
.p-day .p-actions .p-button { width: 100%; }

/* `max-content` on the label column is what makes a long Polish label refuse to wrap
   and widen the page past the viewport. Below the fold it stacks instead. */
.p-dl { display: grid; grid-template-columns: max-content 1fr; gap: var(--p-s2) var(--p-s5); margin: 0; }
@media (max-width: 560px) {
  .p-dl { grid-template-columns: 1fr; gap: 2px var(--p-s3); }
  .p-dl dd { margin-bottom: var(--p-s2); }
}
.p-dl dt { color: var(--p-dim); }
.p-dl dd { margin: 0; font-variant-numeric: tabular-nums; }

/* An archive nobody needs open: native <details>, so there is no state to hold and no
   toggle to write. Used for the expired half of the block register, which D17 keeps for
   the analytics denominator and which would otherwise bury the two entries that matter. */
.p-details {
  border: 1px solid var(--p-line);
  border-radius: var(--p-r2);
  background: var(--p-sunk);
  padding: var(--p-s3) var(--p-s4);
  margin-top: var(--p-s4);
}
.p-details > summary {
  cursor: pointer;
  font-weight: 600;
  font-size: 13.5px;
  color: var(--p-dim);
  list-style-position: inside;
}
.p-details > summary:hover { color: var(--p-ink); }
.p-details[open] > summary { margin-bottom: var(--p-s3); }
.p-details .p-table-box { box-shadow: none; }

/* Controls ----------------------------------------------------------------- */

.p-button {
  font: inherit;
  font-weight: 550;
  padding: var(--p-s2) var(--p-s4);
  border: 1px solid var(--p-line-strong);
  border-radius: var(--p-r1);
  background: var(--p-panel);
  color: var(--p-ink);
  cursor: pointer;
  white-space: nowrap;
  transition: background 120ms ease, border-color 120ms ease, color 120ms ease;
}
.p-button:hover:not(:disabled) { border-color: var(--p-accent); color: var(--p-accent); background: var(--p-amber-soft); }
.p-button:disabled { opacity: 0.45; cursor: not-allowed; }

/* The one primary action per form. Amber as a FILL with ink on top is 5.6:1; amber as
   text would have been 2.5:1, which is why the accent token exists separately. */
.p-primary { background: var(--p-amber); border-color: var(--p-accent); color: var(--p-ink); }
.p-primary:hover:not(:disabled) { background: var(--p-accent); color: var(--p-panel); border-color: var(--p-accent); }

/* Destructive, and it says so before it is pressed rather than only in the confirm. */
.p-danger { color: var(--p-warn); border-color: #e8c3b8; }
.p-danger:hover:not(:disabled) { background: var(--p-warn); border-color: var(--p-warn); color: var(--p-panel); }

.p-small { padding: var(--p-s1) var(--p-s3); font-size: 13px; }

.p-input,
.p-select {
  font: inherit;
  padding: var(--p-s2) var(--p-s3);
  border: 1px solid var(--p-line-strong);
  border-radius: var(--p-r1);
  background: var(--p-panel);
  color: var(--p-ink);
  max-width: 100%;
}
.p-input:hover, .p-select:hover { border-color: var(--p-accent); }
.p-date { width: auto; font-variant-numeric: tabular-nums; }
.p-label { display: block; color: var(--p-dim); font-size: 12.5px; font-weight: 600; margin-bottom: var(--p-s1); }
.p-form { display: flex; flex-direction: column; gap: var(--p-s2); max-width: 340px; }
.p-grid-form { display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--p-s3); margin-bottom: var(--p-s4); }
.p-field { display: flex; flex-direction: column; gap: var(--p-s1); }
.p-field .p-input,
.p-field .p-select { min-width: 168px; }
.p-field > .p-button { margin-top: var(--p-s1); }
.p-check { width: 18px; height: 18px; accent-color: var(--p-amber); }

/* Dialog ------------------------------------------------------------------- */

/* Replaces ten native prompt()/confirm() calls, including a three-step chained prompt
   for lending a fixed desk back to the pool. `<dialog>` is native, so this costs no
   dependency and no build step, and ::backdrop is the one way to dim the page without
   a second element the screens would have to remember to remove. */
.p-dialog {
  border: 1px solid var(--p-line);
  border-radius: var(--p-r3);
  padding: 0;
  background: var(--p-panel);
  color: var(--p-ink);
  box-shadow: var(--p-shadow-lift);
  width: min(460px, calc(100vw - 2 * var(--p-s5)));
}
.p-dialog::backdrop { background: rgba(61, 30, 18, 0.34); }
.p-dialog-body { padding: var(--p-s5); display: flex; flex-direction: column; gap: var(--p-s3); }
.p-dialog-title { font-size: 18px; margin: 0; letter-spacing: -0.01em; }
.p-dialog-text { margin: 0; color: var(--p-dim); white-space: pre-line; }
.p-dialog-foot {
  display: flex;
  justify-content: flex-end;
  gap: var(--p-s2);
  padding: var(--p-s3) var(--p-s5);
  border-top: 1px solid var(--p-line);
  background: var(--p-sunk);
  border-radius: 0 0 var(--p-r3) var(--p-r3);
  flex-wrap: wrap;
}

/* Login picker ------------------------------------------------------------- */

/* The header is hidden until an identity is picked, so the sign-in screen carries the
   brand on its own. */
.p-signin { display: flex; align-items: center; gap: var(--p-s4); flex-wrap: wrap; }
.p-signin img { border-radius: var(--p-r3); display: block; }
.p-signin .p-lede { margin-bottom: 0; }

.p-picker { display: flex; flex-wrap: wrap; gap: var(--p-s3); margin-top: var(--p-s5); }
.p-card {
  font: inherit;
  text-align: left;
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 232px;
  padding: var(--p-s4);
  border: 1px solid var(--p-line);
  border-radius: var(--p-r2);
  background: var(--p-panel);
  cursor: pointer;
  box-shadow: var(--p-shadow);
  transition: border-color 120ms ease, transform 120ms ease;
}
.p-card:hover { border-color: var(--p-accent); transform: translateY(-1px); }
.p-card-name { font-weight: 650; }
.p-card-meta,
.p-card-stub { color: var(--p-dim); font-size: 13px; }
.p-card-stub { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; }
.p-card-inactive { opacity: 0.72; }
.p-badge {
  display: inline-block;
  margin-top: var(--p-s2);
  font-size: 12px;
  color: var(--p-warn);
  background: var(--p-warn-bg);
  border-radius: var(--p-s1);
  padding: 1px var(--p-s2);
  width: max-content;
}

/* Empty and loading states -------------------------------------------------- */

/* There was no loading affordance anywhere in the panel: app.js clears main and then
   awaits, so every navigation showed a blank page for the length of the call. */
.p-loading { display: flex; flex-direction: column; gap: var(--p-s3); padding: var(--p-s5) 0; }
.p-skeleton {
  height: 14px;
  border-radius: var(--p-r1);
  background: linear-gradient(90deg, var(--p-sunk), var(--p-amber-soft), var(--p-sunk));
  background-size: 220% 100%;
  animation: p-shimmer 1.25s ease-in-out infinite;
}
.p-skeleton:nth-child(2) { width: 82%; }
.p-skeleton:nth-child(3) { width: 64%; }
@keyframes p-shimmer {
  from { background-position: 120% 0; }
  to { background-position: -20% 0; }
}
@media (prefers-reduced-motion: reduce) {
  .p-skeleton { animation: none; }
  .p-button, .p-card, .p-plan .desk { transition: none; }
}

.p-empty { text-align: center; color: var(--p-dim); padding: var(--p-s6) var(--p-s4); }
.p-empty img { width: 76px; height: 76px; opacity: 0.55; border-radius: var(--p-r3); }
.p-empty p { margin: var(--p-s3) 0 0; }

/* Analytics ---------------------------------------------------------------- */

.p-stats { display: flex; flex-wrap: wrap; gap: var(--p-s3); margin-bottom: var(--p-s4); }
.p-stat {
  flex: 1 1 180px;
  background: var(--p-panel);
  border: 1px solid var(--p-line);
  border-radius: var(--p-r2);
  padding: var(--p-s4);
  box-shadow: var(--p-shadow);
}
.p-stat-value { font-size: 27px; font-weight: 650; letter-spacing: -0.02em; font-variant-numeric: tabular-nums; }
.p-stat-label { color: var(--p-dim); font-size: 13px; margin-top: 2px; }
.p-stat-note { color: var(--p-dim); font-size: 12px; margin-top: var(--p-s2); }

/* The bar chart is hand-drawn SVG: the CSP forbids a charting library
   (`script-src 'self'`), and there is no build step to bundle one anyway. */
.p-chart { width: 100%; height: auto; display: block; overflow: visible; }
.p-chart-bar { fill: var(--p-amber); }
.p-chart-bar-soft { fill: var(--p-amber-soft); stroke: var(--p-line-strong); }
.p-chart-axis { stroke: var(--p-line-strong); stroke-width: 1; }
.p-chart-label { fill: var(--p-dim); font: 12px var(--p-font); text-anchor: middle; }
.p-chart-value { fill: var(--p-ink); font: 11px var(--p-font); text-anchor: middle; font-weight: 600; }

/* The heatmap legend is a continuous ramp, so it is a gradient and not swatches. */
.p-ramp { display: flex; align-items: center; gap: var(--p-s3); margin-top: var(--p-s4); color: var(--p-dim); font-size: 13px; flex-wrap: wrap; }
.p-ramp-bar {
  flex: 1 1 200px;
  height: 12px;
  border-radius: 999px;
  border: 1px solid var(--p-line-strong);
  background: linear-gradient(
    90deg,
    var(--p-heat-0), var(--p-heat-1), var(--p-heat-2), var(--p-heat-3),
    var(--p-heat-4), var(--p-heat-5), var(--p-heat-6)
  );
}

/* Toast -------------------------------------------------------------------- */

.p-toast {
  position: fixed;
  right: var(--p-s5);
  bottom: var(--p-s5);
  max-width: min(460px, calc(100vw - 2 * var(--p-s5)));
  padding: var(--p-s3) var(--p-s4);
  border-radius: var(--p-r2);
  background: var(--p-ink);
  color: #fff6ea;
  box-shadow: var(--p-shadow-lift);
  z-index: 10;
}
.p-toast-error { background: var(--p-warn); }

/* Load-bearing, and the only !important in the file: .p-header is display:flex and
   .p-toast is position:fixed, and both beat the user-agent's own [hidden] rule. app.js
   toggles each of them through the `hidden` property. */
[hidden] { display: none !important; }
