/*
 * CAPCON — shared design tokens (Phase 0).
 *
 * One visual identity for every odcube.landimage.info frontend. Link it in the
 * <head> of any app:
 *     <link rel="stylesheet" href="/assets/capcon-theme.css">
 *
 * Palette is the canonical set already used by the Manager (imported there from
 * Mapper/Calc). Everything is a CSS custom property so /config can retune the
 * whole platform by overriding these on :root at runtime (see
 * capcon-theme-loader.js) — no redeploy, no per-file edits.
 *
 * Phase 0 ships the TOKENS only. Base component classes (.btn/.badge/.pill/…)
 * arrive in Phase 2; apps keep their own component CSS until then and may start
 * referencing the var()s immediately.
 */
/* Condensed display face for app-name wordmarks (.cc-brand-name) — lets the name
   be large and bold yet still fit the sidebar-width column. Must precede all rules. */
@import url('https://fonts.googleapis.com/css2?family=Oswald:wght@500;600;700&display=optional');
:root {
  /* ── Surfaces ─────────────────────────────────────────────────────────── */
  --bg:#0f1923;        --panel:#131f2e;   --panel2:#1a2d42;
  --bg0:#0a1018;       --bg1:#0f1923;     --bg2:#131f2e;     --bg3:#1a2d42;
  --line:#1e3550;      --line2:#2a4a6a;

  /* ── Text (bright → dim) ──────────────────────────────────────────────── */
  --txt:#dfe7ef;       --txt2:#cdd6e0;    --txt3:#8aabb0;    --txt4:#4a7aab;
  /* legacy aliases used by Mapper/Calc imports */
  --text:#cdd6e0;      --text2:#8aabb0;   --text3:#4a7aab;   --text4:#2a4a6a;

  /* ── Accents ──────────────────────────────────────────────────────────── */
  --blue:#5bb8ff;      --blue2:#3a9fff;   --blue3:#1e5da0;   --blue4:#0d2a45;
  --signal:#5bb8ff;    --signal-dim:#1e5da0;
  --ok:#3abf80;        --info:#5bb8ff;    --warn:#f0b040;    --error:#cf7060;
  --ok-bg:rgba(58,191,128,.14);   --info-bg:rgba(91,184,255,.14);
  --warn-bg:rgba(240,176,64,.14); --error-bg:rgba(207,112,96,.14);

  /* ── Type ─────────────────────────────────────────────────────────────── */
  --sans:'Inter',-apple-system,BlinkMacSystemFont,'Segoe UI',system-ui,sans-serif;
  --mono:'JetBrains Mono',ui-monospace,SFMono-Regular,Menlo,monospace;
  --font-display:'Oswald','Arial Narrow',var(--sans);  /* condensed app-name wordmarks */
  /* Single knob for global scale — /config's "font size" slider edits this and
     every --fs-* below tracks it. */
  /* Two independent type axes — /config has a slider for each:
     --font-base = body / UI text;  --font-heading = title-bar headings. */
  /* Fluid type — scales with the CSS viewport (already zoom/DPI-normalized) so
     the UI stays comfortable from laptops to large hi-res monitors. The baseline
     (14/15) matches the ~1536x864 design target (1920@125%, 16:9).

     IMPORTANT — aspect-balanced scale. The variable term blends viewport WIDTH
     and HEIGHT so the chrome scales by the overall screen size, not width alone.
     The split (c/2 of vw + c*16/9/2 of vh) is calibrated so the result is
     IDENTICAL to a width-only `c*vw` on any 16:9 viewport (the design ratio) —
     existing 16:9 setups are unchanged — but on a taller-than-16:9 screen the
     vh term lifts the scale to match the layout (which fills 100vh), and on a
     wider/shorter screen it holds the scale down. This stops the UI from looking
     vertically stretched / horizontally compressed off the design aspect ratio.
     /config sliders still override. */
  --font-base:clamp(13px, 0.15vw + 0.267vh + 9.4px, 18px);     /* body / UI text knob     */
  --font-heading:clamp(14px, 0.15vw + 0.267vh + 10.4px, 19px); /* heading / title-bar     */
  --fs-xs:calc(var(--font-base) - 3px);      /* ~11 — badges, captions       */
  --fs-sm:calc(var(--font-base) - 2px);      /* ~12 — secondary controls     */
  --fs-md:var(--font-base);                  /*  14 — body / inputs          */
  --fs-lg:calc(var(--font-base) + 1px);      /* ~15 — buttons / controls     */
  --fs-xl:var(--font-heading);               /* app title bars (heading axis)*/
  --fs-2xl:calc(var(--font-heading) + 8px);  /* large page headings          */
  --lh:1.5;

  /* ── Spacing / shape ──────────────────────────────────────────────────── */
  /* Spacing scales with the viewport too (baseline 4/8/12/18 at ~1536x864),
     using the same aspect-balanced vw+vh blend as the type scale above. */
  --sp-1:clamp(4px, 0.065vw + 0.116vh + 2px, 6px);   --sp-2:clamp(8px, 0.13vw + 0.231vh + 4px, 12px);
  --sp-3:clamp(12px, 0.195vw + 0.347vh + 6px, 18px); --sp-4:clamp(18px, 0.295vw + 0.524vh + 9px, 26px);
  --radius:6px;       --radius-sm:4px;    --radius-lg:10px;
  --shadow:0 2px 10px rgba(0,0,0,.28);

  /* ── Layout (harmonized to the Tracker app) ──────────────────────────── */
  /* Narrowed 2026-09-09 from clamp(300px,…,440px) (~310px at 1536x864). The
     panel list is short labels, so the old column was mostly empty space taken
     from the panel a user is actually reading. The floor is set by the brand
     block, not by the menu: 18px padding x2 + a 44px chip + a 12px gap leaves
     ~150px for "CAPCON <app>" at 20px in the condensed display face, which the
     longest name (CAPCON Database) fits. Both name and keyword ellipsize, so a
     longer app name degrades rather than breaking the layout. */
  --sidebar-w:clamp(220px, 3.2vw + 5.4vh + 145px, 340px);  /* fluid (aspect-balanced): ~241px at 1536x864 */
  --topbar-pad:8px 16px;    /* top title-bar padding (sets its height) */
}

/* ════════════════════════════════════════════════════════════════════════════
 * Base components (Phase 2).
 *
 * Namespaced `.cc-*` so they NEVER collide with an app's existing classes —
 * linking this file changes nothing until an element opts in by using a class.
 * All values come from the tokens above, so /config retunes every component
 * platform-wide. Phase 3 migrates each app's markup/CSS onto these.
 * ════════════════════════════════════════════════════════════════════════════ */

/* Buttons ─────────────────────────────────────────────────────────────────── */
.cc-btn{display:inline-flex;align-items:center;justify-content:center;gap:6px;
  width:100%;padding:9px 12px;border:1px solid transparent;border-radius:var(--radius-sm);
  font-family:var(--sans);font-size:var(--fs-lg);font-weight:600;letter-spacing:.4px;
  cursor:pointer;transition:background .15s,border-color .15s,color .15s;
  background:var(--panel2);color:var(--txt)}
.cc-btn:hover:not(:disabled){background:var(--line2)}
.cc-btn:disabled{opacity:.5;cursor:not-allowed}
.cc-btn-sm{width:auto;padding:5px 10px;font-size:var(--fs-sm)}
.cc-btn-primary{background:var(--blue3);border-color:var(--blue3);color:#dfeeff}
.cc-btn-primary:hover:not(:disabled){background:var(--blue2)}
.cc-btn-danger{background:#5a2020;border-color:#5a2020;color:#ffb3b3}
.cc-btn-danger:hover:not(:disabled){background:#7a2828}
.cc-btn-export{background:#0a2a1a;border:1px solid #1a4a2a;color:var(--ok)}
.cc-btn-export:hover:not(:disabled){background:#0d3520}
.cc-btn-ghost{background:transparent;border-color:var(--line2);color:var(--txt2)}
.cc-btn-ghost:hover:not(:disabled){color:var(--txt);border-color:var(--blue3)}

/* Inputs / selects ────────────────────────────────────────────────────────── */
.cc-input{width:100%;background:var(--bg0);border:1px solid var(--line);color:var(--txt);
  padding:6px 9px;border-radius:var(--radius-sm);font-family:var(--sans);font-size:var(--fs-md);
  outline:none;transition:border-color .2s}
.cc-input:focus{border-color:var(--blue3)}

/* Section label ───────────────────────────────────────────────────────────── */
.cc-section-title{font-size:var(--fs-sm);font-weight:700;letter-spacing:1.2px;
  text-transform:uppercase;color:var(--txt4);margin-bottom:9px}

/* Badge ───────────────────────────────────────────────────────────────────── */
.cc-badge{display:inline-block;background:var(--blue4);color:var(--blue);
  font-size:var(--fs-xs);font-weight:600;padding:2px 8px;border-radius:10px;border:1px solid var(--blue3)}
.cc-badge-ok{background:var(--ok-bg);color:var(--ok);border-color:var(--ok)}
.cc-badge-warn{background:var(--warn-bg);color:var(--warn);border-color:var(--warn)}
.cc-badge-error{background:var(--error-bg);color:var(--error);border-color:var(--error)}

/* Pill (toggle / filter) ──────────────────────────────────────────────────── */
.cc-pill{padding:5px 10px;border:1px solid var(--line);background:var(--bg0);color:var(--txt3);
  border-radius:var(--radius-sm);cursor:pointer;font-size:var(--fs-sm);font-weight:600;
  transition:all .15s;text-align:center}
.cc-pill:hover{border-color:var(--line2);color:var(--txt)}
.cc-pill.active{border-color:var(--blue);background:var(--blue4);color:var(--blue)}

/* Card / panel section ────────────────────────────────────────────────────── */
.cc-card{background:var(--panel);border:1px solid var(--line);border-radius:var(--radius);padding:var(--sp-3)}

/* Loading spinner ─────────────────────────────────────────────────────────── */
.cc-spinner{display:inline-block;width:12px;height:12px;border:2px solid var(--line);
  border-top-color:var(--blue);border-radius:50%;animation:cc-spin .7s linear infinite;
  vertical-align:middle;margin-right:5px}
@keyframes cc-spin{to{transform:rotate(360deg)}}


/* Background-tasks floating panel ─────────────────────────────────────────────
 * Upper-right, just below the top bar — an auto-hiding stack of cards, one per
 * running background task, each with a determinate progress bar. Shared across
 * apps; driven by CAPCON.tasks.render() in /assets/capcon-tasks.js.
 * Anchored to the TOP (not the bottom) so the cards are always fully on-screen
 * regardless of monitor size — a bottom-right anchor pushed the cards partly
 * off-screen on large displays. `--header-h` (set by maps/calc to 36px) gives
 * the bar height; the 44px fallback clears the padding-driven dashboard/data-app
 * bars (~42px). */
.cc-bgtasks{position:fixed;top:calc(var(--header-h, 44px) + 12px);right:18px;
  display:flex;flex-direction:column;gap:10px;z-index:1000;max-width:380px}
.cc-bgtasks:empty{display:none}
.cc-bgtask{background:var(--panel2);border:1px solid var(--warn);border-radius:8px;
  padding:11px 14px 9px;min-width:260px;box-shadow:0 6px 20px rgba(0,0,0,.45);
  animation:cc-bgfade .25s ease}
.cc-bgtask .cc-bgtask-head{display:flex;align-items:baseline;gap:8px;font-family:var(--mono);font-size:12px}
.cc-bgtask .cc-bgtask-name{color:var(--warn);text-transform:uppercase;letter-spacing:.6px;font-weight:600}
.cc-bgtask .cc-bgtask-et{margin-left:auto;color:var(--txt3);font-variant-numeric:tabular-nums}
/* Optional per-card action button (e.g. Stop) — wired via CAPCON.tasks onAction. */
.cc-bgtask .cc-bgtask-action{margin-left:8px;font-family:var(--mono);font-size:10px;
  text-transform:uppercase;letter-spacing:.5px;color:var(--warn);cursor:pointer;
  background:transparent;border:1px solid var(--warn);border-radius:4px;padding:2px 8px}
.cc-bgtask .cc-bgtask-action:hover{background:var(--warn);color:var(--bg0)}
.cc-bgtask .cc-bgtask-det{font-family:var(--mono);font-size:11px;color:var(--txt2);margin:4px 0 8px;
  word-break:break-all}
.cc-bgtask .cc-bgtask-bar{height:4px;background:var(--line);border-radius:2px;overflow:hidden}
/* Determinate growing bar — width set per-update; no infinite slide, no flash. */
.cc-bgtask .cc-bgtask-bar > i{display:block;height:100%;width:0;background:var(--warn);
  transition:width .8s linear}
@keyframes cc-bgfade{from{transform:translateY(8px);opacity:0}to{transform:none;opacity:1}}

/* Top-bar pill system ──────────────────────────────────────────────────────────
 * ONE definition for every pill that sits on an app's top bar — the identity
 * pill (.cc-userpill), plus status chips / counters / badges (.cc-pill). The
 * Manager's bar is the reference look; this reproduces it for every app.
 *
 * Why a fixed height + line-height:1 + box-sizing:border-box: a pill MUST look
 * identical in every app, but each app's <body> sets a different font-size /
 * line-height (tracker 15px/1.5, maps 13px/1.45, manager 14px/1.55…). Without a
 * fixed height the pill inherits that and ends up a different height — and a
 * different height — per app. Pinning height:26px makes every pill the same
 * height and, with the bar's `align-items:center`, sit exactly on its vertical
 * centre. `flex:0 0 auto` means a pill never shrinks, so its text can't spill
 * over a neighbour. Colour is layered on by a modifier class on the element.
 *
 * Usage:
 *   <span class="cc-pill">…</span>                     a neutral chip
 *   <span class="cc-pill" style="…">…</span>           or with app colours
 *   <span id="cc-userpill" class="cc-userpill"></span> the identity pill
 *
 * Top-bar contract: the identity pill is ALWAYS in the right-hand group of the
 * bar — `margin-left:auto` shoves it there (it eats all free space to its left)
 * and `order:1000` makes it render last whatever its DOM position. App-specific
 * pills (.cc-pill) live at the LEFT/middle of the bar, well clear of it, so the
 * two groups can never share the corner or overlap. New apps get this for free
 * by mounting #cc-userpill and putting their own pills early in the bar.
 *
 * `order:1000` is a floor, not the end of the bar: the Help button deliberately
 * sits PAST the pill on order:1001 (capcon-help.css), because Help works with
 * no account at all and so belongs outside the sign-in state. Anything else
 * that must render right of the pill needs order > 1000 — DOM position alone
 * will not do it, since flex reorders an unordered item back to order:0. */
.cc-pill,.cc-userpill{display:inline-flex;align-items:center;gap:6px;flex:0 0 auto;
  height:26px;box-sizing:border-box;padding:0 11px;border-radius:13px;
  border:1px solid var(--line2);background:transparent;color:var(--txt2);
  font-family:var(--mono);font-size:11px;line-height:1;letter-spacing:.5px;white-space:nowrap}
.cc-pill b,.cc-userpill b{font-weight:700;color:var(--txt)}

/* Identity pill: teal, pinned to the far-right corner, hidden until populated. */
.cc-userpill{display:none;order:1000;margin-left:auto;color:var(--signal);border-color:var(--signal-dim);
  background:rgba(45,212,191,.06);text-transform:uppercase}
.cc-userpill.cc-userpill-ready{display:inline-flex}
.cc-userpill .cc-userpill-dot{color:var(--ok)}
.cc-userpill .cc-userpill-role{font-weight:700;color:var(--signal)}
.cc-userpill .cc-userpill-groups{color:var(--txt3);text-transform:none;letter-spacing:0}
.cc-userpill .cc-userpill-out{color:var(--warn)}   /* signed-out dot — CAPCON has no demo tier */
.cc-userpill a{color:var(--txt3);text-decoration:none}
.cc-userpill a:hover{color:var(--signal)}

/* App brand block ───────────────────────────────────────────────────────────────
 * The identity block at the TOP of every app's left sidebar column (the same
 * place the Manager puts it): a green-gradient logo tile + a bold CONDENSED
 * "CAPCON <app>" wordmark (Oswald via --font-display) stacked over a short
 * mono UPPERCASE keyword (e.g. CHANGE DETECTION). The condensed face lets the name
 * be large yet still fit the sidebar-width column; the name + keyword ellipsize
 * within it rather than widening it. The block fills the sidebar width and is
 * separated from the menu below by a bottom border. Each app's shell makes the
 * sidebar span full height so this sits above the top bar, which starts at the
 * sidebar's right edge. Markup:
 *   <div class="cc-brand">
 *     <div class="cc-brand-logo">S</div>
 *     <div class="cc-brand-text">
 *       <h1 class="cc-brand-name"><strong>CAPCON</strong> Loader</h1>
 *       <div class="cc-brand-sub">CHANGE DETECTION</div>
 *     </div>
 *   </div>                                                                       */
/* Metrics mirror the Manager's .brand block EXACTLY: 18px padding, a 26px logo
   tile aligned to the TITLE line (align-items:flex-start), and the keyword set a
   relaxed 8px below the title — not crammed against it. The bottom border + 14px
   margin separate it from the menu, same as the Manager sidebar. */
.cc-brand{display:flex;align-items:center;gap:12px;min-width:0;overflow:hidden;flex-shrink:0;
  padding:18px;border-bottom:1px solid var(--line);margin-bottom:14px}
.cc-brand-logo{flex:0 0 auto;width:26px;height:26px;border-radius:6px;display:flex;align-items:center;
  justify-content:center;font-family:var(--font-display);font-size:16px;font-weight:700;color:#fff;letter-spacing:0;
  background:linear-gradient(135deg,var(--signal-dim),#2bbd8a)}

/* ── Application icon — Sentinel-1 satellite ─────────────────────────────────
   Replaces the legacy "S" glyph platform-wide. A centered ::before overlays the
   official Copernicus Sentinel-1 line-art icon (recoloured white,
   /assets/sentinel1-icon.png) on each logo box. The chip is a deliberate dark
   square with a subtle border (the look the Manager had by accident); the old
   text glyph is hidden with color:transparent. Brand chips (.cc-brand-logo and
   the Manager/Admin/API .hdr-logo) are enlarged to span the two-line title +
   keyword; the Help logo (.cc-help-logo) keeps its own size. Covers every app +
   the Help drawer + standalone manuals — no per-app markup change. */
.cc-brand-logo,.hdr-logo,.cc-help-logo{
  color:transparent !important;position:relative;
  background:var(--bg0) !important;          /* dark chip — replaces the old gradients */
  border:1.5px solid rgba(170,200,235,.50);  /* pronounced light frame to emphasise the icon */
}
.cc-brand-logo,.hdr-logo{                    /* brand chips: large, span title + keyword */
  width:44px !important;height:44px !important;border-radius:10px;
}
.brand .brand-txt{display:flex;flex-direction:column;min-width:0}  /* Manager/Admin/API title+sub column beside the icon */
.cc-brand-logo::before,.hdr-logo::before,.cc-help-logo::before{
  content:"";position:absolute;inset:0;
  background:center/80% no-repeat url("/assets/sentinel1-icon.png");
}
.cc-brand-text{display:flex;flex-direction:column;min-width:0}
.cc-brand-name{margin:0;min-width:0;font-family:var(--font-display);font-size:20px;font-weight:600;
  /* line-height + padding-bottom give the condensed face room for its descenders
     (g/p/y) — at line-height:1 the overflow:hidden clip shaved them off. */
  line-height:1.25;padding-bottom:2px;letter-spacing:.4px;color:var(--txt);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.cc-brand-name strong{color:var(--signal);font-weight:700}
/* Short keyword under the wordmark — matches the Manager's .sub treatment
   (mono, uppercase, 2px tracking, a relaxed 8px below the title). */
.cc-brand-sub{margin-top:8px;min-width:0;font-family:var(--mono);font-size:10.5px;line-height:1;
  color:var(--txt3);letter-spacing:2px;text-transform:uppercase;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

/* ── Platform application menu ────────────────────────────────────────────────
 * The six applications, left to right in the order of `apps:` in
 * capcon.project.yaml. It lives in the PORTAL top bar and in EVERY app's top
 * bar, so an operator can move between applications without going back to the
 * portal first. Both copies use this one block: the portal writes the markup by
 * hand, each app's shell has it generated into the shell by bin/stamp_app.py,
 * and a menu that renders differently in the two places is the thing an
 * operator notices before anything else.
 *
 * EQUAL WIDTHS ARE THE POINT. `flex:0 0 <fixed>` on every item, not
 * width-to-content: the straplines differ in length by a factor of three
 * ("validation" against "institutions · users · groups"), so content-sized
 * items put the application names at uneven intervals and the eye cannot find
 * them. Fixed items keep the names on a regular pitch and the gaps identical.
 *
 * EVERY STRAPLINE IS ONE LINE, and is clipped rather than wrapped. Keeping them
 * short enough to fit is the manifest's job, not the CSS's: `strapline:` in
 * capcon.project.yaml is the place to shorten one. A wrapped second line was
 * tried and reverted — it doubled the height of the whole bar to accommodate
 * the two longest entries, and reserving the second line on every item (needed
 * to keep the names on one baseline) meant five of six carried visible dead
 * space.
 *
 * IT NEVER WRAPS. `flex-wrap:nowrap` with shrinkable items: on a narrow window
 * every item narrows by the same amount and the row stays one row. Wrapping was
 * tried first and is worse than it sounds — the last application silently drops
 * to a second line, which reads as a rendering fault rather than as a menu that
 * did not fit, and the app that lands there changes with the window width. */
.cc-appmenu{display:flex;flex-wrap:nowrap;gap:4px;min-width:0}
/* 9.5em ≈ 119px is the PREFERRED width — six items plus gaps ≈ 733px — but the
   basis is shrinkable and capped rather than fixed, so the row adapts instead
   of overflowing. Identical basis and identical shrink factor on every item is
   what keeps the widths equal at any window size. */
.cc-appmenu a{flex:1 1 9.5em;min-width:0;max-width:11em;
  display:block;padding:5px 10px;border-radius:var(--radius-sm);
  border:1px solid var(--line);background:var(--bg0);
  text-decoration:none;color:var(--txt3);font-size:12.5px;font-weight:600;
  letter-spacing:.6px;text-align:center;overflow:hidden;
  transition:color .15s,border-color .15s,background .15s}
.cc-appmenu a:hover{border-color:var(--line2);color:var(--txt2)}

/* ENTITLEMENT IS VISIBLE IN THE MENU. Grey is the resting state: before sign-in
   nothing is known about the account, so nothing claims to be available. On
   sign-in, capcon-user.js adds .entitled to the applications /auth/me lists in
   `apps` — the contract the account's institution holds — and those take the
   same blue as the Help button, which is the platform's "this is available to
   you" colour. Help itself is blue from the start because it needs no account.
   Grey is a SIGNAL, NOT A GATE: the item stays clickable and the app enforces
   access itself (two independent gates — permission, and per-project access).
   A link that looks dead but works is less confusing than one that silently
   does nothing, and entitlement is not the same thing as permission. */
.cc-appmenu a.entitled{border-color:var(--blue3);background:var(--blue4);color:var(--blue)}
.cc-appmenu a.entitled:hover{color:#dfeeff;border-color:var(--blue2);background:var(--blue3)}
/* The app you are in. Marked on the shell's own entry by stamp_app.py; the
   portal has no entry of its own, so nothing is active there. */
.cc-appmenu a.active{box-shadow:inset 0 -2px 0 var(--signal)}
.cc-appmenu a .sub{display:block;overflow:hidden;text-overflow:ellipsis;
  white-space:nowrap;margin-top:3px;font-size:9.5px;font-weight:400;
  line-height:1.3;letter-spacing:.3px;color:var(--txt3);text-transform:none}

/* ── Year · project · period selector ─────────────────────────────────────────
 * Rendered by capcon-contextbar.js into #capcon-context-host, which every app
 * shell puts at the TOP OF THE SIDEBAR, directly under the brand and above the
 * panel list.
 *
 * It began in the top bar and was moved here on 2026-09-09. Two reasons, and
 * the second is the one that matters. Three labelled dropdowns are ~450px wide,
 * which is most of a top bar that also has to hold six application entries —
 * something had to give and it was the menu, one application at a time. And the
 * selection is not navigation: it is the scope every panel in this sidebar
 * reads and writes under, so it belongs beside them, above the list it governs.
 *
 * TWO ROWS: year and period share the first, project takes the second on its
 * own. A year is four digits and a period six, so side by side they waste
 * nothing; a project name is long enough that a half-width control would
 * truncate every one of them. Placement is explicit rather than by source
 * order, so the markup can keep the cascade order (year -> project -> period)
 * that the change handlers depend on. */
.cc-ctx{display:grid;grid-template-columns:1fr 1fr;gap:8px;padding:12px 14px 14px;
  border-bottom:1px solid var(--line)}
.cc-ctx-field{min-width:0;display:flex;flex-direction:column;gap:3px}
.cc-ctx-field[data-field="year"]  {grid-area:1 / 1}
.cc-ctx-field[data-field="period"]{grid-area:1 / 2}
.cc-ctx-field[data-field="project"]{grid-area:2 / 1 / auto / -1}
.cc-ctx-label{font-family:var(--mono);font-size:9.5px;letter-spacing:1.4px;
  text-transform:uppercase;color:var(--txt3)}
.cc-ctx select{width:100%;min-width:0;padding:4px 8px;font-size:13px;
  font-family:inherit;color:var(--txt);background:var(--bg);
  border:1px solid var(--line);border-radius:6px}
.cc-ctx select:disabled{color:var(--txt3);background:var(--panel)}
/* Spans both columns and wraps rather than widening the sidebar, whose width is
   fixed by --sidebar-w. */
.cc-ctx-warn{grid-column:1/-1;font-size:11.5px;line-height:1.35;color:var(--warn,#d8a657)}

/* ── Access gate (sign-in required / access restricted) ───────────────────────
   Shared so every app's sign-in / access-denied screen is identical. Mirrors the
   Manager's original card so all apps match it. Centre a `.cc-gate` card in the
   page (or in a full-width container) and use the helper classes below. */
.cc-gate{max-width:580px;margin:13vh auto;padding:36px;background:#11161c;
  border:1px solid #21303d;border-radius:11px;text-align:center;
  font-family:var(--sans);color:#cdd6e0}
.cc-gate-icon{font-size:44px;margin-bottom:10px}
.cc-gate-title{font-size:21px;margin:0 0 14px;color:#fff;font-weight:600}
.cc-gate p{line-height:1.6;color:#9fb0bf;margin:0 0 4px}
.cc-gate-note{color:#e0b050;margin:6px 0 0}
.cc-gate-btn{display:inline-block;background:#13344f;border:1px solid #2a6699;color:#cfe8ff;
  padding:11px 22px;border-radius:8px;text-decoration:none;font-weight:600;cursor:pointer}
.cc-gate-btn:hover{background:#184a6e}
.cc-gate-btn-ghost{display:inline-block;background:#1b2733;border:1px solid #21303d;color:#cdd6e0;
  padding:10px 20px;border-radius:8px;text-decoration:none}
.cc-gate-btn-ghost:hover{border-color:#2a6699}
.cc-gate-link{color:#5bb8ff;font-size:13px;text-decoration:none}
.cc-gate-link:hover{text-decoration:underline}

/* ── Data tables + row furniture ──────────────────────────────────────────────
 * Added for the Admin app, but kept in the KIT rather than in one panel: Checks
 * and Results list rows too, and a second private copy is how two screens in
 * one platform end up with different row heights and different empty states.
 *
 * Wrap a table in .cc-tablewrap. A table is the one thing allowed to be wider
 * than the panel — the wrapper scrolls it instead of the page, so a long
 * permission list cannot push the whole layout sideways.
 */
.cc-tablewrap{overflow-x:auto;max-width:100%}
.cc-table{width:100%;border-collapse:collapse;font-size:13px}
.cc-table th{text-align:left;color:var(--txt3);font-family:var(--mono);font-size:11px;font-weight:600;
  letter-spacing:.5px;text-transform:uppercase;padding:7px 8px;border-bottom:1px solid var(--line);
  white-space:nowrap}
.cc-table td{padding:9px 8px;border-bottom:1px solid var(--line);vertical-align:top;color:var(--txt);
  overflow-wrap:anywhere}
.cc-table tr:last-child td{border-bottom:0}
.cc-table td.cc-right,.cc-table th.cc-right{text-align:right;white-space:nowrap}
/* The editor drawer: a full-width row that opens under the record being edited,
   so the thing you are changing stays visible above it. */
.cc-table tr.cc-editing>td{background:var(--bg0,var(--bg));padding:14px 10px}

/* A chip. .cc-tag-ok / .cc-tag-warn variants colour it; the × is a real button, never a span
   with an onclick, so it is reachable by keyboard like every other control. */
.cc-tag{display:inline-flex;align-items:center;gap:5px;font-family:var(--mono);font-size:10px;
  letter-spacing:.5px;text-transform:uppercase;background:var(--panel2);border:1px solid var(--line2);
  color:var(--txt2);border-radius:5px;padding:3px 7px;margin:2px 3px 2px 0}
.cc-tag-ok{background:rgba(58,191,128,.14);border-color:var(--ok);color:var(--ok)}
.cc-tag-warn{background:rgba(240,176,64,.14);border-color:var(--warn);color:var(--warn)}
.cc-tag-muted{opacity:.6}
.cc-tag .cc-tag-x{all:unset;cursor:pointer;color:var(--txt3);font-weight:700;line-height:1}
.cc-tag .cc-tag-x:hover{color:var(--err,#cf7060)}
.cc-tag .cc-tag-x:focus-visible{outline:1px solid var(--signal);outline-offset:2px}

.cc-dot{display:inline-block;width:8px;height:8px;border-radius:50%;margin-right:6px}
.cc-dot-on{background:var(--ok)} .cc-dot-off{background:var(--err,#cf7060)}
.cc-muted{color:var(--txt3)}
.cc-row{display:flex;gap:10px;align-items:center;flex-wrap:wrap}
/* Inline status line for a panel: quiet by default, red only on failure. */
.cc-msg{min-height:18px;font-family:var(--mono);font-size:12px;letter-spacing:.3px;color:var(--txt3)}
.cc-msg-err{color:var(--err,#cf7060)}
.cc-empty{color:var(--txt3);font-size:13px;padding:10px 8px}

/* ── Panel annotation block ───────────────────────────────────────────────────
 * The heading paragraph at the top of a panel, laid out as TWO columns: the
 * lead on the left, the practical essentials on the right.
 *
 * Why not simply widen the paragraph. A single column of prose running the full
 * width of a 1400px panel is a ~180-character measure, which is markedly harder
 * to read than the too-tall column it replaced — the eye loses the line on the
 * return sweep. Two columns use the whole width, keep each measure short, and
 * turn the space saved into something worth reading.
 *
 * Collapses to one column below 900px, where two columns would leave neither
 * of them wide enough to be worth having.
 */
/* 1fr : 2fr — the lead is a sentence or two of orientation, the essentials are
   the reference an operator actually returns to, and an even split made the
   short half look padded while the useful half wrapped more than it needed to. */
.cc-annot{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,2fr);
  gap:2px 34px;align-items:start;margin-bottom:10px}
.cc-annot .lead{max-width:none;margin:0}
@media (max-width:900px){ .cc-annot{grid-template-columns:minmax(0,1fr);gap:12px} }

/* term → fact pairs. A tight grid rather than a <ul>, so the terms line up and
   scan as a reference card instead of reading as more prose. */
.cc-essentials{display:grid;grid-template-columns:auto minmax(0,1fr);gap:3px 10px;
  font-size:12.5px;line-height:1.5;align-content:start}
.cc-essentials dt{color:var(--txt);font-weight:600;white-space:nowrap}
.cc-essentials dd{color:var(--txt3);margin:0}
@media (max-width:520px){
  .cc-essentials{grid-template-columns:minmax(0,1fr);gap:1px}
  .cc-essentials dd{margin:0 0 6px}
}
