/* EnigmaTasks — shell + dashboard + task-page styles, OneBloc suite theme.
   Tokens (--acc, --ob-*, --of-* aliases) come from board.css :root, loaded first. */

/* ---------- scrollbars: macOS-style ----------
   board.css paints a solid #cbd5e1 bar on a 10px track, which reads as a hard grey rail down every
   scrolling panel. Restated here (tasks.css loads last) as a translucent overlay thumb on an
   invisible track, darkening on hover — the same behaviour macOS gives you.

   `background-clip: content-box` with a transparent border is what makes it look inset and slim:
   the border becomes breathing room the thumb doesn't paint into, so it floats off the edge rather
   than filling a gutter. Being translucent (rgba, not a fixed grey) also means one rule works on
   white panels, tinted board columns and the near-white page alike. */
::-webkit-scrollbar { width: 11px; height: 11px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
  background-color: rgba(16, 33, 80, .18);
  border-radius: 999px;
  border: 3px solid transparent;
  background-clip: content-box;
  transition: background-color .15s;
}
::-webkit-scrollbar-thumb:hover { background-color: rgba(16, 33, 80, .34); }
::-webkit-scrollbar-thumb:active { background-color: rgba(16, 33, 80, .45); }
::-webkit-scrollbar-corner { background: transparent; }
/* Firefox has no pseudo-elements for this; these two properties are the whole API. */
* { scrollbar-width: thin; scrollbar-color: rgba(16, 33, 80, .22) transparent; }

/* The file viewer is a dark overlay — a dark thumb on it is invisible, so invert there. */
.of-viewer ::-webkit-scrollbar-thumb { background-color: rgba(255, 255, 255, .26); }
.of-viewer ::-webkit-scrollbar-thumb:hover { background-color: rgba(255, 255, 255, .45); }
.of-viewer * { scrollbar-color: rgba(255, 255, 255, .3) transparent; }

/* The `hidden` attribute must actually hide things.
   The UA stylesheet says `[hidden] { display: none }`, but ANY author rule that sets `display`
   outranks it — so `.et-task { display: grid }` and `.et-handover { display: flex }` quietly made
   `el.hidden = true` a no-op. That is why the Overdue/Today/Week filter appeared to do nothing:
   the rows were correctly marked hidden and went on rendering anyway. */
[hidden] { display: none !important; }

.et-app { display: grid; grid-template-columns: 268px 1fr; min-height: 100vh; background: var(--ob-bg); }
/* A grid item defaults to `min-width: auto`, meaning it refuses to shrink below the widest thing
   inside it. One non-wrapping row — the board-jump rail on /mine — therefore inflated the whole
   1fr track to 1280px on a 375px screen: the page scrolled sideways and every block inside it was
   laid out three screens wide. `min-width: 0` lets the track obey the viewport and hands the
   overflow to the element that actually has it, which then scrolls on its own. */
.et-app > * { min-width: 0; }
.et-app :focus-visible { outline: 2px solid var(--acc); outline-offset: 2px; border-radius: 6px; }

/* ---------- rail (white OneBloc shell) ---------- */
.et-rail { background: var(--ob-card); border-right: 1px solid var(--ob-line); display: flex; flex-direction: column; padding: 20px 16px; gap: 4px; position: sticky; top: 0; height: 100vh; }
.et-brand { display: flex; align-items: center; gap: 11px; padding: 2px 8px 18px; }
/* The bloc is a flat vector mark — the kit forbids gloss, bevel, shadow and 3D extrusion, so no
   box-shadow here. The old .et-cube was a conic-gradient square pretending to be a cube; it wasn't
   the OneBloc mark at all.

   48px: the mark carries seams AND a glyph, and at 36px both were fighting for the same few pixels.
   The kit says drop them below ~24px — the opposite move is to give them room. Measured against the
   rail: 235px of brand row, 107px of wordmark, so this still leaves ~65px spare. */
.et-bloc { width: 48px; height: 48px; flex: none; display: block; }
/* Clear space is ¼ of the cube width per the kit — 12px at this size. */
.et-brand { gap: 12px; }
.et-nm { font-weight: 800; font-size: 15.5px; letter-spacing: -.3px; color: var(--ob-ink); }
.et-nm .one { color: #2B7FF0; } .et-nm .bloc { color: #15327C; }
.et-nm small { display: block; font-weight: 600; font-size: 10.5px; color: var(--ob-slate); }
.et-navlabel { font-size: 10.5px; font-weight: 700; letter-spacing: .7px; text-transform: uppercase; color: var(--ob-faint); padding: 14px 10px 7px; }
.et-nav { display: flex; flex-direction: column; gap: 2px; }
.et-nav a { display: flex; align-items: center; gap: 11px; padding: 9px 11px; border-radius: 10px; color: var(--ob-slate); text-decoration: none; font-size: 13.5px; font-weight: 550; }
.et-nav a:hover { background: var(--ob-line-soft); color: var(--ob-ink); }
.et-nav a.on { background: var(--acc-soft); color: var(--acc-deep); font-weight: 700; }
.et-nav a .ic { width: 18px; text-align: center; opacity: .9; }
.et-nav a .tag { margin-left: auto; font-size: 11px; font-weight: 700; background: var(--ob-danger); color: #fff; border-radius: 20px; padding: 1px 7px; font-family: var(--mono); }
.et-spacer { flex: 1; }
.et-me { display: flex; align-items: center; gap: 11px; padding: 12px 8px 2px; border-top: 1px solid var(--ob-line); margin-top: 8px; }
.et-status { font-size: 10.5px; color: var(--ob-faint); display: flex; align-items: center; gap: 4px; }
.et-status .dot { width: 6px; height: 6px; border-radius: 50%; background: var(--ob-success); }
/* Matches the OneBloc sidebar convention (Account / ERP / FMS): a muted bi-box-arrow-right that
   turns red on hover, so the one destructive control in the rail reads as destructive. */
.et-signout {
  border: none; background: none; color: var(--ob-muted); cursor: pointer; font-size: 15px;
  flex: none; padding: 5px; border-radius: 7px; line-height: 1;
  display: inline-flex; align-items: center; justify-content: center;
  transition: color .12s, background .12s;
}
.et-signout:hover { background: var(--ob-line-soft); color: #DC2626; }
.of-avatar { border-radius: 50%; color: #fff; display: grid; place-items: center; font-weight: 700; flex: none; }

/* ---------- main + topbar ---------- */
.et-main { padding: 28px 32px 52px; max-width: 1280px; width: 100%; }
.et-topbar { display: flex; align-items: flex-end; gap: 18px; margin-bottom: 24px; flex-wrap: wrap; }
.et-topbar h1 { margin: 0; font-size: 26px; font-weight: 600; letter-spacing: -.025em; color: var(--ob-ink); }
.et-topbar .sub { margin: 4px 0 0; font-size: 13.5px; color: var(--ob-muted); }
.et-topbar .actions { margin-left: auto; display: flex; align-items: center; gap: 10px; }
.et-search { height: 42px; width: 220px; border: 1px solid var(--ob-line); border-radius: 11px; background: var(--ob-card); padding: 0 12px 0 36px; font-family: var(--of-font, inherit); font-size: 13px; color: var(--ob-ink);
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='15' height='15' fill='none' stroke='%239AA3AF' stroke-width='2' stroke-linecap='round'><circle cx='6.5' cy='6.5' r='4.5'/><path d='M13 13l-3-3'/></svg>"); background-repeat: no-repeat; background-position: 13px center; }
.et-search::placeholder { color: var(--ob-faint); }
.et-btn { height: 42px; padding: 0 17px; border-radius: 11px; border: 1px solid var(--ob-line); background: var(--ob-card); color: var(--ob-ink); font-family: inherit; font-size: 13px; font-weight: 600; cursor: pointer; display: inline-flex; align-items: center; gap: 7px; box-shadow: 0 1px 2px rgba(16,33,80,.05); }
.et-btn:hover { border-color: var(--acc); color: var(--acc-deep); }
.et-btn-primary { background: var(--acc); border-color: var(--acc); color: #fff; box-shadow: 0 2px 8px rgba(15,158,142,.28); }
.et-btn-primary:hover { background: var(--acc-deep); color: #fff; }

/* ---------- stat band ---------- */
.et-stats { display: grid; grid-template-columns: repeat(4, 1fr); gap: 15px; margin-bottom: 13px; }
.et-stat { background: var(--ob-card); border: 1px solid var(--ob-line); border-radius: 16px; padding: 16px 17px; box-shadow: 0 1px 2px rgba(16,33,80,.05); position: relative; overflow: hidden; }
.et-stat .k { font-size: 12px; font-weight: 600; color: var(--ob-muted); display: flex; align-items: center; gap: 7px; }
.et-stat .v { font-size: 32px; font-weight: 600; letter-spacing: -.03em; margin-top: 7px; line-height: 1; font-family: var(--mono); }
.et-stat .d { font-size: 11.5px; color: var(--ob-faint); margin-top: 8px; }
.et-stat.crit { background: linear-gradient(180deg, var(--ob-danger-soft, #FBEAE6), var(--ob-card) 80%); }
.et-stat.crit .v { color: var(--ob-danger); }
.et-stat .stripe { position: absolute; left: 0; top: 0; bottom: 0; width: 3px; }
.et-stat.crit .stripe { background: var(--ob-danger); }
.et-stat.warn .stripe { background: var(--ob-warning); }
.et-pip { width: 8px; height: 8px; border-radius: 50%; }

/* ---------- deadline nudge ---------- */
.et-nudge { display: flex; align-items: center; gap: 12px; margin: 13px 0 24px; background: var(--ob-warning-soft, #FBF1DE); border: 1px solid #ecd9ad; border-radius: 12px; padding: 12px 16px; font-size: 13px; color: var(--ob-ink); }
.et-nudge .ic { color: var(--ob-warning); font-size: 15px; }
.et-nudge a { margin-left: auto; color: var(--acc-deep); font-weight: 700; text-decoration: none; font-size: 12.5px; white-space: nowrap; }

/* ---------- content grid + panels ---------- */
.et-grid { display: grid; grid-template-columns: 1.35fr 1fr; gap: 19px; align-items: start; }
.et-panel { background: var(--ob-card); border: 1px solid var(--ob-line); border-radius: 16px; box-shadow: 0 1px 2px rgba(16,33,80,.05); }
.et-panel > .head { display: flex; align-items: center; gap: 10px; padding: 16px 19px 14px; border-bottom: 1px solid var(--ob-line); }
.et-panel > .head h2 { margin: 0; font-size: 15px; font-weight: 700; letter-spacing: -.2px; }
.et-panel > .head .hint { font-size: 11.5px; color: var(--ob-faint); }
.et-panel > .head .right { margin-left: auto; }

/* ---------- who's behind ---------- */
.et-legend { display: flex; gap: 15px; padding: 12px 19px; font-size: 11px; color: var(--ob-muted); flex-wrap: wrap; }
.et-legend i { display: inline-flex; align-items: center; gap: 5px; }
.et-legend .sw { width: 9px; height: 9px; border-radius: 3px; }
/* No row borders and no left rail. Every person being behind painted a solid red bar down the whole
   list and boxed each row, which read as a heavy table rather than a scannable list — and a rail
   that is always on carries no information. Overdue is signalled by the pill and the bar instead. */
.et-person {
  display: grid; grid-template-columns: 40px 1fr auto; gap: 14px; align-items: center;
  padding: 12px 14px; margin: 0 5px; border-radius: 12px; border: 1px solid transparent;
  cursor: pointer; background: none; width: calc(100% - 10px); text-align: left; font-family: inherit;
  transition: background .12s, border-color .12s;
}
.et-person + .et-person { margin-top: 2px; }
.et-person:hover { background: var(--ob-line-soft); }
.et-person.sel { background: var(--acc-soft); border-color: var(--acc); }
.et-person .nm { font-size: 13.5px; font-weight: 700; }
.et-person .role { font-size: 11.5px; color: var(--ob-faint); }
/* Track + proportional fill. The track is the team's busiest workload; the fill is this person's
   share of it, so bar LENGTH reads as "how much" and the colours read as "how urgent". */
.et-bar { height: 8px; border-radius: 20px; background: var(--ob-line-soft); overflow: hidden; display: flex; margin-top: 9px; }
.et-bar .fill { display: flex; height: 100%; border-radius: 20px; overflow: hidden; min-width: 8px; }
.et-bar span { height: 100%; display: block; }
/* Solid, flat fills — no gradients or seams, so a segment reads as one confident block of colour. */
/* Pastel, not poster paint. Two earlier passes kept the colour at full strength and only varied the
   shading, which still read as three saturated blocks — seven of these stacked down the panel was
   the loudest thing on the dashboard, competing with the overdue pills that actually need to shout.
   The hue still identifies the state; the saturation does not have to.

   Ramp runs ALONG the bar (90deg), light to slightly-less-light, so the bar reads as one soft
   sweep. --w1/--w2 are how much of the status colour survives against white. */
.et-bar span {
  --w1: 30%; --w2: 58%;
  background: linear-gradient(90deg,
    color-mix(in srgb, var(--sc) var(--w1), #fff) 0%,
    color-mix(in srgb, var(--sc) var(--w2), #fff) 100%);
}
/* Overdue keeps a little more weight than the others — it is the one worth noticing. */
.et-bar .over { --sc: var(--ob-danger); --w1: 38%; --w2: 68%; }
.et-bar .soon { --sc: var(--ob-warning); --w1: 30%; --w2: 56%; }
.et-bar .ok   { --sc: var(--acc);        --w1: 26%; --w2: 50%; }
/* Segment divider: a soft white seam rather than a hard edge between two bands. */
.et-bar .soon, .et-bar .ok { box-shadow: inset 2px 0 0 rgba(255, 255, 255, .85); }
.et-bar { background: var(--ob-line-soft); box-shadow: none; }
.et-person .tally { text-align: right; display: flex; flex-direction: column; align-items: flex-end; gap: 3px; }
.et-person .open { font-size: 12px; color: var(--ob-muted); }
.et-person .open b { font-size: 17px; font-weight: 700; color: var(--ob-ink); font-family: var(--mono); }
.et-ovpill { font-size: 11px; font-weight: 700; padding: 2px 8px; border-radius: 20px; background: var(--ob-danger-soft, #FBEAE6); color: var(--ob-danger); font-family: var(--mono); }

/* ---------- triage ---------- */
.et-seg { display: inline-flex; background: var(--ob-line-soft); border: 1px solid var(--ob-line); border-radius: 10px; padding: 3px; gap: 2px; }
.et-seg button { border: none; background: none; font-family: inherit; font-size: 12px; font-weight: 600; color: var(--ob-muted); padding: 5px 11px; border-radius: 7px; cursor: pointer; }
.et-seg button.on { background: var(--ob-card); color: var(--ob-ink); box-shadow: 0 1px 2px rgba(16,33,80,.08); }
.et-seg button .c { color: var(--ob-faint); font-weight: 700; font-family: var(--mono); }
.et-seg button.on .c { color: var(--ob-danger); }
/* Rows are links into /tasks?card=… — reset the anchor so they still read as list rows. */
/* ---- "Needs attention": pin it to the screen, scroll the list inside ----
   The panel renders every overdue + today + week task, so a busy week made this column metres long
   and the whole page had to be scrolled past it to reach anything. Sticky + an internally scrolling
   list means the triage queue is always in view no matter how far down "Who's behind" runs.
   Body is the scroller (the sidebar is already sticky/100vh), so `top` is viewport-relative. */
.et-attention {
  position: sticky; top: 20px;
  display: flex; flex-direction: column;
  max-height: calc(100vh - 40px);      /* 20px breathing room top and bottom */
}
.et-attention > .head,
.et-attention > .et-filterbar { flex: none; }
.et-attention > #triage {
  overflow-y: auto;
  min-height: 0;                        /* without this a flex child refuses to shrink and never scrolls */
  overscroll-behavior: contain;         /* hitting the end must not start scrolling the page behind it */
  border-bottom-left-radius: 16px; border-bottom-right-radius: 16px;
}

/* Short viewports: pinning wins nothing and costs the little height there is. */
@media (max-height: 620px) {
  .et-attention { position: static; max-height: none; }
  .et-attention > #triage { max-height: 420px; }
}
/* 940px is where .et-grid collapses to one column — once it does, sticking would trap the list
   mid-page while the user is trying to scroll past it. */
@media (max-width: 940px) {
  .et-attention { position: static; max-height: none; }
  .et-attention > #triage { max-height: 60vh; }
}

.et-task { display: grid; grid-template-columns: 14px 1fr auto; gap: 11px; align-items: center; padding: 13px 19px; border-bottom: 1px solid var(--ob-line); color: inherit; text-decoration: none; }
.et-task:last-child { border-bottom: none; }
.et-task:hover { background: var(--ob-line-soft); }
.et-prio { width: 9px; height: 9px; border-radius: 50%; }
.et-prio.high { background: var(--ob-danger); box-shadow: 0 0 0 3px color-mix(in srgb, var(--ob-danger) 16%, transparent); }
.et-prio.normal { background: var(--ob-faint); } .et-prio.low { background: var(--ob-line); }
/* On the board card face the dot sits inline in the title (spans are inline: width/height need
   inline-block here; in the dashboard's grid rows it's a grid item so the base rule suffices). */
.of-board-card .tt .et-prio { display: inline-block; margin-right: 6px; vertical-align: baseline; }
/* Finish-line marker on a column header. Success green, not the module accent: it means "done",
   and the accent is already used for the in-progress WIP dot right next to it. */
.of-board-list-header .of-done-flag { color: var(--ob-success); font-size: 11px; margin-right: 5px; flex: none; }

/* Wider dialog for forms with side-by-side controls. OBModal's 448px default is right for a
   confirm, too tight for a 3-column picker row. */
.ob-modal.et-wide { width: min(680px, 100%); }

/* ---------- new task composer ----------
   Grid with minmax(0,1fr), not fixed px widths in a flex row: the old layout hard-coded 150px for
   the date field, so a native dd/mm/yyyy input (which has its own minimum width plus a calendar
   button) overflowed the dialog on the right. minmax(0,…) lets a column shrink below its content. */
.et-newtask .grid2 { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 200px); gap: 12px; margin-bottom: 12px; }
.et-newtask .grid2b { display: grid; grid-template-columns: minmax(0, 150px) minmax(0, 1fr); gap: 12px; }
.et-newtask .ob-field.row { margin-bottom: 13px; }
.et-newtask .ob-field .opt { font-weight: 400; color: var(--ob-faint); }
.et-newtask .ob-input { width: 100%; box-sizing: border-box; }
.et-newtask .obsel { width: 100%; min-width: 0; }
.et-newtask .et-quickdates { margin: 0 0 14px; }
.et-newtask .hint { margin-top: 14px; }
@media (max-width: 620px) {
  .et-newtask .grid2, .et-newtask .grid2b { grid-template-columns: minmax(0, 1fr); }
}
/* The property popover must escape the dialog, or it gets clipped at the modal's edge. */
.ob-modal .bd { overflow: visible; }
.et-newtask .obprop-pop { width: min(520px, 86vw); }

/* ---------- card panel: property + labels ---------- */
.et-prop-body { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-top: 10px; }
.et-proptag {
  display: inline-flex; align-items: center; gap: 9px; padding: 8px 13px;
  border-radius: 11px; border: 1px solid var(--acc); background: var(--acc-soft); color: var(--acc-deep);
}
/* A whole-condo task is a different KIND of thing from a single-unit one; amber marks the wider blast
   radius so nobody mistakes "all 12 units" for "one unit". */
.et-proptag.whole { border-color: var(--ob-warning); background: var(--ob-warning-soft, #FBF1DE); color: var(--ob-warning); }
.et-proptag .t { display: flex; flex-direction: column; line-height: 1.25; }
.et-proptag .main { font-size: 13px; font-weight: 650; }
.et-proptag .sub { font-size: 10.5px; opacity: .8; text-transform: uppercase; letter-spacing: .3px; }
.et-prop-none { font-size: 12.5px; color: var(--ob-faint); }
.et-prop-hint { font-size: 12px; color: var(--ob-muted); margin: 12px 0 0; }

/* Deadline / Property / Labels use .of-section, which had no base rule at all — so they sat flush
   against whatever followed while the .of-card-section blocks below them were spaced 22px apart. */
.of-card-panel .of-section { margin-bottom: 22px; }

/* ---- two colour channels, and they must not compete ----
   THE COLUMN says which stage the work is at. THE CARD says how urgent it is. Colouring cards by
   stage (the first attempt) spent the loudest signal on the thing you can already see from the
   card's position, leaving nothing for the thing you can't — that an item is late. */

/* --- column = stage. `--sc` comes from the column's own colour, the same value that paints its
   header dot, so recolouring or renaming a column stays truthful. --- */
.of-board-list { --sc: #64748B; }
.of-board-list {
  background: linear-gradient(180deg,
    color-mix(in srgb, var(--sc) 7%, #fff) 0%,
    color-mix(in srgb, var(--sc) 3%, #fff) 190px,
    color-mix(in srgb, var(--sc) 2%, #fff) 100%);
  border: 1px solid color-mix(in srgb, var(--sc) 13%, transparent);
}
.of-board-list .of-board-list-header { border-bottom: 1px solid color-mix(in srgb, var(--sc) 14%, transparent); }
/* The drop target has to stay obviously different from the resting tint. */
.of-board-list.drop-target { border-color: color-mix(in srgb, var(--sc) 55%, transparent); }

/* --- card = urgency, but as an EDGE, not a fill ---
   Washing the whole card was too much: with the column already tinted, a coloured card body left
   the board with no calm surface anywhere. The signal survives as a 3px left stripe — visible down
   a column at a glance — while the card itself stays white for the text to sit on. */
.of-board-list .of-board-card {
  --uc: transparent;
  background: #fff;
  transition: box-shadow .12s, opacity .15s, border-color .12s;
}
.of-board-card.due-over { --uc: #C8472F; }        /* past the deadline */
.of-board-card.due-soon,                          /* within the next week */
.of-board-card.due-today { --uc: #B7791F; }       /* due today — about to be late */

.of-board-card.due-over,
.of-board-card.due-soon,
.of-board-card.due-today { border-left: 3px solid color-mix(in srgb, var(--uc) 45%, #fff); }
/* Overdue is the one that must win the room; nearly-late stays a hint. */
.of-board-card.due-over { border-left-color: var(--uc); }

.of-board-card.due-over:hover,
.of-board-card.due-soon:hover,
.of-board-card.due-today:hover { border-left-color: var(--uc); }

/* ---- attachment viewer ----
   Replaces the old single-file lightbox. Pages through every attachment on the card and picks a
   renderer from the file's own type, so six photos is six arrow presses not six open/close cycles. */
.of-viewer {
  position: fixed; inset: 0; z-index: 2147482400; background: rgba(9, 12, 18, .93);
  display: grid; grid-template-rows: auto 1fr auto; animation: vwin .16s ease-out;
}
@keyframes vwin { from { opacity: 0; } to { opacity: 1; } }

.of-viewer .vw-head {
  display: flex; align-items: center; gap: 12px; padding: 12px 16px; color: #fff;
  background: linear-gradient(180deg, rgba(0, 0, 0, .45), transparent);
}
.of-viewer .vw-ttl { min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.of-viewer .vw-ttl .nm { font-size: 13.5px; font-weight: 650; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.of-viewer .vw-ttl .mt { font-size: 11px; color: #9AA3AF; }
.of-viewer .vw-count { margin-left: auto; font-size: 11.5px; color: #CBD3DE; }
.of-viewer .vw-btn {
  width: 34px; height: 34px; flex: none; border: 1px solid rgba(255, 255, 255, .16); border-radius: 9px;
  background: rgba(255, 255, 255, .07); color: #fff; cursor: pointer; font-size: 14px;
  display: inline-flex; align-items: center; justify-content: center; text-decoration: none;
  transition: background .12s, border-color .12s;
}
.of-viewer .vw-btn:hover { background: rgba(255, 255, 255, .16); border-color: rgba(255, 255, 255, .3); }

.of-viewer .vw-stage {
  min-height: 0; display: flex; align-items: center; justify-content: center;
  padding: 0 62px 8px; overflow: hidden;
}
.of-viewer .vw-stage img,
.of-viewer .vw-stage video { max-width: 100%; max-height: 100%; border-radius: 10px; display: block; }
/* PDFs get the whole stage — a fitted-to-content frame wastes the screen the viewer just took over. */
.of-viewer .vw-stage.k-pdf { padding: 0 16px 8px; }
.of-viewer .vw-stage iframe { width: 100%; height: 100%; border: 0; border-radius: 10px; background: #fff; }
.of-viewer .vw-stage.k-text { padding: 0 16px 8px; }
.of-viewer .vw-text {
  width: 100%; height: 100%; margin: 0; overflow: auto; background: #fff; border-radius: 10px;
  padding: 16px 18px; font-family: var(--mono, "JetBrains Mono", monospace); font-size: 12px;
  line-height: 1.6; color: #1f2937; white-space: pre-wrap; word-break: break-word;
}

/* No-preview state: say so and give the download, rather than a blank frame the user waits on. */
.of-viewer .vw-file {
  display: flex; flex-direction: column; align-items: center; gap: 10px; color: #fff; text-align: center;
  background: rgba(255, 255, 255, .05); border: 1px solid rgba(255, 255, 255, .12);
  border-radius: 16px; padding: 34px 40px;
}
.of-viewer .vw-file .big { font-size: 46px; color: #9AA3AF; }
.of-viewer .vw-file .nm { font-size: 14px; font-weight: 650; max-width: 320px; word-break: break-word; }
.of-viewer .vw-file .wy { font-size: 12px; color: #9AA3AF; }
.of-viewer .vw-dl {
  margin-top: 6px; display: inline-flex; align-items: center; gap: 7px; text-decoration: none;
  background: var(--acc); color: #fff; border-radius: 9px; padding: 9px 15px; font-size: 12.5px; font-weight: 650;
}
.of-viewer .vw-dl:hover { background: var(--acc-deep, #0B7F73); }

.of-viewer .vw-nav {
  position: absolute; top: 50%; transform: translateY(-50%); width: 42px; height: 42px;
  border-radius: 50%; border: 1px solid rgba(255, 255, 255, .18); background: rgba(20, 24, 32, .72);
  color: #fff; cursor: pointer; font-size: 16px; display: inline-flex; align-items: center;
  justify-content: center; transition: background .12s;
}
.of-viewer .vw-nav:hover { background: rgba(40, 46, 58, .95); }
.of-viewer .vw-nav.prev { left: 12px; }
.of-viewer .vw-nav.next { right: 12px; }

.of-viewer .vw-strip {
  display: flex; gap: 8px; padding: 10px 16px 14px; overflow-x: auto; justify-content: center;
  background: linear-gradient(0deg, rgba(0, 0, 0, .45), transparent);
}
.of-viewer .vw-th {
  width: 54px; height: 42px; flex: none; border-radius: 8px; overflow: hidden; cursor: pointer;
  border: 2px solid transparent; background: rgba(255, 255, 255, .09); color: #CBD3DE;
  display: inline-flex; align-items: center; justify-content: center; padding: 0; font-size: 15px;
  transition: border-color .12s, opacity .12s; opacity: .65;
}
.of-viewer .vw-th img { width: 100%; height: 100%; object-fit: cover; display: block; }
.of-viewer .vw-th:hover { opacity: 1; }
.of-viewer .vw-th.on { border-color: var(--acc); opacity: 1; }

@media (max-width: 640px) {
  .of-viewer .vw-stage { padding: 0 10px 8px; }
  .of-viewer .vw-nav { width: 36px; height: 36px; }
  .of-viewer .vw-nav.prev { left: 4px; }
  .of-viewer .vw-nav.next { right: 4px; }
}

/* Square icon-only variant of .et-btn, for the explain toggle. */
.et-btn.icon { width: 42px; padding: 0; justify-content: center; font-size: 16px; }

/* ---- keep a pressed icon button legible on hover ----
   ob-explain.css sets `.obx-btn.on { background: var(--acc); color: #fff }`, but board.css loads
   AFTER it and its `.of-btn:hover { background: #f8fafc }` has the same specificity — so hovering an
   ACTIVE toggle repainted the background near-white while the glyph stayed white, and the icon
   simply vanished. Restated here (tasks.css is last) with a hover that DARKENS instead of lightens. */
.of-btn.obx-btn.on,
.et-btn.obx-btn.on {
  background: var(--acc); border-color: var(--acc); color: #fff;
}
.of-btn.obx-btn.on:hover,
.et-btn.obx-btn.on:hover {
  background: var(--acc-deep); border-color: var(--acc-deep); color: #fff;
}
/* Same trap for any other icon toggle that marks itself pressed. */
.of-btn-icon[aria-pressed="true"]:hover { background: var(--ob-line-soft); }

/* The /mine column header has no wip dot of its own (columns are merged across boards), so explain
   mode needs something to ring. A small stage swatch doubles as a visual key. */
.et-colswatch {
  width: 8px; height: 8px; border-radius: 50%; background: var(--sc, var(--acc)); flex: none;
  display: inline-block;
}

/* ---- Setup screen (owner only) ---- */
.et-master { margin-bottom: 18px; border-left: 3px solid var(--ob-line); transition: border-color .15s; }
.et-master.on { border-left-color: var(--acc); }
.et-master .bd { display: flex; align-items: center; gap: 18px; padding: 18px 20px; }
.et-master .tx { flex: 1; min-width: 0; }
.et-master h2 { margin: 0 0 3px; font-size: 15px; font-weight: 700; }
.et-master p { margin: 0; font-size: 12.5px; color: var(--ob-muted); }
.et-master.on p { color: var(--acc-deep); }

.et-setupgrid { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; align-items: start; margin-bottom: 18px; }
@media (max-width: 1080px) { .et-setupgrid { grid-template-columns: 1fr; } }

/* ---- OneBloc Connect roster (/admin) ---- */
.et-connectlist { margin-top: 18px; border-top: 1px solid var(--ob-line); }
.et-connect-none { font-size: 12.5px; color: var(--ob-faint); padding: 16px 2px 2px; margin: 0; }
.et-connectrow {
  display: flex; align-items: center; gap: 12px;
  padding: 12px 2px; border-bottom: 1px solid var(--ob-line);
}
.et-connectrow:last-child { border-bottom: none; }
.et-connectrow .who { flex: 1; min-width: 0; }
.et-connectrow .nm { font-size: 13.5px; font-weight: 650; color: var(--ob-ink); }
.et-connectrow .sub { font-size: 11.5px; color: var(--ob-faint); margin-top: 2px; }
/* Revoked rows stay visible — an owner needs to see who USED to have access, and restoring is one
   click. Fading rather than hiding says "switched off", not "gone". */
.et-connectrow.off .nm, .et-connectrow.off .sub { opacity: .5; }
.et-connectrow.off .nm { text-decoration: line-through; }

.et-setup { margin-bottom: 18px; }
.et-setup > .head { display: flex; align-items: center; gap: 10px; padding: 15px 20px 13px; border-bottom: 1px solid var(--ob-line); }
.et-setup > .head h2 { margin: 0; font-size: 14.5px; font-weight: 700; display: flex; align-items: center; gap: 8px; flex: 1; }
.et-setup > .head h2 .bi { color: var(--acc); font-size: 16px; }
.et-setup > .bd { padding: 16px 20px 18px; }
.et-setup .lead { margin: 0 0 14px; font-size: 12.5px; color: var(--ob-muted); line-height: 1.55; }
.et-setup .ob-field { margin-bottom: 13px; }
.et-setup .ob-field label { display: block; font-size: 12px; font-weight: 650; color: var(--ob-slate); margin-bottom: 5px; }
.et-setup .ob-input { width: 100%; }
.et-setup .hint { margin: 5px 0 0; font-size: 11.5px; color: var(--ob-faint); line-height: 1.5; }
.et-setup .hint.ok { color: var(--ob-success, #16895A); }
.et-setup .hint code { background: var(--ob-line-soft); padding: 1px 5px; border-radius: 4px; font-size: 11px; }
.et-setup .row2 { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.et-setup .test { display: flex; align-items: center; gap: 12px; margin-top: 16px; padding-top: 15px; border-top: 1px solid var(--ob-line-soft); flex-wrap: wrap; }

/* Test/save feedback sits next to the button that caused it — a toast alone disappears before you
   can read an SMTP error, and those are the ones you need to read twice. */
.res { font-size: 12px; line-height: 1.5; }
.res.ok { color: var(--ob-success, #16895A); font-weight: 600; }
.res.bad { color: var(--ob-danger, #C8472F); font-weight: 600; }
.res.warn { color: var(--ob-warning, #B7791F); font-weight: 600; }

.et-saverow { display: flex; align-items: center; gap: 14px; padding-bottom: 40px; }
.ob-switch.big .tr { transform: scale(1.15); }

/* ---- board switcher in the board header ---- */
.et-switch { position: relative; display: inline-flex; }
.et-switch-pop {
  position: absolute; top: calc(100% + 7px); left: 0; z-index: 2147482000; width: 292px;
  background: var(--ob-card); border: 1px solid var(--ob-line); border-radius: 14px; overflow: hidden;
  box-shadow: 0 18px 44px -12px rgba(17, 19, 34, .26), 0 5px 14px -6px rgba(17, 19, 34, .10);
}
.et-switch-pop .hd {
  padding: 11px 13px 8px; font-size: 10px; font-weight: 700; letter-spacing: .5px;
  text-transform: uppercase; color: var(--ob-faint);
}
.et-switch-pop .lst { max-height: 320px; overflow-y: auto; padding: 0 6px 6px; }
.et-switch-pop .ld { padding: 12px 8px; font-size: 12px; color: var(--ob-faint); }
.et-switch-pop .it {
  --bc: var(--acc);
  display: flex; align-items: center; gap: 10px; padding: 8px 8px; border-radius: 9px;
  text-decoration: none; color: inherit; cursor: pointer;
}
.et-switch-pop a.it:hover { background: color-mix(in srgb, var(--bc) 9%, #fff); }
.et-switch-pop .it.on { background: var(--ob-line-soft); cursor: default; }
.et-switch-pop .it .sw { width: 4px; align-self: stretch; min-height: 30px; border-radius: 2px; background: var(--bc); flex: none; }
.et-switch-pop .it .tx { min-width: 0; flex: 1; }
.et-switch-pop .it .nm {
  font-size: 12.5px; font-weight: 650; color: var(--ob-ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.et-switch-pop .it .sb { display: flex; gap: 8px; margin-top: 2px; font-size: 11px; color: var(--ob-faint); }
.et-switch-pop .it .sb .od { color: var(--ob-danger, #C8472F); font-weight: 650; }
.et-switch-pop .it .sb .cl { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.et-switch-pop .it .pv { color: var(--ob-faint); font-size: 10px; }
.et-switch-pop .it.on .bi-check-lg { color: var(--acc); font-size: 13px; }
.et-switch-pop .ft {
  display: flex; align-items: center; gap: 7px; padding: 10px 13px; border-top: 1px solid var(--ob-line-soft);
  font-size: 12px; font-weight: 600; color: var(--acc); text-decoration: none;
}
.et-switch-pop .ft:hover { background: var(--ob-line-soft); }

/* ---- board shortcut rail on /mine ----
   Horizontal and scrollable rather than a grid: it must not compete with the task columns below it
   for vertical space. The board's own accent runs down the left edge so the rail is scannable by
   colour, matching the tiles on the Boards landing page. */
.et-boardjump { margin: 4px 0 20px; }
.et-boardjump .hd { display: flex; align-items: baseline; gap: 12px; margin-bottom: 9px; }
.et-boardjump .hd .t {
  font-size: 11px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
  color: var(--ob-faint); display: inline-flex; align-items: center; gap: 7px;
}
.et-boardjump .hd .all {
  margin-left: auto; font-size: 12px; font-weight: 600; color: var(--acc);
  text-decoration: none; display: inline-flex; align-items: center;
}
.et-boardjump .hd .all:hover { text-decoration: underline; }
.et-boardjump .rail {
  display: flex; gap: 10px; overflow-x: auto; padding-bottom: 4px;
  scrollbar-width: thin; scroll-snap-type: x proximity;
}
.et-bjump {
  --bc: var(--acc);
  flex: 0 0 auto; min-width: 176px; max-width: 240px; scroll-snap-align: start;
  background: var(--ob-card); border: 1px solid var(--ob-line); border-left: 3px solid var(--bc);
  border-radius: 12px; padding: 11px 13px; text-decoration: none; color: inherit;
  box-shadow: 0 1px 2px rgba(16, 33, 80, .05); transition: border-color .12s, box-shadow .12s, transform .1s;
}
.et-bjump:hover {
  border-color: var(--bc); box-shadow: 0 6px 18px -8px rgba(16, 33, 80, .22); transform: translateY(-1px);
}
.et-bjump .tp { display: flex; align-items: center; gap: 8px; min-width: 0; }
.et-bjump .tp .bi { color: var(--bc); font-size: 13px; flex: none; }
.et-bjump .tp .nm {
  font-size: 13px; font-weight: 650; color: var(--ob-ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.et-bjump .tp .pv { margin-left: auto; color: var(--ob-faint); font-size: 10px; }
.et-bjump .cl {
  font-size: 11px; color: var(--ob-muted); margin-top: 3px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.et-bjump .mt { display: flex; align-items: center; gap: 8px; margin-top: 6px; font-size: 11.5px; color: var(--ob-faint); }
.et-bjump .mt .od { color: var(--ob-danger, #C8472F); font-weight: 650; }

@media (max-width: 640px) { .et-bjump { min-width: 150px; } }

/* ---- anchored popovers: one shape for everything that opens off a button in the card panel ----
   Same card, radius and shadow as the property picker, so Checklist / Attachment / Add field all
   read as the same gesture instead of three different kinds of interruption. */
.of-pop-anchor { position: relative; display: inline-flex; }
.of-pop {
  position: absolute; top: calc(100% + 7px); left: 0; z-index: 2147482000;
  max-width: 92vw; background: var(--ob-card, #fff);
  border: 1px solid var(--ob-line, #E6E9EE); border-radius: 15px;
  box-shadow: 0 18px 44px -12px rgba(17, 19, 34, .26), 0 5px 14px -6px rgba(17, 19, 34, .10);
  text-align: left; cursor: default;
}
/* Buttons hard against the right margin (Attachments "Add") would otherwise run off the panel. */
.of-pop.rt { left: auto; right: 0; }
/* Near the bottom of the screen the popover opens UPWARD instead of into empty space below. */
.of-pop.up { top: auto; bottom: calc(100% + 7px); }
/* When it fits neither way, place() caps the height — the body scrolls so the footer stays reachable. */
.of-pop[style*="max-height"] { display: flex; flex-direction: column; }
.of-pop[style*="max-height"] .of-pop-bd { overflow-y: auto; min-height: 0; }
.of-pop-hd {
  display: flex; align-items: center; gap: 8px; padding: 11px 13px 9px;
  border-bottom: 1px solid var(--ob-line-soft, #F0F2F5);
}
.of-pop-hd .t {
  font-size: 10px; font-weight: 700; letter-spacing: .5px; text-transform: uppercase;
  color: var(--ob-faint, #9AA3AF);
}
.of-pop-hd .xb {
  margin-left: auto; width: 22px; height: 22px; display: inline-flex; align-items: center;
  justify-content: center; border: none; background: transparent; border-radius: 6px;
  cursor: pointer; color: var(--ob-faint, #9AA3AF); font-size: 10px;
}
.of-pop-hd .xb:hover { background: var(--ob-line-soft, #F0F2F5); color: var(--ob-ink, #101720); }
.of-pop-bd { padding: 12px 13px 13px; }
.of-pop-bd .of-input { width: 100%; }
.of-pop-ft { display: flex; justify-content: flex-end; gap: 8px; margin-top: 11px; }

.of-pop-list { display: flex; flex-direction: column; gap: 1px; max-height: 210px; overflow-y: auto; margin-bottom: 10px; }
.of-pop-none { font-size: 12px; color: var(--ob-faint, #9AA3AF); padding: 4px 2px 8px; }
.of-pop-check {
  display: flex; align-items: flex-start; gap: 9px; padding: 6px 7px; border-radius: 8px;
  font-size: 12.5px; line-height: 1.45; color: var(--ob-slate, #3A4453); cursor: pointer;
}
.of-pop-check:hover { background: var(--ob-line-soft, #F0F2F5); }
.of-pop-check input { margin-top: 2px; flex: none; accent-color: var(--acc, #0F9E8E); }
.of-pop-check.done .tx { text-decoration: line-through; color: var(--ob-faint, #9AA3AF); }

/* The button that owns an open popover stays visibly "held down". */
.of-quick-btn.popped, .of-btn.popped { border-color: var(--acc, #0F9E8E); }

/* The label popover anchors HERE. Without this the .of-popover's containing block was some far
   ancestor, so left:0 threw it to the left edge of the page instead of under the button. */
.et-labels { position: relative; }
.et-labelpop { position: absolute; left: 0; top: calc(100% + 6px); }
/* ---- label colour: one stored hex, rendered as a gradient ----
   Labels still store a single hex. The lift and shade are derived from it here, so nothing in the
   database or the API changes and every surface that shows a label picks this up for free.
   Elements set --lc (the base colour); this builds the ramp. */
/* The fallback goes INSIDE each var() rather than declaring --lc here: declaring it would shadow
   the value the parent set, and .et-lbl .dot inherits its colour from the row it sits in. */
.of-label-pill, .of-label-bar, .of-swatch, .et-swatches .sw, .et-lbl .dot {
  background: linear-gradient(135deg,
    color-mix(in srgb, var(--lc, var(--acc, #0F9E8E)) 76%, #fff) 0%,
    var(--lc, var(--acc, #0F9E8E)) 50%,
    color-mix(in srgb, var(--lc, var(--acc, #0F9E8E)) 80%, #000) 100%);
}
/* Light comes from the top-left, so the highlight edge belongs there and the shadow opposite. */
.of-label-pill { box-shadow: inset 0 1px 0 rgba(255, 255, 255, .22), inset 0 -1px 0 rgba(0, 0, 0, .08); }
.of-label-bar { box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25); }

/* ---- label picker: soft tints, not solid colour bars ---- */
.et-labelpop { padding: 14px; border-radius: 14px; box-shadow: 0 12px 34px rgba(15, 23, 42, .13), 0 2px 6px rgba(15, 23, 42, .06); }
.et-lbl-head { display: flex; align-items: center; margin-bottom: 10px; }
.et-lbl-head .t { font-size: 12px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--ob-faint); }
.et-lbl-head .xb {
  margin-left: auto; width: 24px; height: 24px; display: inline-flex; align-items: center; justify-content: center;
  border: none; background: transparent; border-radius: 7px; cursor: pointer; color: var(--ob-faint); font-size: 11px;
}
.et-lbl-head .xb:hover { background: var(--ob-line-soft); color: var(--ob-ink); }

.et-lbl-new { border-top: 1px solid var(--of-border); margin-top: 12px; padding-top: 12px; }
.et-lbl-new .of-input { width: 100%; margin-bottom: 10px; }
.et-lbl-list { display: flex; flex-direction: column; gap: 3px; max-height: 210px; overflow-y: auto; margin: 0 -2px; padding: 0 2px; }
.et-lbl {
  --lc: var(--acc);
  display: flex; align-items: center; gap: 10px; width: 100%; padding: 8px 10px;
  border-radius: 10px; cursor: pointer; font-family: inherit; font-size: 12.5px; font-weight: 600;
  text-align: left; color: var(--ob-slate);
  /* Tint, not fill: the label's colour is a thin wash so five stacked don't read as an alarm.
     Same diagonal direction as the swatches, just far weaker. */
  background: linear-gradient(135deg,
    color-mix(in srgb, var(--lc) 11%, #fff) 0%, color-mix(in srgb, var(--lc) 5%, #fff) 100%);
  border: 1px solid color-mix(in srgb, var(--lc) 18%, transparent);
  transition: background .12s, border-color .12s;
}
.et-lbl:hover {
  background: linear-gradient(135deg,
    color-mix(in srgb, var(--lc) 19%, #fff) 0%, color-mix(in srgb, var(--lc) 10%, #fff) 100%);
  border-color: color-mix(in srgb, var(--lc) 40%, transparent);
}
.et-lbl.on {
  background: linear-gradient(135deg,
    color-mix(in srgb, var(--lc) 17%, #fff) 0%, color-mix(in srgb, var(--lc) 9%, #fff) 100%);
  border-color: var(--lc); color: var(--ob-ink);
}
.et-lbl .dot {
  width: 11px; height: 11px; border-radius: 50%; flex: none;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .35);
}
.et-lbl .nm { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.et-lbl .tick { width: 16px; flex: none; color: var(--lc); font-size: 13px; display: inline-flex; justify-content: center; }
.et-lbl-none { font-size: 12px; color: var(--ob-faint); padding: 10px 2px; }

.et-swatches { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 12px; }
.et-swatches .sw {
  width: 28px; height: 28px; border-radius: 50%; cursor: pointer; padding: 0;
  border: 2px solid transparent;
  /* The inner highlight is what sells the gradient as a sphere rather than a flat disc. */
  box-shadow: inset 0 1px 1px rgba(255, 255, 255, .45), inset 0 -2px 3px rgba(0, 0, 0, .12);
  transition: box-shadow .12s, transform .1s;
}
.et-swatches .sw:hover { transform: scale(1.08); }
/* Ring in the swatch's own colour — a black border would add a second colour to every row. */
.et-swatches .sw.on {
  border-color: #fff;
  box-shadow: inset 0 1px 1px rgba(255, 255, 255, .45), inset 0 -2px 3px rgba(0, 0, 0, .12),
              0 0 0 2.5px var(--lc);
}

.et-labelrow { display: flex; gap: 7px; flex-wrap: wrap; align-items: center; margin-top: 10px; }
.et-addlabel {
  display: inline-flex; align-items: center; gap: 6px; font-family: inherit;
  font-size: 12px; font-weight: 600; color: var(--ob-muted); cursor: pointer;
  padding: 6px 12px; border-radius: 999px; border: 1px dashed var(--ob-line); background: transparent;
  transition: border-color .12s, color .12s, background .12s;
}
.et-addlabel:hover { border-color: var(--acc); color: var(--acc-deep); background: var(--acc-soft); border-style: solid; }

/* ---------- reports ---------- */
.et-rstats { grid-template-columns: repeat(4, 1fr); }
@media (max-width: 900px) { .et-rstats { grid-template-columns: repeat(2, 1fr); } }
.et-report { margin-bottom: 18px; padding-bottom: 4px; }
/* Every report says what decision it supports — a number with no decision attached gets misread. */
.et-why { margin: 0 19px 14px; font-size: 12.5px; color: var(--ob-muted); line-height: 1.55; max-width: 78ch; }
.et-note { margin: 12px 19px 16px; font-size: 12px; color: var(--ob-faint); line-height: 1.55; max-width: 78ch; }

.et-table { width: 100%; border-collapse: collapse; font-size: 12.5px; }
.et-table th {
  text-align: left; font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .4px;
  color: var(--ob-faint); padding: 8px 12px; border-bottom: 1px solid var(--ob-line); white-space: nowrap;
}
.et-table td { padding: 10px 12px; border-bottom: 1px solid var(--ob-line-soft); vertical-align: middle; }
.et-table tr:last-child td { border-bottom: none; }
.et-table td.mono { font-family: var(--mono); font-variant-numeric: tabular-nums; }
.et-table td.bad { color: var(--ob-danger); font-weight: 700; }
.et-table td.warn { color: var(--ob-warning); font-weight: 700; }
.et-table td a { color: var(--acc-deep); text-decoration: none; }
.et-table td a:hover { text-decoration: underline; }
.et-table .who { display: flex; align-items: center; gap: 9px; }
.et-table .who .of-avatar { width: 30px; height: 30px; font-size: 11px; }
.et-table .who .n { display: flex; flex-direction: column; line-height: 1.25; }
.et-table .who .role { font-size: 10.5px; color: var(--ob-faint); }
/* Bands, not a single score: the point is "who needs a conversation", not a league position. */
.et-table td.kpi b { font-family: var(--mono); font-size: 14px; }
.et-table td.kpi .sub { display: block; font-size: 10.5px; color: var(--ob-faint); font-family: var(--mono); }
.et-table td.kpi.good b { color: var(--ob-success); }
.et-table td.kpi.watch b { color: var(--ob-warning); }
.et-table td.kpi.poor b { color: var(--ob-danger); }
.et-table td.kpi .na { font-size: 11px; color: var(--ob-faint); font-style: italic; }

.et-kpigrid { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 12px; padding: 0 19px 16px; }
.et-kpi { border: 1px solid var(--ob-line); border-radius: 12px; padding: 12px 14px; display: flex; flex-direction: column; gap: 3px; }
.et-kpi .lb { font-size: 11px; font-weight: 650; color: var(--ob-muted); text-transform: uppercase; letter-spacing: .3px; }
.et-kpi .vl { font-size: 22px; font-weight: 750; }
.et-kpi.bad { border-color: color-mix(in srgb, var(--ob-danger) 40%, var(--ob-line)); }
.et-kpi.bad .vl { color: var(--ob-danger); }
.et-kpi.warn .vl { color: var(--ob-warning); }

.et-bars { display: flex; align-items: flex-end; gap: 12px; padding: 6px 19px 4px; overflow-x: auto; min-height: 150px; }
.et-bars .wk { display: flex; flex-direction: column; align-items: center; gap: 5px; flex: 1 0 54px; }
.et-bars .pair { display: flex; align-items: flex-end; gap: 3px; height: 104px; }
.et-bars .b { width: 15px; border-radius: 4px 4px 0 0; min-height: 2px; }
.et-bars .b.created { background: var(--ob-faint); }
.et-bars .b.done { background: var(--acc); }
.et-bars .lb { font-size: 10px; color: var(--ob-faint); white-space: nowrap; }
.et-bars .net { font-size: 10.5px; font-family: var(--mono); font-weight: 700; color: var(--ob-faint); }
.et-bars .net.up { color: var(--ob-danger); }      /* backlog grew */
.et-bars .net.down { color: var(--ob-success); }   /* backlog shrank */
.et-report .et-legend { padding: 0 19px 14px; }
.et-legend .sw.created { background: var(--ob-faint); }
.et-legend .sw.done { background: var(--acc); }

@media print {
  .et-shell, .et-topbar .actions { display: none !important; }
  .et-report { break-inside: avoid; border: 1px solid #ddd; }
}

/* ---------- All tasks: filter rail over a board ---------- */
.et-filters { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 12px; }
.et-searchbox { position: relative; flex: 1 1 260px; min-width: 220px; }
.et-searchbox i { position: absolute; left: 12px; top: 50%; transform: translateY(-50%); color: var(--ob-faint); font-size: 13px; }
.et-searchbox input {
  width: 100%; box-sizing: border-box; height: 40px; padding: 0 12px 0 34px;
  border: 1px solid var(--ob-line); border-radius: 11px; background: var(--ob-card);
  font-family: inherit; font-size: 13px; color: var(--ob-ink); outline: none;
}
.et-searchbox input:focus { border-color: var(--acc); box-shadow: 0 0 0 3px var(--acc-soft); }
.et-condofilter { height: 40px; width: auto; min-width: 170px; }
.et-openonly { display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; color: var(--ob-muted); cursor: pointer; white-space: nowrap; }
.et-people { display: flex; gap: 7px; flex-wrap: wrap; margin-bottom: 12px; }
.et-person-chip .ct { font-size: 11px; color: var(--ob-muted); font-weight: 700; }
/* Overdue count on a person chip — the number that decides who you chase first. */
.et-person-chip .od {
  font-size: 10.5px; font-weight: 800; color: #fff; background: var(--ob-danger);
  border-radius: 999px; padding: 1px 6px; min-width: 16px; text-align: center;
}
.et-resultline { font-size: 12px; color: var(--ob-faint); margin-bottom: 10px; }
.et-colempty { font-size: 12px; color: var(--ob-faint); padding: 10px 4px; }

/* ---------- My tasks: 3 stat cards + personal board ---------- */
.et-mystats { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; margin-bottom: 18px; }
@media (max-width: 720px) { .et-mystats { grid-template-columns: 1fr; } }
.et-stat {
  display: flex; flex-direction: column; gap: 2px; position: relative; overflow: hidden;
  background: var(--ob-card); border: 1px solid var(--ob-line); border-radius: 14px; padding: 15px 17px;
}
/* Colour rail rather than a fully tinted card: three loud panels side by side is noise, and the
   number is what the eye should land on. */
.et-stat::before { content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 4px; background: var(--ob-faint); }
.et-stat.over::before { background: var(--ob-danger); }
.et-stat.today::before { background: var(--ob-warning); }
.et-stat .lb { font-size: 11.5px; font-weight: 650; color: var(--ob-muted); text-transform: uppercase; letter-spacing: .3px; }
.et-stat .vl { font-size: 30px; font-weight: 750; line-height: 1.15; color: var(--ob-ink); }
.et-stat.over .vl { color: var(--ob-danger); }
.et-stat.today .vl { color: var(--ob-warning); }
.et-stat .hint { font-size: 11.5px; color: var(--ob-faint); }
/* Nothing overdue is good news — don't shout a red zero. */
.et-stat.quiet::before { background: var(--ob-line); }
.et-stat.quiet .vl { color: var(--ob-faint); }

.et-myboard { display: flex; gap: 14px; align-items: flex-start; overflow-x: auto; padding-bottom: 8px; }
.et-mycard { cursor: pointer; }

/* ---- match the team board's card metrics exactly ----
   /mine and /tasks render their columns into `.of-board-list-cards`, which had NO styling at all —
   the board's equivalent is `.of-cards` (flex column, 8px gap, 2px 8px padding). Cards here were
   stacking on whatever margins they happened to inherit, which is why the two views never looked
   the same. Same numbers as board.css now, with a 10px top so the first card clears the header
   instead of sitting flush against it. */
.of-board-list-cards {
  flex: 1; min-height: 8px; overflow-y: auto;
  display: flex; flex-direction: column; gap: 8px;
  padding: 10px 8px 8px;
}
/* Card internals: identical to .of-board-card in board.css. */
.et-mycard .body { padding: 9px 11px 10px; }
.et-mycard .of-board-card-badges { row-gap: 11px; }

/* The team board's own card list ships 2px of top padding, so its first card sits flush under the
   column header. Same 10px as the other two views — stated here rather than in board.css so that
   file stays re-copyable from OneBloc canon. */
.of-cards { padding-top: 10px; }
.et-boardtag { display: inline-flex; align-items: center; gap: 5px; font-size: 10.5px; color: var(--ob-muted); }
.et-boardtag .dot { width: 7px; height: 7px; border-radius: 50%; background: var(--bc, var(--acc)); flex: none; }

/* Clickable variant on All tasks: the card body opens the panel, this jumps to the board. It is a
   real <a> inside a clickable div, so it stops propagation and needs to look like its own target. */
.et-boardtag.go {
  margin-top: 9px; max-width: 100%; padding: 3px 8px 3px 7px; border-radius: 999px;
  border: 1px solid color-mix(in srgb, var(--bc) 22%, var(--ob-line));
  background: color-mix(in srgb, var(--bc) 6%, #fff);
  text-decoration: none; transition: background .12s, border-color .12s, color .12s;
}
.et-boardtag.go .nm { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.et-boardtag.go .bi { font-size: 13px; margin-left: -2px; opacity: .55; transition: opacity .12s, transform .12s; }
.et-boardtag.go:hover {
  background: color-mix(in srgb, var(--bc) 13%, #fff);
  border-color: color-mix(in srgb, var(--bc) 55%, transparent);
  color: var(--ob-ink);
}
.et-boardtag.go:hover .bi { opacity: 1; transform: translateX(2px); }

/* ---------- boards grid: each board wears its own accent ---------- */
.et-boardgrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(272px, 1fr)); gap: 18px; }
.et-boardcard {
  --bc: var(--acc);
  position: relative; display: flex; flex-direction: column; overflow: hidden;
  text-decoration: none; color: inherit; background: var(--ob-card);
  border: 1px solid var(--ob-line); border-radius: 16px;
  box-shadow: 0 1px 2px rgba(16, 33, 80, .05);
  transition: transform .12s, box-shadow .12s, border-color .12s, opacity .12s;
}
.et-boardcard:hover { transform: translateY(-2px); box-shadow: 0 10px 24px -10px rgba(16, 33, 80, .22); border-color: var(--bc); }
/* Board accent as a real colour field, not a 6px sliver — that strip was the whole reason the page
   read as grey and lifeless. color-mix keeps it a tint, so the title stays legible on any accent. */
/* Header = icon + board name, on one vertically-centred row. The old rule set a fixed 62px height
   with `padding: 14px 16px 0` — top padding only — so `align-items:center` was centring inside a box
   that had already been shoved down 14px, and the icon sat visibly high in an otherwise empty band. */
.et-boardcard .hd {
  display: flex; align-items: center; gap: 12px;
  padding: 14px 16px; min-height: 66px;
  background: linear-gradient(135deg, color-mix(in srgb, var(--bc) 22%, #fff), color-mix(in srgb, var(--bc) 7%, #fff));
  border-bottom: 1px solid color-mix(in srgb, var(--bc) 20%, var(--ob-line));
}
.et-boardcard .ico {
  width: 34px; height: 34px; flex: none; border-radius: 10px; background: var(--bc); color: #fff;
  display: inline-flex; align-items: center; justify-content: center; font-size: 16px;
  box-shadow: 0 2px 6px -1px color-mix(in srgb, var(--bc) 55%, transparent);
}
.et-boardcard .grip {
  flex: none; margin-left: auto; align-self: center;
  color: color-mix(in srgb, var(--bc) 65%, var(--ob-muted));
  font-size: 15px; cursor: grab; opacity: 0; transition: opacity .12s;
}
.et-boardcard:hover .grip { opacity: 1; }
.et-boardcard .bd { padding: 12px 16px 0; flex: 1; }
/* Two lines then ellipsis: a long board name must not push the card taller than its neighbours and
   break the grid's alignment. */
.et-boardcard .nm {
  flex: 1; min-width: 0; font-weight: 700; font-size: 15px; line-height: 1.25;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.et-boardcard .meta { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; }
.et-boardcard .kind { font-size: 11px; font-weight: 650; color: var(--bc); text-transform: uppercase; letter-spacing: .3px; }
.et-boardcard .et-chip.private { color: var(--ob-warning); border-color: color-mix(in srgb, var(--ob-warning) 35%, var(--ob-line)); }
.et-boardcard .cols { display: flex; gap: 5px; flex-wrap: wrap; margin-top: 11px; }
.et-boardcard .col {
  font-size: 10.5px; font-weight: 600; color: var(--ob-muted);
  background: var(--ob-bg); border-radius: 5px; padding: 3px 7px; white-space: nowrap;
}
.et-boardcard .ft {
  display: flex; align-items: center; gap: 12px; padding: 13px 16px;
  margin-top: 12px; border-top: 1px solid var(--ob-line); font-size: 12px; color: var(--ob-muted);
}
.et-boardcard .stat b { color: var(--ob-ink); }
.et-boardcard .stat.over, .et-boardcard .stat.over b { color: var(--ob-danger); font-weight: 700; }
.et-boardcard .stat.ok { color: var(--ob-success); font-weight: 600; }
.et-boardcard .upd { margin-left: auto; font-size: 11px; color: var(--ob-faint); }
/* Drag state: the lifted card fades and tilts, the gap shows where it will land. */
.et-boardcard.dragging { opacity: .4; transform: rotate(1.5deg); }
.et-boardcard.dropbefore { box-shadow: -4px 0 0 0 var(--acc), 0 10px 24px -10px rgba(16, 33, 80, .22); }

/* ---------- inline deadline editor in the card panel ---------- */
.et-deadline .of-section-head { display: flex; align-items: center; gap: 10px; }
.et-deadline .et-due { font-size: 11px; }
.et-quickdates { display: flex; flex-wrap: wrap; gap: 6px; margin: 10px 0 12px; }
.et-qd {
  font-family: inherit; font-size: 12px; font-weight: 600; cursor: pointer;
  padding: 6px 12px; border-radius: 999px; white-space: nowrap;
  border: 1px solid var(--ob-line); background: var(--ob-card); color: var(--ob-slate);
  transition: border-color .12s, background .12s, color .12s;
}
.et-qd:hover { border-color: var(--acc); color: var(--acc-deep); background: var(--acc-soft); }
.et-qd.sel { border-color: var(--acc); background: var(--acc); color: #fff; }
.et-qd.ghost { border-style: dashed; color: var(--ob-muted); font-weight: 500; }
.et-qd.ghost:hover { border-color: var(--ob-danger); color: var(--ob-danger); background: transparent; }
.et-datepick { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
/* The quick-action button at the top of the panel scrolls here instead of opening a dialog —
   without a cue the click looks like it did nothing when the section is already on screen. */
@keyframes etFlash { 0% { background: var(--acc-soft); } 100% { background: transparent; } }
.et-deadline.flash { animation: etFlash 1s ease-out; border-radius: 10px; }

/* ---------- handover strip: drag a card onto a face to reassign ---------- */
.et-handover {
  display: flex; align-items: center; gap: 10px; flex: none;
  padding: 9px 16px; background: var(--ob-card); border-bottom: 1px solid var(--ob-line);
  overflow-x: auto;
}
.et-handover .lb {
  font-size: 11.5px; font-weight: 650; color: var(--ob-muted); white-space: nowrap;
  display: inline-flex; align-items: center; gap: 6px; flex: none;
}
.et-handover .ppl { display: flex; align-items: center; gap: 7px; }
.et-person-chip {
  display: inline-flex; align-items: center; gap: 7px; flex: none;
  padding: 4px 11px 4px 4px; border: 1px solid var(--ob-line); border-radius: 999px;
  background: var(--ob-card); cursor: pointer; font-family: inherit;
  font-size: 12px; color: var(--ob-slate); white-space: nowrap;
  transition: border-color .12s, background .12s, transform .08s;
}
.et-person-chip .of-avatar { width: 24px; height: 24px; font-size: 10px; }
.et-person-chip:hover { border-color: var(--ob-faint); }
.et-person-chip.sel { border-color: var(--acc); background: var(--acc-soft); color: var(--acc-deep); font-weight: 600; }
/* Dragging a card over a face: the target has to read as "let go here". Scale + accent ring, and
   the label goes bold so it is legible even while a card is floating over it. */
.et-person-chip.over {
  border-color: var(--acc); background: var(--acc-soft); color: var(--acc-deep);
  font-weight: 700; transform: scale(1.06);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--acc) 22%, transparent);
}
.et-handover .clr {
  border: none; background: none; font-family: inherit; font-size: 11.5px; font-weight: 600;
  color: var(--acc-deep); cursor: pointer; padding: 4px 6px; white-space: nowrap; flex: none;
}
/* The accountable owner among the card avatars — accent ring, watchers keep the white ring. */
.of-card-avatars .of-avatar.assignee { border-color: var(--acc, #0F9E8E); }
.et-task .t { font-size: 13px; font-weight: 550; line-height: 1.35; }
.et-task .meta { display: flex; align-items: center; gap: 8px; margin-top: 5px; flex-wrap: wrap; }
.et-chip { font-size: 10.5px; color: var(--ob-muted); background: var(--ob-bg); border: 1px solid var(--ob-line); border-radius: 6px; padding: 2px 7px; display: inline-flex; align-items: center; gap: 4px; }
.et-chip .u { color: var(--acc-deep); }
.et-due { font-size: 11px; font-weight: 700; padding: 2px 8px; border-radius: 7px; white-space: nowrap; font-family: var(--mono); }
.et-due.over { background: var(--ob-danger-soft, #FBEAE6); color: var(--ob-danger); }
.et-due.today { background: var(--ob-warning-soft, #FBF1DE); color: var(--ob-warning); }
.et-due.soon, .et-due.neutral { background: var(--ob-bg); color: var(--ob-muted); border: 1px solid var(--ob-line); }
.et-empty { padding: 30px 19px; text-align: center; color: var(--ob-faint); font-size: 12.5px; }
.et-filterbar { display: none; align-items: center; gap: 8px; padding: 10px 19px; background: var(--acc-soft); border-bottom: 1px solid var(--ob-line); font-size: 12px; color: var(--acc-deep); }
.et-filterbar.show { display: flex; }
.et-filterbar button { margin-left: auto; border: none; background: none; color: var(--acc-deep); font-weight: 700; cursor: pointer; font-size: 12px; font-family: inherit; }

@media (max-width: 940px) {
  .et-app { grid-template-columns: 1fr; }
  .et-rail { position: static; height: auto; flex-direction: row; align-items: center; flex-wrap: wrap; }
  .et-rail .et-navlabel, .et-rail .et-spacer { display: none; }
  .et-grid { grid-template-columns: 1fr; }
  .et-stats { grid-template-columns: repeat(2, 1fr); }
}

/* ============================================================================
   /help — the user guide.

   A reading layout, not an app screen: one measured column so the prose is
   actually readable, with the contents list parked beside it on a wide screen
   and folded above it on a phone.
   ============================================================================ */
.et-helpwrap { display: grid; grid-template-columns: 210px minmax(0, 1fr); gap: 40px; align-items: start; }

.et-helptoc { position: sticky; top: 24px; display: flex; flex-direction: column; gap: 2px; }
.et-helptoc .t {
  font-size: 11px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
  color: var(--ob-faint); margin-bottom: 8px;
}
.et-helptoc a {
  font-size: 13px; color: var(--ob-muted); text-decoration: none;
  padding: 6px 10px; border-radius: 8px; border-left: 2px solid transparent;
}
.et-helptoc a:hover { background: var(--ob-line-soft); color: var(--ob-ink); border-left-color: var(--acc); }

/* ~68 characters a line. Wider than this and the eye loses the start of the next one. */
.et-help { max-width: 720px; }
.et-help section { margin-bottom: 46px; scroll-margin-top: 20px; }
.et-help h2 {
  font-size: 21px; font-weight: 650; letter-spacing: -.02em; color: var(--ob-ink);
  margin: 0 0 14px; padding-bottom: 10px; border-bottom: 1px solid var(--ob-line);
}
.et-help h3 { font-size: 15px; font-weight: 700; color: var(--ob-ink); margin: 26px 0 8px; }
.et-help p { font-size: 14px; line-height: 1.65; color: var(--ob-muted); margin: 0 0 12px; }
.et-help p.lead { font-size: 15.5px; line-height: 1.6; color: var(--ob-ink); }
.et-help ul, .et-help ol { font-size: 14px; line-height: 1.65; color: var(--ob-muted); padding-left: 20px; margin: 0 0 12px; }
.et-help li { margin-bottom: 7px; }
.et-help b { color: var(--ob-ink); font-weight: 650; }

/* The things worth stopping for. Sparing on purpose — a page where everything is
   highlighted is a page where nothing is. */
.et-help-note {
  background: var(--acc-soft, #E6F5F3); border-left: 3px solid var(--acc);
  border-radius: 0 10px 10px 0; padding: 12px 15px !important;
  color: var(--acc-deep, #0A6F63) !important; font-size: 13.5px !important;
}
.et-help-note b { color: inherit; }

.et-help-steps li { margin-bottom: 11px; }

.et-help-dl { margin: 0 0 12px; }
.et-help-dl dt { font-size: 14px; font-weight: 700; color: var(--ob-ink); margin-top: 14px; }
.et-help-dl dd { font-size: 14px; line-height: 1.6; color: var(--ob-muted); margin: 4px 0 0; padding-left: 0; }

.et-help-table { width: 100%; border-collapse: collapse; font-size: 13.5px; margin: 0 0 14px; }
.et-help-table th {
  text-align: left; font-size: 11px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase;
  color: var(--ob-faint); padding: 0 12px 8px 0; border-bottom: 1px solid var(--ob-line);
}
.et-help-table td { padding: 11px 12px 11px 0; border-bottom: 1px solid var(--ob-line); color: var(--ob-muted); line-height: 1.55; vertical-align: top; }
.et-help-table td:first-child { white-space: nowrap; width: 1%; }

.et-help-stages { display: flex; flex-direction: column; gap: 2px; margin: 0 0 14px; }
.et-help-stages .s { display: flex; align-items: baseline; gap: 10px; padding: 9px 0; border-bottom: 1px solid var(--ob-line); font-size: 13.5px; }
.et-help-stages .s:last-child { border-bottom: none; }
.et-help-stages .dot { width: 9px; height: 9px; border-radius: 50%; flex: none; }
.et-help-stages b { min-width: 116px; color: var(--ob-ink); }
.et-help-stages span:last-child { color: var(--ob-muted); }

.et-help-page { border: 1px solid var(--ob-line); border-radius: 12px; padding: 16px 18px; margin-bottom: 12px; }
.et-help-page header { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; }
.et-help-page h3 { margin: 0; font-size: 15px; display: flex; align-items: center; gap: 8px; }
.et-help-page h3 .bi { color: var(--acc); }
.et-help-page .who {
  margin-left: auto; font-size: 10.5px; font-weight: 700; letter-spacing: .03em;
  padding: 3px 9px; border-radius: 999px; white-space: nowrap;
}
.et-help-page .who.yes { background: var(--acc-soft, #E6F5F3); color: var(--acc-deep, #0A6F63); }
.et-help-page .who.no { background: var(--ob-line-soft); color: var(--ob-faint); }
/* A page you cannot open is dimmed, NOT hidden: staff ask "where's the team view?" and a guide
   that omits it reads as a missing feature rather than one that isn't theirs. */
.et-help-page.na { opacity: .62; }
.et-help-page p:last-child, .et-help-page ul:last-child { margin-bottom: 0; }

@media (max-width: 940px) {
  /* min-width:0 on both, for the reason in the .et-app rule above: a grid item will not shrink
     below its content, and the contents row is what pushed the page 2px wide — enough to make the
     whole document scroll sideways and drag the fixed chrome out of alignment with it. */
  .et-helpwrap { grid-template-columns: minmax(0, 1fr); gap: 20px; min-width: 0; }
  .et-helpwrap > * { min-width: 0; }
  .et-helptoc {
    position: static; flex-direction: row; flex-wrap: wrap; gap: 6px;
    padding-bottom: 16px; border-bottom: 1px solid var(--ob-line);
  }
  .et-helptoc .t { width: 100%; margin-bottom: 4px; }
  .et-helptoc a {
    border: 1px solid var(--ob-line); border-radius: 999px; padding: 0 13px;
    /* A jump link is a tap target like any other. */
    min-height: 40px; display: inline-flex; align-items: center;
  }
  .et-help { max-width: none; }
  /* A two-column table of nowrap labels does not fit a phone; stack each row instead of making
     the page scroll. */
  .et-help-table thead { display: none; }
  .et-help-table, .et-help-table tbody, .et-help-table tr, .et-help-table td { display: block; width: auto; }
  .et-help-table tr { padding: 11px 0; border-bottom: 1px solid var(--ob-line); }
  .et-help-table td { border: none; padding: 0; }
  .et-help-table td:first-child { width: auto; white-space: normal; margin-bottom: 3px; }
  .et-help-stages .s { flex-wrap: wrap; }
  .et-help-stages b { min-width: 0; }
  .et-help-stages span:last-child { width: 100%; padding-left: 19px; }
}

/* Printing it is a legitimate way to hand this to somebody — drop the chrome, keep the words. */
@media print {
  .et-helptoc, .et-topbar .actions { display: none !important; }
  .et-help { max-width: none; }
  .et-help section { page-break-inside: avoid; margin-bottom: 24px; }
  .et-help-note { border-left-color: #999; background: #f4f4f4 !important; color: #222 !important; }
}

/* ============================================================================
   /quick — task capture opened from the PMS.

   Deliberately NOT the app shell: this is a box to type in, reached from another
   product. Wrapping it in a navigation rail makes it feel like you were dumped
   somewhere else rather than handed a form.
   ============================================================================ */
.et-quickpage {
  min-height: 100vh; background: var(--ob-bg);
  display: flex; flex-direction: column; align-items: center;
  padding: 28px 16px calc(28px + env(safe-area-inset-bottom));
}
.et-quickcard {
  width: 100%; max-width: 460px; background: var(--ob-card);
  border: 1px solid var(--ob-line); border-radius: 16px; padding: 22px;
  box-shadow: 0 6px 28px rgba(15, 23, 42, .07);
}
.et-quickcard .hd { display: flex; align-items: center; gap: 12px; margin-bottom: 20px; }
.et-quickcard .hd .et-bloc { width: 36px; height: 36px; flex: none; }
.et-quickcard .hd h1 { margin: 0; font-size: 19px; font-weight: 650; letter-spacing: -.02em; color: var(--ob-ink); }
.et-quickcard .hd p { margin: 2px 0 0; font-size: 12.5px; color: var(--ob-faint); }

/* The property is a statement of fact, not a field — it came from the page you were on. */
.et-quickprop {
  display: flex; align-items: center; gap: 9px; margin-bottom: 16px;
  padding: 11px 13px; border-radius: 11px;
  background: var(--acc-soft, #E6F5F3); border: 1px solid var(--acc);
  color: var(--acc-deep, #0A6F63); font-size: 13.5px; font-weight: 650;
}
.et-quickprop .bi { font-size: 15px; }
.et-quickprop .whole {
  margin-left: auto; font-size: 10.5px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .04em; opacity: .75;
}

.et-quickmsg { padding: 11px 13px; border-radius: 10px; font-size: 13px; margin-bottom: 16px; line-height: 1.5; }
.et-quickmsg.warn { background: var(--ob-warning-soft, #FBF1DE); border: 1px solid #e8d3a8; color: #8a5a12; }
.et-quickmsg.bad { background: var(--ob-danger-soft, #FBEAE6); border: 1px solid #f0c9bf; color: #8f2f1c; }

/* Collapsed by default: it is context, and an open list of other people's tasks would compete
   with the field you are meant to be filling in. */
.et-quickopen { margin-bottom: 16px; font-size: 12.5px; }
.et-quickopen summary {
  cursor: pointer; color: var(--ob-warning, #B7791F); font-weight: 650;
  padding: 8px 0; list-style: none;
}
.et-quickopen summary::-webkit-details-marker { display: none; }
.et-quickopen summary::before { content: "⚠ "; }
.et-quickopen ul { list-style: none; margin: 4px 0 0; padding: 0 0 0 2px; }
.et-quickopen li { padding: 6px 0; border-top: 1px solid var(--ob-line); }
.et-quickopen a { color: var(--ob-ink); font-weight: 600; text-decoration: none; }
.et-quickopen a:hover { text-decoration: underline; }
.et-quickopen li span { display: block; color: var(--ob-faint); font-size: 11.5px; margin-top: 1px; }

.et-quickcard .ob-field { margin-bottom: 15px; }
.et-quickcard .ob-input { width: 100%; box-sizing: border-box; }
.et-quickcard textarea.ob-input { resize: vertical; font-family: inherit; }

.et-quickdue { display: flex; gap: 7px; margin-bottom: 8px; }
.et-quickdue button {
  flex: 1; min-height: 40px; border: 1px solid var(--ob-line); border-radius: 9px;
  background: var(--ob-card); color: var(--ob-muted);
  font-family: inherit; font-size: 13px; font-weight: 600; cursor: pointer;
}
.et-quickdue button.on { background: var(--acc); border-color: var(--acc); color: #fff; }

.et-quickboard { font-size: 12.5px; color: var(--ob-faint); margin: 0 0 15px; }
.et-btn.block { width: 100%; justify-content: center; min-height: 48px; font-size: 15px; }
.et-quickerr { color: var(--ob-danger); font-size: 13px; margin: 10px 0 0; }

.et-quickdone { text-align: center; padding: 8px 0; }
.et-quickdone .tick {
  width: 52px; height: 52px; border-radius: 50%; margin: 0 auto 14px;
  background: var(--ob-success-soft, #E3F3EA); color: var(--ob-success, #16895A);
  display: grid; place-items: center; font-size: 26px;
}
.et-quickdone h2 { margin: 0 0 6px; font-size: 18px; font-weight: 650; color: var(--ob-ink); }
.et-quickdone p { margin: 0 0 18px; font-size: 14px; color: var(--ob-muted); }
.et-quickdone .acts { display: flex; gap: 9px; }
.et-quickdone .acts > * { flex: 1; justify-content: center; }
.et-quickdone .back { display: inline-block; margin-top: 16px; font-size: 13px; color: var(--ob-faint); }

.et-quickfull { margin-top: 18px; font-size: 13px; color: var(--ob-faint); text-decoration: none; }
.et-quickfull:hover { color: var(--acc-deep, var(--acc)); }

@media (max-width: 480px) {
  .et-quickpage { padding: 0; }
  /* Edge to edge on a phone: a card with margins inside a browser chrome inside a PMS is too many
     nested boxes. */
  .et-quickcard { max-width: none; border: none; border-radius: 0; box-shadow: none; min-height: 100vh; }
}
