/* Document-level stylesheet. Served from 'self' under style-src 'self'.
 *
 * NOTE, stated because §7 layer 2 otherwise looks stronger than it is: the
 * @font-face rule below is the ONE document-level style the ceremony surface
 * depends on. @font-face inside a shadow root is not applied by any engine —
 * font faces are document-scoped — so the pinned family MUST be declared here
 * and the shadow's constructed sheet can only refer to it by name.
 *
 * What that does and does not open:
 *   - it does NOT let document CSS style the ceremony surface. `:host { all:
 *     initial }` still resets every inherited property at the shadow boundary,
 *     and a document rule cannot select into a closed root.
 *   - it DOES mean an attacker who could add a stylesheet to this document
 *     could redefine `FGMonoASCII` to point at a font of their choosing. That
 *     requires defeating `style-src 'self'` — i.e. arbitrary same-origin file
 *     serving, at which point they would simply replace the bundle. It is the
 *     §4.3 residual, not a new one.
 *
 * There is deliberately no `local()` source: a locally installed JetBrains Mono
 * would satisfy a local() lookup and silently become the renderer, which is
 * exactly the unreviewed-renderer problem layer 4 exists to remove.
 */
@font-face {
  font-family: 'FGMonoASCII';
  src: url('/fonts/fg-mono-ascii.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  /* `block` rather than `swap`: a swap period would paint the request in a
   * fallback face first, which is precisely the glyph-substitution window this
   * design refuses. If the face never arrives, the font gate refuses to render
   * a signable view at all. */
  font-display: block;
  unicode-range: U+0020-007E;
}

:root {
  color-scheme: light dark;
  --fg-ink: #111;
  --fg-paper: #fff;
  --fg-rule: #ccc;
  --fg-alarm: #7a1010;
}

html,
body {
  margin: 0;
  padding: 0;
  background: var(--fg-paper);
  color: var(--fg-ink);
  font-family: system-ui, sans-serif;
}

main {
  padding: 1rem;
  max-width: 72rem;
}

.footer {
  border-top: 1px solid var(--fg-rule);
  margin-top: 2rem;
  padding-top: 0.5rem;
  font-family: 'FGMonoASCII', monospace;
  font-size: 0.75rem;
}

.bundle-hash {
  user-select: all;
}

.banner-alarm {
  border: 2px solid var(--fg-alarm);
  background: #fff3f3;
  color: var(--fg-alarm);
  padding: 0.75rem;
  font-weight: 700;
}

/* ---------------------------------------------------------------- pass two --
 *
 * The screens. Two rules run through everything below, and both are security
 * properties rather than taste:
 *
 *   1. COLOUR IS NEVER THE ONLY SIGNAL. Every status carries a glyph and a word
 *      (`.badge-glyph` + `.badge-label`, emitted together by `app/dom.ts`), so
 *      the hues here are reinforcement. Some of them are deliberately below
 *      3:1 against the paper; that is acceptable precisely because they are not
 *      the channel. The `forced-colors` block at the bottom is the proof: with
 *      every hue stripped, the screen still reads.
 *
 *   2. NOTHING HERE STYLES THE CEREMONY SURFACE. `fg-exact-view` is a CLOSED
 *      shadow root with `:host { all: initial }` and its own constructed
 *      stylesheet. No selector in this file can reach into it, and none tries.
 *      The one document-level style the ceremony depends on is the @font-face
 *      at the top of this file, for the reason stated there.
 */

.shell { display: block; }

.nav { display: flex; gap: 0.75rem; border-bottom: 1px solid var(--fg-rule); padding-bottom: 0.5rem; }
.nav-item { text-decoration: none; padding: 0.25rem 0.5rem; color: inherit; }
.nav-on { border-bottom: 3px solid var(--fg-ink); font-weight: 700; }

.outlet { padding-top: 1rem; }
.screen-head { display: flex; gap: 1rem; align-items: baseline; flex-wrap: wrap; }
.muted { color: #555; font-size: 0.875rem; }
.error, .notice { border-left: 4px solid var(--fg-alarm); padding-left: 0.5rem; }
.boundary { border: 1px solid var(--fg-rule); padding: 0.5rem; font-size: 0.875rem; }

/* Icon plus label, as one inline unit that cannot wrap apart. */
.badge { display: inline-flex; gap: 0.35rem; align-items: baseline; white-space: nowrap; }
.badge-glyph { font-family: 'FGMonoASCII', monospace; }
.badge-label { font-size: 0.875rem; }
.verdict-allow .badge-glyph { color: #2f6b2f; }
.verdict-escalate .badge-glyph { color: #8a6100; }
.verdict-block .badge-glyph { color: var(--fg-alarm); }
.verdict-hold .badge-glyph { color: #4a4a8a; }

.tiles { display: flex; flex-wrap: wrap; gap: 0.5rem; margin: 0.75rem 0; }
.tile { border: 1px solid var(--fg-rule); padding: 0.5rem 0.75rem; min-width: 7rem; }
.tile-value { font-size: 1.25rem; font-weight: 700; font-family: 'FGMonoASCII', monospace; }
.tile-label { font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.04em; }
.tile-note { font-size: 0.75rem; color: #555; }

.chips { display: flex; flex-wrap: wrap; gap: 0.35rem; margin: 0.5rem 0; }
.chip { border: 1px solid var(--fg-rule); background: transparent; color: inherit;
        padding: 0.2rem 0.5rem; font: inherit; font-size: 0.8125rem; cursor: pointer;
        text-decoration: none; }
.chip-on { border-color: var(--fg-ink); border-width: 2px; font-weight: 700; }

.field { display: flex; gap: 0.5rem; font-size: 0.875rem; }
.field-term { color: #555; min-width: 9rem; }
.field-value { font-family: 'FGMonoASCII', monospace; }

.button { border: 1px solid var(--fg-ink); background: transparent; color: inherit;
          padding: 0.3rem 0.75rem; font: inherit; cursor: pointer; }
.button[disabled] { opacity: 0.5; cursor: not-allowed; }
.button-danger { border-color: var(--fg-alarm); color: var(--fg-alarm); font-weight: 700; }
.confirm { border: 2px solid var(--fg-alarm); padding: 0.75rem; margin: 0.5rem 0; }
.confirm-input { font: inherit; padding: 0.25rem; }
.act-message { font-family: 'FGMonoASCII', monospace; font-size: 0.875rem; }

/* ---- the timeline (§8.1's three columns) ---- */
.timeline { display: grid; grid-template-columns: 3rem minmax(0, 1fr) 22rem; gap: 0.75rem; }
.timeline-main { min-width: 0; }
.rail { position: relative; border: 1px solid var(--fg-rule); height: 30rem; }
.rail-density { position: absolute; inset: 0; display: flex; flex-direction: column; }
.rail-band { background: var(--fg-ink); }
.rail-marks { position: absolute; inset: 0; }
.rail-mark { position: absolute; left: 0; right: 0; transform: translateY(-50%);
             border: 0; background: transparent; color: inherit; cursor: pointer;
             font-family: 'FGMonoASCII', monospace; font-size: 0.75rem; padding: 0; }
.rail-hit { position: absolute; left: 0; right: 0; height: 2px; background: #8a6100; }
.rail-viewport { position: absolute; left: 0; right: 0; border: 1px solid var(--fg-ink); }

.scroller { height: 30rem; overflow-y: auto; border: 1px solid var(--fg-rule); }
.scroller:focus { outline: 2px solid var(--fg-ink); }
.rows { display: block; }
.row { display: flex; gap: 0.5rem; align-items: baseline; padding: 0.15rem 0.35rem;
       border-bottom: 1px solid #eee; font-size: 0.8125rem; }
.row-card { display: block; border: 1px solid var(--fg-rule); border-left-width: 4px;
            padding: 0.5rem; margin: 0.25rem 0; }
.row-selected { outline: 2px solid var(--fg-ink); }
.row-time, .row-kind, .row-permalink { font-family: 'FGMonoASCII', monospace; font-size: 0.75rem; color: #555; }
.row-line { font-family: 'FGMonoASCII', monospace; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sub-row { display: flex; gap: 0.5rem; padding-left: 1.5rem; font-size: 0.75rem; }
.cluster-toggle { border: 0; background: transparent; color: inherit; font: inherit;
                  cursor: pointer; text-decoration: underline dotted; }
.spacer { display: block; }

.inspector { border: 1px solid var(--fg-rule); padding: 0.5rem; font-size: 0.875rem; }
.severity-track { position: relative; height: 0.75rem; border: 1px solid var(--fg-rule); margin: 0.25rem 0; }
.severity-fill { position: absolute; left: 0; top: 0; bottom: 0; background: #999; }
/* The block-threshold tick. A solid vertical rule, so it survives forced
 * colors and is not merely a lighter shade of the bar beside it. */
.severity-tick { position: absolute; top: -2px; bottom: -2px; width: 2px; background: var(--fg-alarm); }
.projected-line { font-family: 'FGMonoASCII', monospace; white-space: pre-wrap; word-break: break-all;
                  border-left: 3px solid var(--fg-rule); padding-left: 0.5rem; }

.banner { border: 2px solid var(--fg-alarm); background: #fff3f3; padding: 0.75rem; margin: 0.5rem 0; }
.banner-dropped { border-color: #8a6100; background: #fffaf0; }
.pending-banner { position: sticky; top: 0; z-index: 2; background: var(--fg-paper); }
.pending-row { display: flex; gap: 0.75rem; align-items: baseline; padding: 0.35rem;
               border: 1px solid var(--fg-rule); }
.pending-open { border-color: #8a6100; border-width: 2px; }
.pending-lapsed { border-style: dashed; color: #555; }
.pending-clock { font-family: 'FGMonoASCII', monospace; font-weight: 700; }

.live-bar { display: flex; flex-wrap: wrap; gap: 1rem; align-items: baseline;
            border: 1px solid var(--fg-rule); padding: 0.5rem; margin: 0.5rem 0; }
.say { display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: baseline; }
.say-input { font: inherit; min-width: 20rem; padding: 0.25rem; }
.interrupts { display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: baseline; }
.transcript { max-height: 20rem; overflow-y: auto; border: 1px solid var(--fg-rule); }
.transcript-line { display: flex; gap: 0.5rem; padding: 0.15rem 0.35rem; font-size: 0.8125rem;
                   border-bottom: 1px solid #eee; cursor: pointer; }
.transcript-selected { outline: 2px solid var(--fg-ink); }
.transcript-text { font-family: 'FGMonoASCII', monospace; }

.incident-row, .tree-node, .health-row, .audit-row, .sign-row, .run-row, .anchor-row, .drill-row,
.session-row { display: flex; gap: 0.75rem; align-items: baseline; padding: 0.25rem 0;
               border-bottom: 1px solid #eee; font-size: 0.875rem; flex-wrap: wrap; }
.sign-digest, .bundle-hash { font-family: 'FGMonoASCII', monospace; user-select: all; word-break: break-all; }
.device-card { border: 1px solid var(--fg-rule); padding: 0.75rem; margin: 0.5rem 0; }
.device-revoked { opacity: 0.6; border-style: dashed; }
.health-block { border-top: 1px solid var(--fg-rule); padding-top: 0.5rem; margin-top: 0.5rem; }
.kill-engaged .badge-glyph, .kill-engaged .badge-label { color: var(--fg-alarm); font-weight: 700; }
.status { font-size: 0.75rem; color: #555; font-family: 'FGMonoASCII', monospace; }

/* ---- P4: sign-in, the node drill-down, keys and the revocation relay ------
 *
 * Same rules as everything above: colour is never the only signal — every state
 * below already carries a glyph AND a word from `badge()` — and nothing here is
 * an inline style, because `style-src 'self'` refuses those and the build scan
 * fails on them.
 */

/* The re-authentication region. Sits ABOVE the current screen and deliberately
 * does not replace it: an operator reading an escalation at 3am must not lose
 * it to an idle timeout. */
.interrupt:not(:empty) { border: 2px solid var(--fg-alarm); padding: 0.75rem;
                         margin: 0.5rem 0; background: #fff8f8; }
.interrupt .screen-signin { padding: 0; }

.screen-signin { max-width: 44rem; }
.signin-headline { font-weight: 700; }
/* The responder's own words, visually separated so they can be quoted into a
 * bug report without working out which half was the panel talking. */
.signin-detail { font-family: 'FGMonoASCII', monospace; font-size: 0.8125rem;
                 word-break: break-word; border-left: 4px solid var(--fg-rule);
                 padding-left: 0.5rem; }
.button-primary { border-width: 2px; font-weight: 700; }
.button-hold { touch-action: none; user-select: none; -webkit-user-select: none; }

/* The node drill-down. */
.node-reason { font-weight: 700; }
.tree-path { font-family: 'FGMonoASCII', monospace; }
.tree-title { color: #444; }
.tree-reason { color: #555; font-size: 0.8125rem; flex-basis: 100%; }
.event-row { display: flex; gap: 0.75rem; align-items: baseline; padding: 0.25rem 0;
             border-bottom: 1px solid #eee; font-size: 0.875rem; flex-wrap: wrap; }
.event-kind { font-family: 'FGMonoASCII', monospace; }
.event-message { flex: 1 1 20rem; }
.event-resolved { opacity: 0.65; }
.severity-crit .badge-glyph { color: var(--fg-alarm); }
.severity-warn .badge-glyph { color: #8a6100; }
.severity-unknown .badge-glyph { color: #4a4a8a; }
.status-crit .badge-glyph { color: var(--fg-alarm); }
.status-warn .badge-glyph { color: #8a6100; }
.status-stale .badge-glyph, .status-unknown .badge-glyph { color: #4a4a8a; }
.status-ok .badge-glyph { color: #2f6b2f; }

/* Keys and the revocation relay. */
.key-card { border: 1px solid var(--fg-rule); padding: 0.75rem; margin: 0.5rem 0; }
.key-revoked, .key-expired { opacity: 0.6; border-style: dashed; }
.chain-dump { font-family: 'FGMonoASCII', monospace; font-size: 0.75rem;
              white-space: pre; overflow-x: auto; user-select: text;
              border: 1px solid var(--fg-rule); padding: 0.5rem; }
.revocation-relay { border-top: 1px solid var(--fg-rule); margin-top: 1rem; padding-top: 0.5rem; }
.revocation-input { font-family: 'FGMonoASCII', monospace; width: 100%; box-sizing: border-box; }

/* ---- metric charts -------------------------------------------------------
 *
 * One measure, one axis, no legend — the caption names the series. Colour is
 * not carrying identity here (there is only one series), so the marks are ink
 * and the status hues stay reserved for status. Geometry arrives through CSSOM
 * (`el()`'s `geometry`), never a style attribute.
 */
.chart { margin: 0 0 1.25rem; padding: 0; }
.chart-title { font-weight: 700; font-size: 0.875rem; margin-bottom: 0.25rem; }
.chart-frame { display: flex; gap: 0.5rem; align-items: stretch; }
/* Recessive axis: the numbers matter, the furniture does not. */
.chart-axis { display: flex; flex-direction: column; justify-content: space-between;
              font-family: 'FGMonoASCII', monospace; font-size: 0.6875rem;
              color: #555; text-align: right; min-width: 3.5rem; }
.chart-plot { position: relative; display: flex; align-items: flex-end; gap: 1px;
              height: 5rem; flex: 1 1 auto; border-left: 1px solid var(--fg-rule);
              border-bottom: 1px solid var(--fg-rule); padding: 0 1px; }
.chart-col { position: relative; flex: 1 1 0; min-width: 2px; height: 100%; }
/* Thin marks. The range is the bucket's min→max; the tick is its average. */
.chart-range { position: absolute; left: 0; right: 0; background: var(--fg-ink);
               border-radius: 1px; min-height: 2px; }
.chart-tick { position: absolute; left: -1px; right: -1px; height: 2px;
              background: var(--fg-bg); }
/* A hole in monitoring, drawn as a hole. Never bridged, and visibly different
 * from a column of zero height. */
.chart-gap { flex: 1 1 0; min-width: 3px; height: 100%; opacity: 0.5;
             background-image: repeating-linear-gradient(45deg,
               var(--fg-rule) 0, var(--fg-rule) 1px, transparent 1px, transparent 4px); }
.chart-xaxis { display: flex; justify-content: space-between;
               font-family: 'FGMonoASCII', monospace; font-size: 0.6875rem;
               color: #555; margin-top: 0.25rem; padding-left: 4rem; }
.chart-summary { font-family: 'FGMonoASCII', monospace; font-size: 0.75rem;
                 color: #333; margin: 0.25rem 0; }
.chart-table { margin-top: 0.25rem; font-size: 0.8125rem; }
.chart-table-body { font-family: 'FGMonoASCII', monospace; font-size: 0.6875rem;
                    white-space: pre; overflow-x: auto; max-height: 18rem;
                    overflow-y: auto; user-select: text;
                    border: 1px solid var(--fg-rule); padding: 0.5rem; }

/* Windows forced-colors mode strips every hue. Everything above still reads,
 * because the glyph and the word carry the meaning; these rules only make sure
 * the borders that separate regions survive as system colours rather than
 * disappearing into the background. */
@media (forced-colors: active) {
  .chip-on, .row-selected, .transcript-selected { border: 2px solid CanvasText; }
  .banner, .confirm, .pending-open { border: 2px solid CanvasText; }
  .interrupt:not(:empty) { border: 2px solid CanvasText; background: Canvas; }
  .key-card, .device-card, .chain-dump { border: 1px solid CanvasText; }
  /* The chart survives with no hue at all: the marks become system ink, the
   * gap keeps its hatch, and every number is already printed as text beside
   * the plot and in the table view under it. */
  .chart-range { background: CanvasText; }
  .chart-tick { background: Canvas; }
  .chart-gap { background-image: repeating-linear-gradient(45deg,
                 CanvasText 0, CanvasText 1px, transparent 1px, transparent 4px); }
  .chart-plot { border-left: 1px solid CanvasText; border-bottom: 1px solid CanvasText; }
  .severity-fill { background: CanvasText; }
  .severity-tick { background: CanvasText; }
  .rail-band { background: CanvasText; }
}
