/* AutoSteward — control surfaces (buttons, tabs, chips, quiet actions)
 * =====================================================================
 * ONE authority for what a control looks like. Loaded last on purpose.
 *
 * WHY THIS FILE EXISTS — three measured defects, not a matter of taste:
 *
 * 1. Controls were painted for light mode and then patched back for dark with a
 *    slab of `html[data-theme="dark"] … !important` rules. That patch keys on the
 *    APPEARANCE, but `midnight` is a dark design in BOTH of its appearances
 *    (--canvas #071120 at data-theme="light"). So the patch never fires there and
 *    you get a white button with a #9eb1c6 border sitting on a near-black page.
 *
 * 2. Those dark patches hardcode #156fbd / #2d8bd5 / #1768b2. Measured across all
 *    ten designs in dark mode, every primary button came back rgb(21,111,189) —
 *    one blue for nine distinct accents. Picking Ledger (green) or Teal or Onyx
 *    (grey) changed nothing. The design picker was silently dead for controls.
 *
 * 3. `.security-filter-button` was `color:#26445f` on a transparent face with a
 *    transparent border and no dark-mode correction anywhere — 1.72:1 text on
 *    every dark surface. Invisible, 20 of 20 design x appearance combinations.
 *
 * THE FIX — derive from polarity, never from `data-theme`.
 * Every design already declares --ink and --surface as opposite poles. So
 * `color-mix(in srgb, var(--ink) 28%, transparent)` is a dark edge on a light
 * design and a light edge on a dark one, with no branch and nothing to keep in
 * sync. A design that is dark in its light appearance is handled for free.
 * That property is what `tests/test_controls.mjs` pins.
 *
 * BOUNDARY — this file sets colour, edge, shadow, focus and press. It never sets
 * geometry. Sizes, padding, min-height and gap stay in styles.css, because
 * contract tests pin gap:10px, padding:18px and min-height:32px, and a stray
 * declaration here would move them out from under those tests.
 *
 * NO COLOUR TRANSITIONS. Transitioning a property whose value comes from a custom
 * property freezes the old paint when the design axis changes, which is what broke
 * the live preview in the design picker once already. Only `transform` and
 * `box-shadow` animate here; the press state carries the feedback instead.
 */

:root{
  /* Face: the control's own fill. Mixing --ink INTO the surface darkens on a light
     design and lightens on a dark one — the same declaration, both polarities. */
  --ctl-face:            var(--surface-strong, #fff);
  --ctl-face-hover:      color-mix(in srgb, var(--ink) 8%,  var(--surface-strong, #fff));
  --ctl-face-active:     color-mix(in srgb, var(--ink) 15%, var(--surface-strong, #fff));
  --ctl-ink:             var(--ink);

  /* Edge: the thing that was missing. A control must be findable before it is
     readable, so every control gets one and it can never mix to transparent. */
  --ctl-edge:            color-mix(in srgb, var(--ink) 30%, transparent);
  --ctl-edge-hover:      color-mix(in srgb, var(--ink) 52%, transparent);
  --ctl-edge-quiet:      color-mix(in srgb, var(--ink) 26%, transparent);

  --ctl-shadow:          0 1px 2px color-mix(in srgb, var(--ink) 15%, transparent);
  --ctl-shadow-hover:    0 2px 5px color-mix(in srgb, var(--ink) 20%, transparent);

  /* Emphasis rides the design's own accent, which is the whole point of the picker, and it is
     now the accent ITSELF rather than a darkened version of it.

     It used to be deepened to 72%, because the raw swatch is a display colour and white is not
     readable on a bright one — white on Alpine's #0ea5e9 measured 2.7:1. That was the right fix
     for the wrong layer: it darkened the BUTTON so that a hardcoded white would fit, while the
     active nav block went on painting the raw accent with the same hardcoded white and stayed at
     2.6:1. Two surfaces, one colour, one of them quietly unreadable.

     Each palette now states --accent-ink, the text colour that belongs on its accent, so the
     deepening has nothing left to do — and while it was still here it pulled the other way,
     dropping a dark ink onto an already-dark bed (claret's dark primary measured 3.61:1).
     Dropping it also makes the primary button and the active page the same colour, which is what
     anyone would have assumed they were. tests/test_design_palettes.mjs holds the ink contrast. */
  --ctl-accent:          var(--accent, #0369a1);
  --ctl-accent-hover:    color-mix(in srgb, var(--accent, #0369a1) 86%, #000);
  --ctl-accent-ink:      var(--accent-ink, #fff);
  --ctl-ring:            color-mix(in srgb, var(--accent, #1768b2) 60%, transparent);

  /* Quiet actions read as text until touched. They still need a hit-surface. */
  --ctl-quiet-ink:       color-mix(in srgb, var(--accent, #1768b2) 72%, var(--ink));
}

/* ── The default control ────────────────────────────────────────────────────
   :root prefixes lift these to 0-2-0 so they beat the bare single-class rules
   in styles.css without needing !important. */
:root :is(.button, .desktop-action-button, .desktop-menu-button, .desktop-tab,
          .account-menu-button, .header-search-button, .icon-button, .system-close-button){
  color: var(--ctl-ink);
  background: var(--ctl-face);
  background-image: none;              /* kills the inherited #fff→#edf2f7 bevel */
  border: 1px solid var(--ctl-edge);
  box-shadow: var(--ctl-shadow);
  transition: box-shadow .12s ease, transform .06s ease;
}

:root :is(.button, .desktop-action-button, .desktop-menu-button, .desktop-tab,
          .account-menu-button, .header-search-button, .icon-button,
          .system-close-button):hover:not(:disabled):not([aria-disabled="true"]){
  color: var(--ctl-ink);
  background: var(--ctl-face-hover);
  border-color: var(--ctl-edge-hover);
  box-shadow: var(--ctl-shadow-hover);
}

/* Press is the feedback, since colour cannot animate. The control goes down and
   its shadow collapses under it — a physical grip, matching the wheel mark. */
:root :is(.button, .desktop-action-button, .desktop-menu-button, .desktop-tab,
          .account-menu-button, .header-search-button, .icon-button,
          .system-close-button):active:not(:disabled){
  background: var(--ctl-face-active);
  box-shadow: inset 0 1px 2px color-mix(in srgb, var(--ink) 22%, transparent);
  transform: translateY(1px);
}

/* ── Emphasis ─────────────────────────────────────────────────────────────── */
:root .button.primary,
:root .desktop-action-button.primary{
  color: var(--ctl-accent-ink);
  background: var(--ctl-accent);
  border-color: color-mix(in srgb, var(--ctl-accent) 74%, #000);
  box-shadow: var(--ctl-shadow);
}
:root .button.primary:hover:not(:disabled),
:root .desktop-action-button.primary:hover:not(:disabled){
  color: var(--ctl-accent-ink);
  background: var(--ctl-accent-hover);
  border-color: color-mix(in srgb, var(--ctl-accent) 58%, #000);
  box-shadow: var(--ctl-shadow-hover);
}

/* --red-solid, not --red.
 *
 * --red is tuned to be read as TEXT against the appearance's canvas, so the dark palette
 * defines it as a pale #ff8d96. Used here as a FILL under `color:#fff` it measured 2.21:1 in
 * dark across ALL TEN designs — every Delete, Purge and Remove button in the program had a
 * label you could not read, on exactly the buttons that must be understood before they are
 * pressed. --red-solid is the same red in light and a properly dark one in dark, so white
 * carries in both. Keep the two apart: a status colour and a fill colour want opposite
 * lightness, and one token cannot be both. */
:root .button.danger{
  color: #fff;
  background: var(--red-solid, #c9363e);
  /* Saturated fills can sit at the same luminance as a dark canvas, so the edge
     is what separates them — hue alone does not survive a greyscale check. */
  border-color: color-mix(in srgb, var(--red-solid, #c9363e) 58%, var(--ink));
}
:root .button.danger:hover:not(:disabled){
  background: color-mix(in srgb, var(--red-solid, #c9363e) 86%, #000);
  border-color: color-mix(in srgb, var(--red-solid, #c9363e) 40%, var(--ink));
}

/* 58% not 78%: the face is already tinted with the same hue, so the ink has to keep
   enough of --ink in it to stay apart from that face. Measured floor is midnight,
   whose light appearance is a dark surface -- 78% landed there at 3.99:1. */
:root .button.danger-outline{
  color: color-mix(in srgb, var(--red, #c9363e) 58%, var(--ink));
  background: color-mix(in srgb, var(--red, #c9363e) 9%, var(--surface-strong, #fff));
  border-color: color-mix(in srgb, var(--red, #c9363e) 46%, transparent);
}
:root .button.danger-outline:hover:not(:disabled){
  background: color-mix(in srgb, var(--red, #c9363e) 17%, var(--surface-strong, #fff));
  border-color: color-mix(in srgb, var(--red, #c9363e) 66%, transparent);
}

:root .button.warning-action{
  color: color-mix(in srgb, var(--amber, #a8650a) 58%, var(--ink));
  background: color-mix(in srgb, var(--amber, #a8650a) 12%, var(--surface-strong, #fff));
  border-color: color-mix(in srgb, var(--amber, #a8650a) 50%, transparent);
}
:root .button.warning-action:hover:not(:disabled){
  background: color-mix(in srgb, var(--amber, #a8650a) 20%, var(--surface-strong, #fff));
  border-color: color-mix(in srgb, var(--amber, #a8650a) 70%, transparent);
}

/* ── Quiet actions ──────────────────────────────────────────────────────────
   These are meant to read as text, but the owner's complaint is that they vanish.
   So: accent-derived ink that is always mixed against --ink (never a fixed blue
   that goes muddy on a dark canvas), and a real surface the moment you touch
   them. `.link-btn` keeps its inline flow — no border in the resting state. */
:root .link-btn{
  color: var(--ctl-quiet-ink);
  background: none;
  border: 0;
  border-radius:var(--r-control);
  text-decoration-line: underline;
  text-decoration-color: color-mix(in srgb, var(--ctl-quiet-ink) 38%, transparent);
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
  cursor: pointer;
}
:root .link-btn:hover:not(:disabled){
  color: color-mix(in srgb, var(--accent, #1768b2) 88%, var(--ink));
  text-decoration-color: currentColor;
}

:root :is(.header-help-button, .security-filter-button){
  color: var(--ctl-ink);
  background: transparent;
  border: 1px solid var(--ctl-edge-quiet);
  box-shadow: none;
  transition: box-shadow .12s ease, transform .06s ease;
}
:root :is(.header-help-button, .security-filter-button):hover:not(:disabled){
  color: var(--ctl-ink);
  background: var(--ctl-face-hover);
  border-color: var(--ctl-edge-hover);
}
:root :is(.header-help-button, .security-filter-button):active:not(:disabled){
  transform: translateY(1px);
}

/* The count pill inside a filter button. Was #435971 on #d8e3ed — a light chip
   with dark text, unreadable the moment the surrounding surface went dark. */
:root .security-filter-button strong{
  color: var(--ctl-ink);
  background: color-mix(in srgb, var(--ink) 13%, transparent);
}
:root .security-filter-button.active{
  color: var(--ctl-accent-ink);
  background: var(--ctl-accent);
  border-color: color-mix(in srgb, var(--ctl-accent) 74%, #000);
  box-shadow: var(--ctl-shadow);
}
:root .security-filter-button.active strong{
  color: var(--ctl-accent);
  background: var(--ctl-accent-ink);
}

/* ── Selected tabs ──────────────────────────────────────────────────────────
   Same story as the primary button: the dark patch pinned these to #1768b2 for
   every design. */
:root :is(.vehicle-tabs, .system-tools-tabs, .tools-section-tabs) button:is(.active, [aria-current="page"]),
:root .desktop-tab:is(.active, [aria-current="page"]),
:root .alignment-control-section .button.active{
  color: var(--ctl-accent-ink);
  background: var(--ctl-accent);
  border-color: color-mix(in srgb, var(--ctl-accent) 74%, #000);
}

/* ── Sale Wizard validation / Finance state ───────────────────────────────
   FIX135: controls.css is loaded last, so the state styling belongs here. Keeping
   these rules in styles.css allowed the default .button authority above to repaint
   the Finance control after Sale Wizard state classes had been applied. */
:root .button.sw-detail-button.sw-finance-ready{
  color: var(--ctl-ink);
  background: var(--ctl-face);
  border-color: var(--ctl-accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--ctl-accent) 62%, transparent), var(--ctl-shadow);
}
:root .button.sw-detail-button.sw-finance-ready:hover:not(:disabled){
  color: var(--ctl-ink);
  background: var(--ctl-face-hover);
  border-color: var(--ctl-accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--ctl-accent) 72%, transparent), var(--ctl-shadow-hover);
}
:root .button.sw-detail-button.sw-finance-ready b{
  color: var(--ctl-accent-ink);
  background: var(--ctl-accent);
}

:root .button.sw-detail-button.sw-finance-complete{
  color: var(--ctl-ink);
  background: var(--ctl-face);
  border-color: var(--pui-ok, #1c7a4a);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--pui-ok, #1c7a4a) 68%, transparent), var(--ctl-shadow);
}
:root .button.sw-detail-button.sw-finance-complete:hover:not(:disabled){
  color: var(--ctl-ink);
  background: var(--ctl-face-hover);
  border-color: var(--pui-ok, #1c7a4a);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--pui-ok, #1c7a4a) 78%, transparent), var(--ctl-shadow-hover);
}
:root .button.sw-detail-button.sw-finance-complete b{
  color: #fff;
  background: var(--pui-ok, #1c7a4a);
}

/* Stale BHPH deliberately keeps the existing amber/orange badge. It means the
   schedule existed but an upstream amount changed and generation is required. */
:root .button.sw-detail-button.sw-finance-stale b{
  color: #fff;
  background: var(--pui-warn, #9a6700);
}

/* Required data must be visually unmistakable. The prior 16% ring was too faint
   on the dark Sale Wizard. Keep the field face readable while making the edge and
   outer ring explicit. */
:root .sw-field :is(input, select).sw-missing,
:root .sw-detail-button.sw-missing{
  border-color: var(--pui-risk, #b4341f) !important;
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--pui-risk, #b4341f) 62%, transparent) !important;
}
:root .sw-field :is(input, select).sw-missing:focus{
  border-color: var(--pui-risk, #b4341f) !important;
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--pui-risk, #b4341f) 76%, transparent) !important;
}

/* ── Disabled ───────────────────────────────────────────────────────────────
   Muted rather than faded to nothing: opacity alone on a dark canvas dissolves
   the control completely. */
:root :is(.button, .desktop-action-button, .desktop-menu-button, .desktop-tab,
          .link-btn, .security-filter-button):disabled,
:root :is(.button, .desktop-action-button)[aria-disabled="true"]{
  color: color-mix(in srgb, var(--ink) 42%, transparent);
  background: color-mix(in srgb, var(--ink) 5%, var(--surface, #fff));
  border-color: var(--ctl-edge-quiet);
  box-shadow: none;
  transform: none;
  opacity: 1;
  cursor: not-allowed;
  text-decoration: none;
}

/* ── Focus ──────────────────────────────────────────────────────────────────
   One ring everywhere, on the design's accent, offset so it never sits on top of
   the control's own edge. */
:root :is(.button, .desktop-action-button, .desktop-menu-button, .desktop-tab,
          .link-btn, .header-help-button, .header-search-button,
          .security-filter-button, .account-menu-button, .icon-button):focus-visible{
  outline: 2px solid var(--ctl-accent);
  outline-offset: 2px;
  box-shadow: 0 0 0 4px var(--ctl-ring);
}

/* Windows high-contrast: system colours must win outright, and translucent
   color-mix edges are dropped there. */
@media (forced-colors: active){
  :root :is(.button, .desktop-action-button, .desktop-menu-button, .desktop-tab,
            .header-help-button, .security-filter-button, .account-menu-button,
            .header-search-button, .icon-button){
    border: 1px solid ButtonBorder;
    box-shadow: none;
  }
}

@media (prefers-reduced-motion: reduce){
  :root :is(.button, .desktop-action-button, .desktop-menu-button, .desktop-tab,
            .header-help-button, .security-filter-button):active{
    transform: none;
  }
}

/* FIX140 — compact page tabs use the same unmistakable blue selected state as Sales.
 * This file loads last, so keep this authority here rather than fighting it in styles.css. */
:root :is(.system-tools-tabs,.titles-tabs,.financial-top-tabs) button:is(.active,[aria-current="page"]){
  color:#fff;
  background:#075dcc;
  border-color:#9ac8ff;
  box-shadow:0 0 0 2px rgba(7,93,204,.24),0 4px 12px rgba(7,93,204,.28);
}

/* FIX161 — Inventory Insights: one compact page with top tabs, management periods and
 * record-level drill-downs. Financial visibility is enforced by the launcher; these styles are
 * presentation only and must never be treated as a permission boundary. */
:root .insights-tabs{
  display:flex;flex-wrap:wrap;gap:6px;margin:0 0 16px;padding:5px;
  width:max-content;max-width:100%;border:1px solid var(--ctl-edge-quiet);
  border-radius:12px;background:color-mix(in srgb,var(--surface,#fff) 94%,var(--ink) 6%);
}
:root .insights-tab{
  min-height:36px;padding:7px 13px;border:1px solid transparent;border-radius:9px;
  background:transparent;color:var(--ink);font:inherit;font-weight:700;cursor:pointer;
}
:root .insights-tab.is-active{
  color:#fff;background:#075dcc;border-color:#9ac8ff;
  box-shadow:0 0 0 2px rgba(7,93,204,.2),0 3px 10px rgba(7,93,204,.22);
}
:root .insights-periods{display:flex;flex-wrap:wrap;gap:7px;margin:12px 0 14px}
:root .insights-custom-dates{display:flex;flex-wrap:wrap;gap:12px;margin:-2px 0 14px}
:root .insights-custom-dates label{display:grid;gap:5px;font-weight:700}
:root .insights-custom-dates input{min-height:38px}
:root .insights-management{margin-top:16px}
:root .insights-kpi{appearance:none;text-align:left;font:inherit;color:inherit;cursor:pointer;width:100%}
:root .insights-kpi.is-active{outline:2px solid var(--ctl-accent);outline-offset:2px}
:root .insights-filterbar{display:flex;flex-wrap:wrap;align-items:center;gap:10px;margin:12px 0}
:root .insights-filterbar .search{flex:1 1 280px;min-width:220px}
:root .insights-filterbar select{min-height:40px;max-width:280px}
:root .insights-row-actions{display:flex;flex-wrap:wrap;gap:6px;white-space:nowrap}
:root .insights-negative{color:var(--red,#b4341f);font-weight:800}
:root .insights-drilldown{margin-top:14px}
@media (max-width:700px){
  :root .insights-tabs{width:100%}
  :root .insights-tab{flex:1 1 calc(50% - 6px)}
  :root .insights-filterbar .search,:root .insights-filterbar select{width:100%;max-width:none;flex-basis:100%}
}

/* FIX161 R2 — Inventory Insights owner-test UX correction.
 * Keep the page dense and managerial: compact summary cards, real KPI cards instead of a flat
 * ruled strip, an unmistakable selected KPI, and useful content immediately under the controls. */
:root .insights-shell{max-width:1480px;margin:0 auto;display:grid;gap:14px}
:root .insights-overview-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:12px}
:root .insights-summary-card{padding:16px 18px;border:1px solid var(--line);border-radius:12px;background:var(--surface);box-shadow:var(--shadow);min-width:0}
:root .insights-summary-card>strong{display:block;margin:2px 0 9px;color:var(--ink);font-size:var(--fs-h2);line-height:var(--lh-h2);letter-spacing:-.02em}
:root .insights-summary-card>div{display:flex;flex-wrap:wrap;gap:6px 12px;color:var(--muted);font-size:var(--fs-small)}
:root .insights-summary-card .risk{color:var(--red);font-weight:700}
:root .insights-management{margin-top:0;padding:0;overflow:visible}
:root .insights-management-head{display:flex;align-items:flex-end;justify-content:space-between;gap:18px;padding:16px 18px 10px;border-bottom:1px solid var(--line)}
:root .insights-management-head h2{margin:0;color:var(--ink);font-size:var(--fs-h2)}
:root .insights-management-head p:not(.eyebrow){margin:4px 0 0;color:var(--muted);font-size:var(--fs-small)}
:root .insights-management-head .insights-periods{justify-content:flex-end;margin:0}
:root .insights-management-head .insights-custom-dates{margin:8px 0 0}
:root .insights-financial-grid{grid-template-columns:repeat(5,minmax(0,1fr));gap:10px;margin:0;padding:12px 14px;border:0;border-radius:0;background:transparent;overflow:visible}
:root .insights-financial-grid .insights-kpi{position:relative;display:flex;min-height:96px;padding:13px 14px;border:1px solid var(--line);border-radius:11px;background:var(--surface-soft);box-shadow:none;transition:transform .14s ease,border-color .14s ease,box-shadow .14s ease,background .14s ease}
:root .insights-financial-grid .insights-kpi:first-child{border-left:1px solid var(--line)}
:root .insights-financial-grid .insights-kpi:hover{transform:translateY(-2px);border-color:color-mix(in srgb,var(--blue) 45%,var(--line));box-shadow:0 6px 14px color-mix(in srgb,var(--ink) 10%,transparent)}
:root .insights-financial-grid .insights-kpi.is-active{border:2px solid var(--blue);background:color-mix(in srgb,var(--blue) 16%,var(--surface));box-shadow:0 8px 20px color-mix(in srgb,var(--blue) 20%,transparent),inset 0 0 0 1px color-mix(in srgb,var(--blue) 35%,transparent);outline:0;transform:translateY(-2px)}
:root .insights-financial-grid .insights-kpi.is-active .kpi-copy strong{color:var(--ink);font-weight:800}
:root .insights-financial-grid .insights-kpi.is-active .kpi-copy strong::before{background:var(--blue)}
:root .insights-financial-grid .insights-kpi.danger.is-active{border-color:var(--red);background:color-mix(in srgb,var(--red) 12%,var(--surface));box-shadow:0 8px 20px color-mix(in srgb,var(--red) 15%,transparent)}
/* The label keeps clear of the corner badge. At 1180px a KPI card is ~160px wide and "Avg Front Gross" ran
   under "VIEW" (measured by tools/dev/walk); the label now wraps short of the badge: "VIEW" needs
   36px, the active card's "VIEWING" 62px (both measured). */
:root .insights-financial-grid .insights-kpi .kpi-copy>strong{padding-right:36px}
:root .insights-financial-grid .insights-kpi.is-active .kpi-copy>strong{padding-right:62px}
:root .insights-kpi-state{position:absolute;right:10px;top:9px;color:var(--muted);font-size:var(--fs-micro);font-weight:800;text-transform:uppercase;letter-spacing:.06em}
:root .insights-kpi.is-active .insights-kpi-state{color:var(--blue)}
:root .insights-kpi.danger.is-active .insights-kpi-state{color:var(--red)}
:root .insights-detail-link{display:flex;align-items:center;gap:12px;padding:10px 16px;margin:0 14px;border-left:3px solid var(--blue);background:color-mix(in srgb,var(--blue) 7%,transparent)}
:root .insights-detail-link strong{color:var(--ink)}
:root .insights-detail-link span{color:var(--muted);font-size:var(--fs-small)}
:root .insights-management>.insights-filterbar{margin:10px 14px}
:root .insights-management>.insights-drilldown{margin:0 14px 14px}
:root .insights-stat-strip{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:0;border:1px solid var(--line);border-radius:11px;background:var(--surface);overflow:hidden}
:root .insights-stat-strip>div{padding:11px 14px;border-left:1px solid var(--line)}
:root .insights-stat-strip>div:first-child{border-left:0}
:root .insights-stat-strip span{display:block;color:var(--muted);font-size:var(--fs-small)}
:root .insights-stat-strip strong{display:block;margin-top:2px;color:var(--ink);font-size:var(--fs-lead)}
:root .insights-stat-strip .risk strong{color:var(--red)}
:root .insights-highlights{display:grid;grid-template-columns:repeat(5,minmax(0,1fr));gap:8px;padding:0 14px 12px}
:root .insights-highlight{padding:10px 12px;border:1px solid var(--line);border-radius:9px;background:var(--surface-soft);min-width:0}
:root .insights-highlight span,:root .insights-highlight small{display:block;color:var(--muted);font-size:var(--fs-small);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
:root .insights-highlight strong{display:block;margin:2px 0;color:var(--ink);font-size:var(--fs-lead)}
:root .insights-highlight.bad strong{color:var(--red)}
:root .insights-highlight.good strong{color:var(--green)}
:root .insights-attention{margin-top:0}
:root .insights-reasons{display:flex;flex-wrap:wrap;gap:4px}
:root .insights-reason{display:inline-flex;padding:3px 7px;border-radius:999px;background:var(--ambersoft);color:var(--amber);font-size:var(--fs-micro);font-weight:700;white-space:nowrap}
:root .insights-data-warning{background:color-mix(in srgb,var(--red) 7%,transparent)}
:root .insights-inline-warning{display:block;margin-top:2px;color:var(--red);font-weight:800;font-size:var(--fs-micro)}
:root .insights-market-note{display:block;margin-top:3px;color:var(--muted);font-size:var(--fs-micro)}
:root .insights-position-alert{color:var(--amber)}
:root .insights-filterbar{margin:0;gap:8px}
:root .insights-sold .insights-highlights{padding-top:0}
@media (max-width:1100px){
  :root .insights-overview-grid{grid-template-columns:1fr 1fr}
  :root .insights-financial-grid{grid-template-columns:repeat(3,minmax(0,1fr))}
  :root .insights-highlights{grid-template-columns:repeat(3,minmax(0,1fr))}
}
@media (max-width:760px){
  :root .insights-overview-grid{grid-template-columns:1fr}
  :root .insights-management-head{align-items:stretch;flex-direction:column}
  :root .insights-management-head .insights-periods{justify-content:flex-start}
  :root .insights-financial-grid,:root .insights-highlights{grid-template-columns:1fr 1fr}
  :root .insights-detail-link{align-items:flex-start;flex-direction:column;gap:2px}
}

/* HIDDEN MEANS HIDDEN. The permission layer in app.js (applyPermissionUi) hides a control a role
 * will be refused by setting the `hidden` attribute, and the browser's own `[hidden]{display:none}`
 * loses to ANY author display rule: `.button{display:inline-flex}` alone kept every hidden button
 * on screen. Measured on the running app as Accounting and Read-only, 2026-09-28: Delete, Delete
 * Customer, Archive, Import and Remove selected were all "hidden" and all visible, all enabled,
 * all refused by the launcher when pressed. !important because many rules here are `:root .x`,
 * which outranks a bare attribute selector; nothing in the app shows an element it marked hidden. */
[hidden]{display:none!important}
