/* =============================================================================
   ESSENLIX SKILLS PLATFORM — "Atelier" redesign
   Single-stylesheet, framework-free, drop-in replacement for app/static/app.css
   -----------------------------------------------------------------------------
   • Everything is driven by CSS custom properties in :root (see "TOKENS").
   • Dark mode is pre-tokenized: add data-theme="dark" to <html> to enable.
   • Class names match the existing component inventory so templates change little.
   • Target: WCAG 2.1 AA. Primary green on white = 5.2:1; white on green = 5.2:1.
   ============================================================================= */

/* ----------------------------------------------------------------------------
   FONTS  (self-hosted Manrope, as today. Mono uses the system stack so no new
   font dependency is required. To match the mocks exactly you MAY self-host
   IBM Plex Mono and swap --font-mono — optional, not required.)
---------------------------------------------------------------------------- */
@font-face{
  font-family:"Manrope";
  src:url("/static/fonts/manrope.woff2") format("woff2");
  font-weight:400 800; font-style:normal; font-display:swap;
}

/* ----------------------------------------------------------------------------
   TOKENS — LIGHT (default)
---------------------------------------------------------------------------- */
:root{
  /* brand */
  --brand:#2F7A52;            /* primary green — actions, active states, focus  */
  --brand-strong:#276B45;     /* hover / pressed                                */
  --brand-tint:#EEF4EE;       /* faint green fill (chips, success bg, avatars)  */
  --brand-tint-border:#DCE8DB;
  --accent:#E08A3C;           /* orange — RESERVED for the attention dot only   */

  /* ink & surfaces */
  --ink:#1B1A17;              /* primary text                                   */
  --muted:#6F6B63;            /* secondary text (AA: 5.3:1 on white)            */
  --faint:#78756D;            /* meta / small labels (AA: 4.6:1 on white)       */
  --disabled:#A8A297;         /* placeholder / disabled (decorative only)       */
  --canvas:#F7F5F1;           /* page background (warm paper)                   */
  --surface:#FFFFFF;          /* cards, app bar                                 */
  --surface-2:#FAF8F4;        /* subtle inset panels, table header              */
  --line:#E7E2D9;             /* borders / dividers                             */
  --hairline:#F0ECE4;         /* lighter inner dividers (table rows)            */

  /* status — success */
  --ok:#2F7A52; --ok-ink:#1A4D2E; --ok-bg:#EEF4EE; --ok-border:#DCE8DB;
  /* status — warning */
  --warn:#8A6A1F; --warn-bg:#FBF3E4; --warn-border:#EBD9B0; --warn-icon:#C98A1E;
  /* status — error */
  --bad:#B5482F; --bad-bg:#FBEDEA; --bad-border:#F0CFC8;

  /* workflow-kind taxonomy */
  --kind-det:#3A6EA5; --kind-det-border:#CDDDF0;   /* deterministic (blue)      */
  --kind-agt:#0D8A7E; --kind-agt-border:#B8E3DD;   /* agentic (teal)            */

  /* type */
  --font-sans:"Manrope", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --font-mono:ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, monospace;

  /* radius */
  --r-card:14px; --r-control:10px; --r-input:10px; --r-chip:8px; --r-pill:999px; --r-sm:6px;

  /* elevation */
  --shadow-sm:0 1px 2px rgba(40,36,28,.04);
  --shadow-card:0 1px 3px rgba(40,36,28,.06);
  --shadow-pop:0 12px 32px rgba(40,36,28,.10);
  --ring:0 0 0 3px rgba(47,122,82,.18);

  /* spacing scale (4px base) */
  --s1:4px; --s2:8px; --s3:12px; --s4:16px; --s5:20px; --s6:24px;
  --s7:32px; --s8:44px; --s9:56px;

  /* motion */
  --t-fast:120ms; --t:200ms; --ease:cubic-bezier(.2,.6,.2,1);

  /* layout */
  --page-max:1600px; --appbar-h:64px; --gutter:40px;
}

/* ----------------------------------------------------------------------------
   TOKENS — DARK  (starting point; enable with <html data-theme="dark">)
   Only the values that should change are overridden — every component below
   reads tokens, so dark mode needs no per-component rules.
---------------------------------------------------------------------------- */
:root[data-theme="dark"]{
  --brand:#4FAE78; --brand-strong:#5FBF87; --brand-tint:#1E2D24; --brand-tint-border:#2E463A;
  --accent:#E89B52;

  --ink:#F2EFE9; --muted:#B7B2A8; --faint:#8E897F; --disabled:#6B665D;
  --canvas:#1A1916; --surface:#211F1B; --surface-2:#262420;
  --line:#36322B; --hairline:#2B2925;

  --ok:#4FAE78; --ok-ink:#A9D9BD; --ok-bg:#1E2D24; --ok-border:#2E463A;
  --warn:#D9B36A; --warn-bg:#2C2616; --warn-border:#4A3F22; --warn-icon:#D9B36A;
  --bad:#E08A77; --bad-bg:#2E1C18; --bad-border:#4A2A22;

  --kind-det:#7FAAD8; --kind-det-border:#2C3D52;
  --kind-agt:#4FC0B2; --kind-agt-border:#234742;

  --shadow-sm:0 1px 2px rgba(0,0,0,.30);
  --shadow-card:0 1px 3px rgba(0,0,0,.40);
  --shadow-pop:0 12px 32px rgba(0,0,0,.45);
  --ring:0 0 0 3px rgba(79,174,120,.30);
}

/* ----------------------------------------------------------------------------
   RESET & BASE
---------------------------------------------------------------------------- */
*,*::before,*::after{box-sizing:border-box}
html,body{margin:0;padding:0}
body{
  font-family:var(--font-sans);
  background:var(--canvas);
  color:var(--ink);
  font-size:14px; line-height:1.5;
  -webkit-font-smoothing:antialiased; text-rendering:optimizeLegibility;
}
h1,h2,h3{margin:0; letter-spacing:-.02em; color:var(--ink)}
h1{font-size:28px; font-weight:800; line-height:1.2}
h2{font-size:22px; font-weight:800; line-height:1.2; letter-spacing:-.01em}
h3{font-size:17px; font-weight:700; line-height:1.3; letter-spacing:-.01em}
p{margin:0}
a{color:var(--brand); text-decoration:none}
a:hover{color:var(--brand-strong)}
small,.meta{color:var(--faint)}
.mono{font-family:var(--font-mono)}
.page{max-width:var(--page-max); margin:0 auto; padding:32px var(--gutter) 56px}

/* uppercase tracked micro-label (used for field labels, section eyebrows) */
.eyebrow{font:600 11px/1 var(--font-mono); letter-spacing:.14em; text-transform:uppercase; color:var(--faint)}

/* ----------------------------------------------------------------------------
   APP BAR
---------------------------------------------------------------------------- */
.appbar{
  height:var(--appbar-h); background:var(--surface);
  border-bottom:1px solid var(--line);
  display:flex; align-items:center; justify-content:space-between;
  padding:0 32px; position:sticky; top:0; z-index:50;
}
.appbar__brand{display:inline-flex; align-items:center}
.appbar__brand img{height:24px; width:auto; display:block}
.appbar__nav{display:inline-flex; align-items:center; gap:22px}
.appbar__email{font:500 13px/1 var(--font-sans); color:var(--faint)}
.appbar__link{font:500 13px/1 var(--font-sans); color:var(--faint)}
.appbar__link:hover{color:var(--ink)}
.appbar__link.is-active{color:var(--brand); font-weight:700; border-bottom:2px solid var(--brand); padding-bottom:2px}

.avatar{
  width:30px; height:30px; border-radius:var(--r-pill);
  background:var(--brand-tint); border:1px solid var(--brand-tint-border);
  display:inline-flex; align-items:center; justify-content:center;
  font:700 13px/1 var(--font-sans); color:var(--brand);
}

/* Narrow screens: the bar wraps to two rows rather than overflowing. Four
   items plus an avatar do not fit beside the wordmark at 375px, and an FAE
   pasting a WhatsApp thread is plausibly on a phone. */
@media (max-width:720px){
  .appbar{height:auto; flex-wrap:wrap; padding:10px 16px; gap:6px}
  .appbar__brand img{height:20px}
  .appbar__nav{width:100%; gap:18px}
  .appbar__nav .usermenu{margin-left:auto}
}

/* Account menu. <details> so it opens with no JS at all; app.js only adds
   click-outside and Escape, which are conveniences rather than requirements. */
.usermenu{position:relative}
.usermenu__summary{
  list-style:none; cursor:pointer; display:inline-flex; align-items:center;
  border-radius:var(--r-pill);
}
.usermenu__summary::-webkit-details-marker{display:none}
.usermenu__summary:focus-visible{outline:none; box-shadow:var(--ring)}
.usermenu[open] .avatar{border-color:var(--brand)}
.usermenu__panel{
  position:absolute; top:calc(100% + 10px); right:0; min-width:210px;
  background:var(--surface); border:1px solid var(--line);
  border-radius:var(--r-card); box-shadow:var(--shadow-pop);
  padding:6px; z-index:60;
}
.usermenu__email{
  font:500 12px/1.4 var(--font-sans); color:var(--faint);
  padding:8px 10px 10px; margin:0; word-break:break-all;
  border-bottom:1px solid var(--line);
}
.usermenu__item{
  display:block; padding:9px 10px; border-radius:var(--r-sm);
  font:500 13px/1 var(--font-sans); color:var(--ink);
}
.usermenu__item:hover{background:var(--brand-tint)}
.usermenu__item.is-active{color:var(--brand); font-weight:700}

/* Attachment list on an entry. */
.attach{list-style:none; margin:8px 0 0; padding:0;
  display:flex; flex-direction:column; gap:6px}
.attach__row{display:flex; align-items:center; gap:10px;
  font:500 13px/1 var(--font-sans)}
.attach__name{color:var(--brand); font-weight:600}
.attach__meta{color:var(--faint); font-size:12px}
.attach__label{color:var(--muted); font-size:12px; font-style:italic}
.attach__rm{border:none; background:none; cursor:pointer; color:var(--faint);
  font:400 16px/1 var(--font-sans); padding:0 4px}
.attach__rm:hover{color:var(--bad)}
.attach-add{display:flex; gap:8px; align-items:center; flex-wrap:wrap;
  margin-top:12px}
.attach-add .input{padding:8px 10px; font-size:13px; width:auto}

/* Page title with a right-aligned action (Database -> Export). */
.page-head{
  display:flex; align-items:flex-start; justify-content:space-between;
  gap:24px; flex-wrap:wrap;
}
.page-head > div{min-width:0}
.page-head .btn,.page-head .btn-ghost{flex:none; margin-top:4px}

/* ----------------------------------------------------------------------------
   VERIFY — the review layout (Option B, 2026-09-20)
   The page used to split left/right by data policy: restricted on the left,
   saved on the right. That is a real boundary but it is not the reviewer's
   task, so the eye crossed the gutter on every step and the left column ran
   out 1,008px before the right one did. It now reads in the order the decision
   is made, with the documents alongside rather than below.
---------------------------------------------------------------------------- */
.verify-layout{
  display:grid; grid-template-columns:minmax(0,1.62fr) minmax(0,1fr);
  gap:20px; margin-top:20px; align-items:start;
}
.verify-main,.verify-rail{display:flex; flex-direction:column; gap:16px; min-width:0}
.verify-main > form{display:flex; flex-direction:column; gap:16px; min-width:0}
.verify-main > form[hidden]{display:none}

/* Sticky so the documents stay on screen while the answer is being typed --
   that is the moment the quotes are wanted. It scrolls inside itself when it
   outgrows the viewport, so a long grounding answer cannot trap the page. */
.verify-rail{
  position:sticky; top:calc(var(--appbar-h) + 16px);
  max-height:calc(100vh - var(--appbar-h) - 32px); overflow-y:auto;
  scrollbar-width:thin;
}

.verify-actions{
  display:flex; flex-wrap:wrap; align-items:center; justify-content:space-between;
  gap:12px 16px; background:var(--surface); border:1px solid var(--line);
  border-radius:var(--r-card); padding:16px 20px; box-shadow:var(--shadow-card);
}
.verify-actions__end{display:flex; flex-wrap:wrap; align-items:center; gap:10px}
/* The reject and discard forms carry their own top margins from the markup
   they came from; inside the bar they are flex items and must not. */
.verify-actions__end form{margin-top:0 !important}

.verify-details > summary{
  cursor:pointer; font-weight:700; font-size:15px; list-style:none;
}
.verify-details > summary::-webkit-details-marker{display:none}
.verify-details > summary::before{content:"\25B8"; color:var(--muted); margin-right:8px}
.verify-details[open] > summary::before{content:"\25BE"}
.verify-details__body{display:flex; flex-direction:column; gap:16px; margin-top:16px}
/* Nested cards inside the disclosure are already on a card ground: flatten them
   so it does not read as boxes inside a box. */
.verify-details__body .card{
  border:0; border-top:1px solid var(--hairline); border-radius:0;
  box-shadow:none; padding:16px 0 0; background:transparent;
}
.verify-details__body .card:first-child{border-top:0; padding-top:0}

@media (max-width:1100px){
  .verify-layout{grid-template-columns:1fr}
  .verify-rail{position:static; max-height:none; overflow:visible}
}

/* The flag chips on the dashboard are links now, to the page that explains
   them. They keep the chip's shape and gain the affordance. */
.chip--flag{text-decoration:none; cursor:pointer}
.chip--flag:hover{border-color:var(--brand); color:var(--ink); background:var(--surface-2)}

/* The checks page's own form row. It deliberately does NOT reuse
   .tagedit__form, which is absolutely positioned to hang out of the dashboard's
   <details> popup and, borrowed here, rendered over the app bar. */
.checks-form{display:flex; gap:8px; align-items:center; flex-wrap:wrap; margin-top:14px}
.checks-form .input{min-width:132px}

/* The checks page: one row per reason or flagged passage. Not cards -- they sit
   inside a card already, and boxes inside a box flatten the hierarchy. */
.checks{display:flex; flex-direction:column; gap:14px}
.check{border-left:3px solid var(--line); padding-left:14px}
.check__kind{font-family:var(--font-mono); font-size:11px; font-weight:600;
  letter-spacing:.09em; text-transform:uppercase; color:var(--faint); margin:0 0 4px}
.check__detail{font-size:14px; line-height:1.5; margin:0}
.check__where{font-size:12.5px; color:var(--muted); margin:4px 0 0}

/* The nav row below has to sit in the same place on every document, and its own
   row was only half of that: a one-line filename and a two-line one still put
   it 34px apart, so it went on moving as you clicked through the corpus. Reserve
   two lines of title whatever the name is. The size steps down on a narrow
   screen so a long filename still fits those two lines instead of taking four. */
.page-head--doc h1{font-size:clamp(20px,4.4vw,28px); min-height:2.4em}

/* Page navigation on the document preview. Its own row on purpose: while these
   buttons shared .page-head's wrapping flex row with the <h1>, a long filename
   pushed them onto a second line, so the same control sat in a different place
   on different documents at one window width. A row of its own cannot wrap.
   The count sits between the arrows -- it is navigation, not metadata. */
.pagenav{
  display:flex; align-items:center; gap:10px; flex-wrap:nowrap;
  margin-top:16px; padding-bottom:16px; border-bottom:1px solid var(--hairline);
}
.pagenav__count{
  font-family:var(--font-mono); font-size:12px; color:var(--muted);
  font-variant-numeric:tabular-nums; white-space:nowrap; margin-inline:auto;
}
.pagenav .btn,.pagenav .btn-ghost{flex:none; margin-top:0; white-space:nowrap}
.pagenav .is-disabled{opacity:.38; pointer-events:none}
@media (max-width:520px){
  .pagenav{gap:6px}
  .pagenav__count{font-size:11px}
}

/* Second-level tabs (Queue, Admin). */
.subnav{
  display:flex; gap:4px; margin:0 0 24px;
  border-bottom:1px solid var(--line);
}
.subnav__link{
  display:inline-flex; align-items:center; gap:7px; padding:10px 12px;
  font:500 13px/1 var(--font-sans); color:var(--faint);
  border-bottom:2px solid transparent; margin-bottom:-1px;
}
.subnav__link:hover{color:var(--ink)}
.subnav__link.is-active{color:var(--brand); font-weight:700; border-bottom-color:var(--brand)}
.subnav__count{
  font:700 11px/1 var(--font-sans); padding:3px 8px; border-radius:var(--r-pill);
  background:var(--brand-tint); border:1px solid var(--brand-tint-border);
  color:var(--brand);
}
/* Zero recedes: an empty half of the queue should not compete with a full one. */
.subnav__count.is-zero{
  background:transparent; border-color:var(--line); color:var(--faint);
}

/* attention dot — the ONE use of --accent */
.attention-dot{
  width:7px; height:7px; border-radius:var(--r-pill); background:var(--accent);
  display:inline-block; animation:pulse 1.3s ease-in-out infinite;
}
@keyframes pulse{0%,100%{opacity:1}50%{opacity:.3}}

/* ----------------------------------------------------------------------------
   BUTTONS
---------------------------------------------------------------------------- */
.btn,.btn-ghost,.btn-sm{
  display:inline-flex; align-items:center; gap:8px; justify-content:center;
  font-family:var(--font-sans); font-weight:700; font-size:14px; line-height:1;
  border-radius:var(--r-control); border:1px solid transparent; cursor:pointer;
  padding:12px 20px; transition:background var(--t-fast) var(--ease),
    border-color var(--t-fast) var(--ease), color var(--t-fast) var(--ease);
  text-decoration:none; white-space:nowrap;
}
/* primary — WHITE text on green (replaces the old dark-on-green) */
.btn{background:var(--brand); color:#fff}
.btn:hover{background:var(--brand-strong); color:#fff}
/* ghost — white, bordered, muted text; hover gains brand border */
.btn-ghost{background:var(--surface); color:var(--muted); border-color:var(--line); font-weight:600}
.btn-ghost:hover{border-color:var(--brand); color:var(--ink)}
/* compact — for tables/lists */
.btn-sm{padding:8px 14px; font-size:13px; border-radius:var(--r-chip)}
.btn-sm.btn{background:var(--brand); color:#fff}
.btn-sm.btn-ghost{background:var(--surface); color:var(--muted); border-color:var(--line)}

/* Two ways to end a ticket, and they must not look alike.
   Reject records a judgement and can be undone. Discard deletes. Both were
   btn-ghost, which made them read like "Merge" and every other link on the
   page. Compound selectors and placed after .btn-sm, or that rule's background
   wins on source order. Tokens only, so the dark theme follows. */
.btn-warn,.btn-sm.btn-warn{
  background:var(--warn-bg); color:var(--warn); border-color:var(--warn-border);
}
.btn-warn:hover,.btn-sm.btn-warn:hover{
  border-color:var(--warn-icon); color:var(--warn-icon);
}
.btn-danger,.btn-sm.btn-danger{
  background:var(--bad-bg); color:var(--bad); border-color:var(--bad-border);
}
.btn-danger:hover,.btn-sm.btn-danger:hover{
  background:var(--bad); color:var(--surface); border-color:var(--bad);
}

:where(.btn,.btn-ghost,.btn-sm,.input,.opt,a):focus-visible{outline:none; box-shadow:var(--ring)}

/* ----------------------------------------------------------------------------
   CARD
---------------------------------------------------------------------------- */
.card{
  background:var(--surface); border:1px solid var(--line);
  border-radius:var(--r-card); padding:30px; box-shadow:var(--shadow-sm);
}
.card__sub{color:var(--muted); margin-top:6px; max-width:760px}

/* A bilingual body: the two languages are one block of content, so they share
   one measure. The Chinese half used .card__sub -- a subtitle class, capped at
   760px -- while the English sibling had no cap, so the same answer wrapped at
   two different widths. 760px is the measure the design system already picked;
   English at full width was ~150 characters a line, well past comfortable. */
.answer-body{max-width:760px}
.answer-body--zh{color:var(--muted); margin-top:6px}

/* ----------------------------------------------------------------------------
   WORKFLOW CARDS (home) — flat, description visible (no flip)
---------------------------------------------------------------------------- */
.skill-grid{display:grid; grid-template-columns:repeat(auto-fill,minmax(300px,1fr)); gap:18px}
.skill-card{
  background:var(--surface); border:1px solid var(--line); border-radius:var(--r-card);
  padding:22px; display:flex; flex-direction:column; gap:14px;
  box-shadow:var(--shadow-sm); transition:box-shadow var(--t) var(--ease),
    border-color var(--t) var(--ease); text-decoration:none; color:inherit;
}
.skill-card:hover{box-shadow:var(--shadow-card); border-color:var(--brand-tint-border)}
.skill-card h3{min-height:44px}
.skill-card p{color:var(--muted); font-size:13.5px; flex:1}
.skill-card .start{display:inline-flex; align-items:center; gap:6px; font-weight:700; color:var(--brand)}

/* ----------------------------------------------------------------------------
   TAGS / KIND CHIPS
---------------------------------------------------------------------------- */
.tag{
  display:inline-flex; align-items:center; gap:7px;
  font:600 11px/1 var(--font-mono); letter-spacing:.06em; text-transform:uppercase;
  border:1px solid var(--line); border-radius:var(--r-sm); padding:4px 8px; color:var(--muted);
}
.tag::before{content:""; width:6px; height:6px; border-radius:var(--r-pill); background:currentColor}
.tag--det{color:var(--kind-det); border-color:var(--kind-det-border)}
.tag--agt{color:var(--kind-agt); border-color:var(--kind-agt-border)}
/* inline kind label used on skill cards (dot + word, no border) */
.kind{display:inline-flex; align-items:center; gap:7px; font:600 11px/1 var(--font-mono);
  letter-spacing:.08em; text-transform:uppercase}
.kind::before{content:""; width:6px; height:6px; border-radius:var(--r-pill); background:currentColor}
.kind--det{color:var(--kind-det)} .kind--agt{color:var(--kind-agt)}

/* ----------------------------------------------------------------------------
   BREADCRUMB
---------------------------------------------------------------------------- */
.crumb{font:500 13px/1 var(--font-sans); color:var(--faint); margin-bottom:24px}
.crumb a{color:var(--brand); font-weight:600}
.crumb .sep{margin:0 8px; color:var(--line)}

/* ----------------------------------------------------------------------------
   STEPPER  (one definition; set labels in the template)
---------------------------------------------------------------------------- */
.stepper{display:flex; gap:10px; margin-bottom:28px}
.step{
  flex:1; display:flex; align-items:center; gap:11px;
  background:var(--surface); border:1px solid var(--line);
  border-radius:12px; padding:13px 16px;
}
.step__num{
  width:26px; height:26px; border-radius:var(--r-pill); flex:none;
  background:var(--surface-2); color:var(--disabled);
  display:inline-flex; align-items:center; justify-content:center; font:700 13px/1 var(--font-sans);
}
.step__label{display:flex; flex-direction:column; gap:3px; min-width:0}
.step__title{font:700 13px/1.2 var(--font-sans); color:var(--ink)}
.step__hint{font:500 12px/1.2 var(--font-sans); color:var(--faint)}
.step.is-upcoming{opacity:.7}
.step.is-upcoming .step__title{color:var(--muted)}
.step.is-active{border:1.5px solid var(--brand); box-shadow:var(--ring)}
.step.is-active .step__num{background:var(--brand-tint); border:1.5px solid var(--brand); color:var(--brand)}
.step.is-done .step__num{background:var(--brand); color:#fff}

/* ----------------------------------------------------------------------------
   FORMS
---------------------------------------------------------------------------- */
.field{margin-bottom:22px}
.label{display:block; font:700 12px/1 var(--font-sans); letter-spacing:.02em; color:var(--ink); margin-bottom:9px}
.label .opt-note{font-weight:500; color:var(--disabled); text-transform:none; letter-spacing:0}
.label .req{font-weight:600; color:var(--bad)}
.input{
  width:100%; font:500 14px/1 var(--font-sans); color:var(--ink);
  background:var(--surface); border:1px solid var(--line);
  border-radius:var(--r-input); padding:13px 15px;
}
.input::placeholder{color:var(--disabled)}
.input:focus{outline:none; border-color:var(--brand); box-shadow:var(--ring)}

/* upload drop zone */
.drop{
  border:1.5px dashed var(--brand-tint-border); background:var(--brand-tint);
  border-radius:12px; padding:34px; display:flex; flex-direction:column;
  align-items:center; gap:12px; text-align:center; transition:border-color var(--t) var(--ease);
}
.drop.is-dragover{border-color:var(--brand)}
.drop__icon{width:42px; height:42px; border-radius:11px; background:var(--surface);
  border:1px solid var(--brand-tint-border); display:inline-flex; align-items:center;
  justify-content:center; color:var(--brand); font:700 20px/1 var(--font-sans)}
.drop__hint{font:500 14px/1.4 var(--font-sans); color:var(--muted)}
/* transient "wrong file type" notice under a .drop zone (added by upload.js) */
.drop-note{margin:8px 0 0; padding:8px 12px; border-radius:var(--r-sm);
  background:var(--bad-bg); color:var(--bad); border:1px solid var(--bad-border);
  font:500 13px/1.4 var(--font-sans); transition:opacity .4s var(--ease)}
.drop-note.is-leaving{opacity:0}

/* Static help under a field. Not .drop-note: that one is the error palette,
   and telling someone what a field is for is not a warning. */
.field-note{
  margin:8px 0 0; font:500 12.5px/1.5 var(--font-sans); color:var(--faint);
}
.field-note .mono{font-size:12px; color:var(--muted)}

/* file list */
.file{
  display:flex; align-items:center; gap:12px;
  border:1px solid var(--line); border-radius:var(--r-control); padding:11px 14px;
}
.file__type{font:600 11px/1 var(--font-mono); color:var(--brand);
  background:var(--brand-tint); border-radius:var(--r-sm); padding:4px 7px}
.file__name{flex:1; font:500 13.5px/1 var(--font-mono); color:var(--ink)}
.file__size{font:500 12px/1 var(--font-sans); color:var(--disabled)}
.file__remove{font:600 16px/1 var(--font-sans); color:var(--disabled); cursor:pointer; background:none; border:none}

/* split footer (Back / … / Continue) */
.wizard-footer{display:flex; align-items:center; justify-content:space-between; margin-top:22px; gap:12px}
.wizard-footer .group{display:flex; gap:12px}

/* ----------------------------------------------------------------------------
   QUESTION UI (agentic)
---------------------------------------------------------------------------- */
.qprogress{display:flex; align-items:center; gap:14px; margin-bottom:24px}
.qprogress span{font:600 12px/1 var(--font-mono); color:var(--muted); white-space:nowrap}
.qbar{flex:1; height:6px; border-radius:3px; background:var(--hairline); overflow:hidden}
.qbar__fill{display:block; height:100%; background:var(--brand); border-radius:3px}
.opt{
  display:flex; align-items:center; gap:12px; cursor:pointer;
  border:1px solid var(--line); border-radius:11px; padding:14px 16px; margin-bottom:10px;
  font:500 14px/1 var(--font-sans); color:var(--muted); background:var(--surface);
  transition:border-color var(--t-fast) var(--ease), background var(--t-fast) var(--ease);
}
.opt__radio{width:18px; height:18px; border-radius:var(--r-pill); border:1.5px solid var(--disabled);
  display:inline-flex; align-items:center; justify-content:center; flex:none}
/* multi-select option: a SQUARE box with a checkmark, vs the round radio above —
   the shape tells the user they can pick more than one. */
.opt__check{width:18px; height:18px; border-radius:5px; border:1.5px solid var(--disabled);
  display:inline-flex; align-items:center; justify-content:center; flex:none}
.opt.is-selected{border:1.5px solid var(--brand); background:var(--brand-tint); color:var(--ink); font-weight:600}
.opt.is-selected .opt__radio{border-color:var(--brand)}
.opt.is-selected .opt__radio::after{content:""; width:9px; height:9px; border-radius:var(--r-pill); background:var(--brand)}
.opt.is-selected .opt__check{border-color:var(--brand); background:var(--brand)}
.opt.is-selected .opt__check::after{content:"\2713"; font-size:12px; line-height:1; color:#fff; font-weight:700}

/* ----------------------------------------------------------------------------
   CALLOUTS & ALERTS
---------------------------------------------------------------------------- */
.callout{display:flex; gap:13px; border-radius:12px; padding:16px 18px; margin-bottom:24px;
  background:var(--ok-bg); border:1px solid var(--ok-border)}
.callout__icon{flex:none; width:20px; height:20px; border-radius:var(--r-pill); margin-top:1px;
  display:inline-flex; align-items:center; justify-content:center; font:700 12px/1 var(--font-sans); color:#fff}
.callout__title{font:700 13.5px/1.3 var(--font-sans); margin-bottom:3px}
.callout__body{font:400 13.5px/1.5 var(--font-sans)}
/* success (default) */
.callout .callout__icon{background:var(--brand)}
.callout .callout__title{color:var(--ok-ink)} .callout .callout__body{color:var(--ok)}
/* The sync status line. "Syncing" has to read as a live state, not a label, so
   it takes the brand colour and a slow pulse rather than another grey word. */
.syncing{color:var(--brand)}
@keyframes fae-pulse{0%,100%{opacity:1}50%{opacity:.45}}
@media (prefers-reduced-motion: no-preference){.syncing{animation:fae-pulse 1.4s ease-in-out infinite}}

/* Pages, tokens and spend: kept, but behind one click. They are telemetry, and
   they used to sit in front of the two numbers this page exists to report. */
.corpus-detail > summary{cursor:pointer; display:inline-block; padding:2px 0}
.corpus-detail > summary::marker{color:var(--muted)}
.corpus-detail[open] > summary{margin-bottom:2px}

/* A named list inside a callout: the file names are the payload, so they get
   their own lines and the body's leading rather than a paragraph's run-on. */
.callout__list{margin:6px 0 4px; padding-left:18px}
.callout__list li{margin:2px 0}
/* warning */
.callout.warn{background:var(--warn-bg); border-color:var(--warn-border)}
.callout.warn .callout__icon{background:var(--warn-icon)}
.callout.warn .callout__title{color:#7A5A14} .callout.warn .callout__body{color:var(--warn)}
/* error */
.alert.error{background:var(--bad-bg); border-color:var(--bad-border)}
.alert.error .callout__icon{background:var(--bad)}
.alert.error .callout__title{color:var(--bad)} .alert.error .callout__body{color:var(--bad)}

/* ----------------------------------------------------------------------------
   QC LEVEL ROWS  (replaces dense bullet text)
---------------------------------------------------------------------------- */
.qc-levels{display:flex; flex-direction:column; gap:10px; margin-bottom:22px}
.qc-level{display:flex; align-items:center; gap:14px; border:1px solid var(--line);
  border-radius:var(--r-control); padding:14px 16px}
.qc-level.is-warn{border-color:var(--warn-border); background:#FEFBF5}
.qc-level__name{font:700 14px/1 var(--font-sans); color:var(--ink); width:58px}
.qc-level__n{font:500 12px/1 var(--font-mono); color:var(--faint); width:50px}
.qc-level__finding{flex:1; font:400 13.5px/1.4 var(--font-sans); color:var(--muted)}
.qc-level__finding strong{font-weight:700; color:var(--ink)}

/* status pill (shared by QC rows, My runs, Admin) — pairs colour + glyph + word */
.pill{display:inline-flex; align-items:center; gap:6px; font:600 12px/1 var(--font-sans);
  border-radius:var(--r-pill); padding:5px 11px; border:1px solid transparent; white-space:nowrap}
.pill--ok{color:var(--ok); background:var(--ok-bg); border-color:var(--ok-border)}
.pill--warn{color:var(--warn); background:var(--warn-bg); border-color:var(--warn-border)}
.pill--bad{color:var(--bad); background:var(--bad-bg); border-color:var(--bad-border)}

/* technical report disclosure (replaces the dark navy island with a light mono panel) */
.qc-report-toggle{font:600 13px/1 var(--font-sans); color:var(--faint);
  border-top:1px solid var(--hairline); padding-top:16px; cursor:pointer}
.qc{background:var(--surface-2); border:1px solid var(--line); border-radius:var(--r-control);
  padding:16px 18px; font:500 12.5px/1.7 var(--font-mono); color:var(--muted);
  white-space:pre-wrap; overflow:auto; max-height:340px; margin-top:12px}

/* ----------------------------------------------------------------------------
   LIVE STATUS LOG (agentic, 2s poll)
---------------------------------------------------------------------------- */
.log{background:var(--surface); border:1px solid var(--line); border-radius:var(--r-card);
  padding:20px 22px; box-shadow:var(--shadow-sm)}
.log__head{display:flex; align-items:center; gap:9px; margin-bottom:14px}
.log__head .live-dot{width:8px; height:8px; border-radius:var(--r-pill); background:var(--kind-agt);
  animation:pulse 1.2s ease-in-out infinite}
.log__head .live-dot.is-done{background:var(--brand); animation:none}
.log__title{font:700 12px/1 var(--font-sans); letter-spacing:.04em; text-transform:uppercase; color:var(--ink)}
.log__refresh{font:500 11px/1 var(--font-mono); color:var(--disabled); margin-left:auto}
.log__wrap{background:var(--surface-2); border:1px solid var(--hairline); border-radius:var(--r-control);
  padding:6px 0; max-height:260px; overflow:auto}
.log__row{display:flex; gap:12px; padding:8px 16px; border-bottom:1px solid var(--hairline)}
.log__row:last-child{border-bottom:none}
.log__time{font:500 11px/1.4 var(--font-mono); color:var(--disabled); width:60px; flex:none}
.log__tag{font:600 11px/1 var(--font-sans); border-radius:var(--r-sm); padding:3px 7px; height:fit-content}
.log__tag--answered,.log__tag--done{color:var(--ok); background:var(--ok-bg)}
.log__tag--waiting{color:var(--warn); background:var(--warn-bg)}
.log__tag--neutral{color:var(--muted); background:var(--hairline)}
.log__tag--error{color:var(--bad); background:var(--bad-bg)}
.log__msg{font:500 12px/1.4 var(--font-mono); color:var(--muted); flex:1}
/* agent prose (reasoning/answers): readable sans, real line height, keep line breaks */
.log__msg--prose{font:400 13px/1.55 var(--font-sans); white-space:pre-wrap; word-break:break-word}
/* fenced code blocks + tables emitted by the agent's status text (_status_md) */
.log__code{font:500 12px/1.5 var(--font-mono); background:var(--surface-2);
  border:1px solid var(--line); border-radius:var(--r-sm); padding:10px 12px;
  margin:6px 0; overflow-x:auto; white-space:pre; word-break:normal}
.log__table{border-collapse:collapse; margin:8px 0; font-size:12.5px; max-width:100%}
.log__table th,.log__table td{border:1px solid var(--line); padding:5px 9px; text-align:left;
  vertical-align:top; white-space:normal; word-break:break-word}
.log__table th{background:var(--surface-2); font-weight:700}

/* ----------------------------------------------------------------------------
   TABLES  (My runs, Admin)
---------------------------------------------------------------------------- */
.table-scroll{overflow:auto; border-radius:var(--r-card)}
/* Fixed-height scroll window with the sticky header staying put.
   624px = a 48px header plus eight 72px rows. 72px is a row whose question
   wraps to two lines; a one-line row is 66px, so eight always fit and a ninth
   peeks in when the questions are short -- which is the hint that there is more
   to scroll. 505px was described as ~8 rows and actually showed six.
   scrollbar-gutter keeps the column widths identical whether or not the list is
   long enough to scroll, so nothing reflows as it grows. */
.table-scroll--rows{max-height:624px; scrollbar-gutter:stable}
/* .grid sets overflow:hidden to round its own corners, and an ancestor with
   overflow:hidden becomes the sticky header's scrollport -- which never
   scrolls, so the header had nothing to stick to and scrolled away with the
   rows. The window already rounds and clips, so the table does not need to. */
.table-scroll--rows .grid{overflow:visible}
.grid{width:100%; border-collapse:collapse; background:var(--surface);
  border:1px solid var(--line); border-radius:var(--r-card); overflow:hidden}
/* fixed layout: <colgroup> widths fill the full table width (no trailing gap);
   cells stay single-line and ellipsize so every row is the same height */
.grid--fixed{table-layout:fixed}
.grid--fixed th,.grid--fixed td{overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
/* opt a fixed-layout cell back into wrapping (e.g. the input-files list) */
.grid--fixed td.cell-wrap{white-space:normal; overflow:visible; text-overflow:clip; word-break:break-word}
/* a cell holding a status pill: never ellipsize the pill */
.grid--fixed td.cell-pill{overflow:visible; text-overflow:clip}
/* input-files cell (My Runs + Admin Runs): collapsed shows the comma-separated
   list clamped to two lines; expanded (.is-expanded, toggled by app.js) hides the
   clamp and reveals .files-list with one filename per line. The clamp lives on an
   inner span, NOT the <td>, so the cell keeps table-cell vertical alignment. */
.grid--fixed td.cell-files{white-space:normal; word-break:break-word; text-overflow:clip}
.grid--fixed td.cell-files .files-clamp{display:-webkit-box; -webkit-box-orient:vertical;
  -webkit-line-clamp:2; line-clamp:2; overflow:hidden}
.grid--fixed td.cell-files .files-list{display:none; margin:0; padding:0; list-style:none}
.grid--fixed td.cell-files .files-list li{white-space:normal; word-break:break-word}
.grid--fixed td.cell-files.is-expanded .files-clamp{display:none}
.grid--fixed td.cell-files.is-expanded .files-list{display:block}
.grid--fixed td.cell-files .files-toggle{display:inline-block; margin-top:4px; padding:0;
  background:none; border:none; cursor:pointer; font:inherit; color:var(--brand);
  text-decoration:underline}
/* auto-layout table: fills the container when content is short, but cells never
   wrap — long content widens the table so .table-scroll scrolls horizontally */
.grid--scroll th,.grid--scroll td{white-space:nowrap}
.grid thead th{
  text-align:left; background:var(--surface-2); border-bottom:1px solid var(--line);
  font:700 10.5px/1 var(--font-mono); letter-spacing:.08em; text-transform:uppercase;
  color:var(--faint); padding:13px 22px; position:sticky; top:0; z-index:1;
}
.grid tbody td{padding:16px 22px; border-bottom:1px solid var(--hairline); vertical-align:middle;
  font:500 14px/1.4 var(--font-sans); color:var(--ink)}
.grid tbody tr:last-child td{border-bottom:none}
.grid .cell-mono{font:500 12.5px/1.3 var(--font-mono); color:var(--muted)}
.grid .cell-muted{color:var(--muted)}
/* "needs your answer" row highlight */
.grid tr.row--attn td{background:#FEFBF5}

/* admin filter bar — fields share the row evenly and grow to fill the table width */
.filters{display:flex; gap:12px; align-items:center; margin-bottom:18px}
/* A filter bar is one line of controls, not a form section. The default card
   padding plus .field's bottom margin plus .filters' own left 70px of empty
   space under a single row of inputs. This wraps them tightly instead. */
.card--filters{padding:16px 18px}
.card--filters .filters{margin-bottom:0}
.card--filters .field{margin-bottom:0}
.filters > .input{flex:1 1 0; min-width:110px; width:auto; padding:10px 13px; font-size:13px}
.filters select.input{appearance:none}
/* labelled date field: the label grows with the others, the input fills it */
.filters .flbl{flex:1 1 0; min-width:120px; display:flex; align-items:center; gap:8px;
  font:600 11px/1 var(--font-mono); letter-spacing:.04em; text-transform:uppercase; color:var(--faint)}
.filters .flbl .input{flex:1 1 auto; min-width:0}
.filters .btn{flex:0 0 auto}

/* ----------------------------------------------------------------------------
   AUTH (login / recovery)
---------------------------------------------------------------------------- */
.auth{min-height:100vh; display:flex; flex-direction:column; align-items:center;
  justify-content:center; gap:36px; background:var(--canvas); padding:80px 0}
.auth__logo{height:34px; width:auto}
.auth__card{width:420px; max-width:calc(100vw - 32px); background:var(--surface);
  border:1px solid var(--line); border-radius:16px; padding:36px 34px; box-shadow:var(--shadow-card)}
.auth__card h1{font-size:24px}
.auth__card .input-tag{font:500 13px/1.4 var(--font-mono); color:var(--ink);
  background:var(--surface-2); border-radius:var(--r-sm); padding:2px 6px}
.btn-google{width:100%; padding:14px 18px}
.btn-google .g{width:18px; height:18px; border-radius:var(--r-pill); background:#fff;
  display:inline-flex; align-items:center; justify-content:center; font:800 12px/1 var(--font-sans); color:var(--brand)}

/* error page card */
.error-card{width:460px; max-width:calc(100vw - 32px); text-align:center;
  background:var(--surface); border:1px solid var(--line); border-radius:16px;
  padding:38px 36px; box-shadow:var(--shadow-card)}
.error-card__icon{width:48px; height:48px; border-radius:var(--r-pill); margin-bottom:16px;
  background:var(--bad-bg); border:1px solid var(--bad-border); color:var(--bad);
  display:inline-flex; align-items:center; justify-content:center; font:700 22px/1 var(--font-sans)}
.error-card .ref{font:500 12px/1.4 var(--font-mono); color:var(--disabled); margin:8px 0 24px}

/* ----------------------------------------------------------------------------
   TEMPLATE SUPPORT HELPERS  (small wrappers the templates need)
---------------------------------------------------------------------------- */
/* title + kind-tag header row (wizard, agentic, admin panels) */
.card-head{display:flex; align-items:center; gap:12px; flex-wrap:wrap; margin-bottom:6px}
/* file-list container (rows are .file; built server- or client-side) */
.file-list{list-style:none; margin:16px 0 0; padding:0; display:flex; flex-direction:column; gap:10px}
/* success medallion on the deterministic "done" screen (mirrors .error-card__icon) */
.success-medallion{width:48px; height:48px; border-radius:var(--r-pill); margin-bottom:16px;
  background:var(--brand-tint); border:1px solid var(--brand-tint-border); color:var(--brand);
  display:inline-flex; align-items:center; justify-content:center; font:700 22px/1 var(--font-sans)}

/* ----------------------------------------------------------------------------
   MOTION PREFERENCES
---------------------------------------------------------------------------- */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation:none !important; transition:none !important}
}

/* a date is a single token; letting it wrap turned 2026-09-14 into two lines */
.grid .cell-date{white-space:nowrap}

/* The two country columns are narrow by design -- they are scanned, not read.
   The grid's generous 22px side padding left only 66px of a 110px column for
   text, so "Saudi Arabia" (91px) wrapped to two lines. Narrower padding buys
   back the width without widening the column. */
/* headers included: the padding is what aligns the heading with the values
   under it, so applying it to one and not the other pushes them apart. */
.grid .cell-country{padding-left:12px; padding-right:12px}

/* Possible duplicates (§6) — verification page, above the merge control.
   A recommendation the admin reads, so the question is the loud part and the
   model's reason sits under it in the muted voice the rest of the AI output
   uses. Never styled as an error: nothing here is wrong, it is a suggestion. */
.dupe__title{font:700 14px/1.3 var(--font-sans); color:var(--ink); margin:0}
.dupe__row{border-top:1px solid var(--hairline); padding-top:12px; margin-top:12px}
.dupe__head{display:flex; align-items:center; gap:10px; flex-wrap:wrap}
.dupe__ref{font:600 12.5px/1 var(--font-mono); color:var(--muted); text-decoration:none}
.dupe__ref:hover{text-decoration:underline}
.dupe__q{font:500 13.5px/1.5 var(--font-sans); color:var(--ink); margin:8px 0 0}
.dupe__why{font:400 13px/1.5 var(--font-sans); color:var(--muted); margin:4px 0 8px}
.dupe__note{font:400 13px/1.5 var(--font-sans); color:var(--faint); margin:4px 0 0}
.dupe__more{margin-top:12px}
.dupe__more[open] .dupe__row:first-of-type{margin-top:8px}

/* From the documents (§6, §8.3) — the grounded block on the verify page. Same
   voice as the duplicate card: the quote is the loud part. DIFFERS/PARTIAL get
   the attention border because they are the cases the whole feature exists for. */
.ground--differs{border-color:var(--bad-border)}
.ground__note{font:400 13px/1.5 var(--font-sans); color:var(--faint); margin:4px 0 0}
.ground__judge{margin:8px 0 10px}
/* A contradiction found on a verdict that did NOT answer (FAE-2026-0024). The card
   above says "not found in the documents", so this has to carry its own weight: the
   admin is about to approve a draft built from the reply it contradicts. */
.ground__conflict{border:1px solid var(--bad-border); border-radius:8px; padding:10px 12px; margin:10px 0 0}
.ground__conflict .ground__note:first-child{color:var(--ink)}
.ground__reason{font:500 13.5px/1.5 var(--font-sans); color:var(--ink); margin:4px 0}
.ground__cite{border-top:1px solid var(--hairline); padding-top:10px; margin-top:10px}
.ground__cite-head{display:flex; align-items:center; gap:10px; flex-wrap:wrap}
.ground__ref{font:600 12.5px/1 var(--font-mono); color:var(--muted); text-decoration:none}
.ground__ref:hover{text-decoration:underline}
.ground__meta{font:400 12px/1 var(--font-mono); color:var(--faint)}
.ground__quote{background:#fff7cc; border-left:4px solid #e6b800; padding:8px 12px; margin:8px 0 0;
  font:400 13.5px/1.5 var(--font-sans); color:var(--ink); white-space:pre-wrap}
.ground__quote--derived{background:#eef; border-left-color:#88a; font-style:italic}
.ground__quote--missing{background:#fde8e8; border-left-color:var(--bad); font-style:italic}
.ground__more{margin-top:8px}

/* The fused draft's provenance (§6.6) — under the answer editor. Quiet: the
   editor is the loud part; this says where its sentences came from. */
.fuse{border-top:1px solid var(--hairline); margin-top:12px; padding-top:10px}
.fuse__title{font:700 13px/1.3 var(--font-sans); color:var(--ink); margin:0}
.fuse__note{font:400 13px/1.5 var(--font-sans); color:var(--faint); margin:4px 0 0}
.fuse__conflicts{background:#fff7cc; border-left:4px solid #e6b800; padding:8px 12px; margin:8px 0 0}
.fuse__conflict{font:400 13px/1.5 var(--font-sans); color:var(--ink); margin:4px 0 0}
.fuse__more{margin-top:8px}
.fuse__claim{display:flex; align-items:baseline; gap:8px; flex-wrap:wrap; margin-top:6px}
.fuse__text{font:400 13px/1.5 var(--font-sans); color:var(--ink)}
.fuse__ref{font:600 12px/1 var(--font-mono); color:var(--muted); text-decoration:none}
.fuse__ref:hover{text-decoration:underline}

/* Filter bar control heights.
   A text input and a select carrying the same .input class do not come out the
   same height: the input sizes from the font's normal metrics and ignores
   line-height:1, the select honours it. 47px against 42px, so the row never
   lined up -- and the submit button, aligned to the tallest item, hung three
   pixels below the four selects while sitting level with the search box.
   One explicit height settles all of them, and bottom alignment puts the
   button on the controls' line rather than splitting the difference with the
   labels above them. */
.card--filters .filters{align-items:end}
.card--filters .input{height:42px; padding-top:0; padding-bottom:0}
.card--filters .btn{height:42px}

/* M8: documents */
.chip { display:inline-block; padding:2px 8px; border-radius:999px; font-size:12px; background:var(--chip-bg, #eef); margin:2px 4px 0 0; }
.chip--stale, .chip--failed, .chip--warn { background:#fde8e8; }
.chip--ok, .chip--current { background:#e6f6ea; }
/* vertical-align matters: an inline-flex box sits on its BASELINE by default,
   and .iconbtn next to it sets vertical-align:middle. Without this the re-ingest
   form (one 28px button, no select to pull its baseline down) rode 4px higher
   than the download icon beside it. Measured on /fae/docs 2026-09-18. */
.inline-form { display:inline-flex; gap:6px; align-items:center; vertical-align:middle; }
.input--sm { padding:2px 6px; font-size:12px; }
/* A flex column, not two blocks in flow. The iframe used to be sized
   calc(100% - 40px) -- a guess at the button's height -- and the button's real
   footprint is 48px, so the dialog overflowed by 13px. Reaching the end of the
   document then chained the scroll into the dialog and carried Close up out of
   view. Now the button cannot shrink, the iframe takes exactly what is left,
   and overflow:hidden means the dialog has nothing to scroll.

   The display lives on [open]: a bare display:flex here would beat the user
   agent's dialog:not([open]){display:none} and render the dialog permanently. */
.preview-dialog{ width:min(1100px, 96vw); height:90vh; padding:0; border:0;
  border-radius:8px; overflow:hidden; }
.preview-dialog[open]{ display:flex; flex-direction:column; }
.preview-dialog iframe { flex:1 1 auto; width:100%; min-height:0; border:0; }
.preview-close { flex:none; margin:4px; align-self:flex-start; }
.preview-quote { background:#fff7cc; padding:8px 12px; border-left:4px solid #e6b800; white-space:pre-wrap; }
.preview-quote--derived { background:#eef; border-left-color:#88a; font-style:italic; }
.preview-md { white-space:pre; overflow-x:auto; font-size:12px; }
.preview-blocks li.is-cited { background:#fff7cc; }
.filetype { font-size:15px; margin-right:6px; vertical-align:-1px; }
.preview-video { width:100%; max-height:70vh; background:#000; border-radius:6px; }
.filetype { vertical-align:-3px; margin-right:7px; opacity:.75; flex:none; }
.is-embedded .page { padding-top:12px; }
.nowrap { white-space:nowrap; }
.table td .inline-form { margin-right:6px; }

/* File Dashboard -------------------------------------------------------- */
.grid td.cell-file a{font-weight:600}
.grid td.cell-file .file-name--plain{font-weight:600; color:var(--muted)}
.grid td.cell-actions{white-space:nowrap}
/* Row actions are marks, not words: five word-buttons per row read as prose. */
.iconbtn{display:inline-flex; align-items:center; justify-content:center;
  width:28px; height:28px; padding:0; border:1px solid var(--line);
  border-radius:6px; background:var(--surface); color:var(--muted);
  cursor:pointer; vertical-align:middle}
.iconbtn:hover{color:var(--ink); border-color:var(--ink); background:var(--surface-2)}

/* The dashboard packs five columns plus a row of controls into one screen, so
   it trims the grid's generous 22px cell padding. Nothing scrolls sideways. */
.docs-grid th, .docs-grid td { padding-left:14px; padding-right:14px }
/* The action cell holds selects and icon buttons: never clip or ellipsize it. */
.grid--fixed td.cell-actions { overflow:visible; text-overflow:clip; white-space:nowrap }
.grid--fixed td.cell-actions .inline-form { display:inline-flex; gap:4px; margin:0 0 0 6px }
.grid--fixed td.cell-actions .input--sm { max-width:92px }
.grid--fixed td.cell-file { white-space:normal; word-break:break-word }
/* The frame belongs to the scroll window, not the table. .table-scroll--rows
   sets the table to overflow:visible so the sticky header has a scrollport, and
   the table's own 1px top border then scrolls out of view -- leaving a strip
   above the header where passing rows showed through. The window clips, so it
   is the thing that should carry the border and the radius. */
.docs-wrap { border:1px solid var(--line); border-radius:var(--r-card) }
.docs-wrap .docs-grid { border:0; border-radius:0 }

/* A citation whose answer was edited after it was recorded (§7.6). Dimmed, not
   hidden: the drift report reads these, and a reader deserves to see the doubt. */
.cite--stale{opacity:.7}

/* Drive modified / Ingested on the file dashboard (§8.1). Smaller than the other
   mono cells: two timestamps per row is a lot of ink for something you read only
   when a row says STALE. */
.cell-when{font-size:11.5px; color:var(--faint); white-space:nowrap; line-height:1.35}
/* Date over time: "2026-09-17 15:53" needs 164px on one line and the column is
   112px, so every timestamp was clipped to "2026-09-…" -- which is exactly the
   part you need when Drive modified is being compared against Ingested. */
.cell-when b{display:block; font-weight:500; color:var(--muted)}
.cell-when span{display:block; font-size:10.5px; opacity:.8}

/* The per-file tag editor. Scope and region are a one-time decision, so the two
   selects and their Save hide behind one mark; <details> means no JS, matching
   the account menu. The open panel floats over the row rather than growing it:
   ten rows that reflow when one is expanded is worse than the five buttons. */
.tagedit{position:relative; display:inline-block; vertical-align:middle}
.tagedit__toggle{list-style:none; cursor:pointer}
.tagedit__toggle::-webkit-details-marker{display:none}
.tagedit__toggle::marker{content:""}
.tagedit[open] .tagedit__toggle{color:var(--ink); border-color:var(--ink)}
/* Deliberately NOT .inline-form. That class is targeted by
   `.grid--fixed td.cell-actions .inline-form{display:inline-flex}`, specificity
   (0,3,1), which outranks any `.tagedit:not([open]) .tagedit__form` rule at
   (0,3,0) -- and absolute positioning then blockifies inline-flex to flex. The
   result measured in the browser was details.open false with the form still
   46px tall, so every row showed its selects with the disclosure shut. Owning
   the layout here removes the collision instead of escalating specificity. */
.tagedit__form{display:flex; gap:6px; align-items:center;
  position:absolute; right:0; top:34px; z-index:20; padding:8px;
  background:var(--surface); border:1px solid var(--line); border-radius:8px;
  box-shadow:0 6px 20px rgba(0,0,0,.12)}
.tagedit:not([open]) .tagedit__form{display:none}
/* The panel floats free of the column, so it is not bound by the 92px cap
   `.grid--fixed td.cell-actions .input--sm` puts on an in-row select. At 92px
   two of them plus Save squeezed to ~24px each: visible chevrons, no readable
   text. Measured open at 86px total before this. */
.tagedit__form .input--sm{max-width:none; min-width:108px; font-size:12.5px; padding:4px 8px}
