/* The cogitator surface — a screen you read the app off.
   ================================================================

   WHAT THIS IS

   A skin. It does not know what a campaign or a battle is. It knows
   how to draw a lit panel with bracketed corners, a hairline under a
   heading, a gradation rail and a phosphor readout — and it draws all
   of that out of `--cog-*` tokens, which `bb-tokens.css` declares once
   per universe.

   ONE WAY IN

     <html data-surface="cogitator">  -> the whole app

   That attribute is the player's setting and the only hook in this
   file. There is no class a screen can wear to opt itself in, and
   there is deliberately nowhere to put one.

   The campaign screens used to carry a `.cog` class unconditionally,
   which made this a skin two screens always had and everything else
   could be given. That is not a setting — a player who chose Standard
   still got an instrument panel on the campaign screens, and a player
   who chose the Cogitator got one app drawn two ways depending on
   which rules happened to be scoped. Every rule below now keys on the
   attribute alone, so the setting is the whole answer: Standard is the
   app as it always was, everywhere, and the Cogitator is the
   instrument, everywhere.

   WHY IT IS FRAMEWORK RATHER THAN A HORUS HERESY STYLESHEET

   The reference the look came from is a 40k one: a strategium screen,
   green phosphor on black, scanlines and gradations. That is
   vocabulary. The MECHANISM under it — a panel with drawn corners, a
   ruled heading, a monospaced data column, an overlay that sits above
   the content and takes no taps — is not about which game you are
   playing, and no sci-fi game should own a second copy of it.

   So the chrome is here and the palette is not:

     html[data-universe="hh"] -> phosphor green on a lit black screen

   Warhammer 40,000 adds its own block in `bb-tokens.css` when it
   lands and inherits every mark below without touching this file.

   WHICH GAMES ARE OFFERED IT

   The sci-fi ones, and only those. `app/framework/surfaces.py`
   registers this surface to the `scifi` genre and a universe declares
   which genre it is, so The Old World is never offered it and never
   sets the attribute. The stylesheet does not enforce that and should
   not try — a stylesheet that names the universes it refuses is the
   same mistake as one that names the screens it decorates.

   HOW IT RE-SKINS SCREENS IT HAS NEVER HEARD OF

   The scope re-points a handful of `--bb-*` tokens at its own values.
   Every rule already written against `--bb-bg-surface` or
   `--bb-accent-primary` inside it follows without being touched, which
   is what makes "the whole app" a setting rather than a rewrite of
   thirty stylesheets.

   That also draws the line on what belongs here. A screen that reads
   the tokens needs nothing. A screen that hardcodes a colour needs
   fixing where it hardcodes it, NOT a rule in this file naming its
   class — this stylesheet is a palette and a small vocabulary of
   marks, and the day it starts carrying per-screen exceptions it has
   become a second copy of every screen.

   PROSE STAYS PROPORTIONAL. Only data goes monospace: scores, codes,
   records, labels. Setting a whole app in Share Tech Mono is the
   fastest way to make it unreadable, and readability is the exact
   thing this setting exists to let a player judge.

   NO ART. Every mark below is drawn by the browser — gradients for
   the ground and the vignette, repeating gradients for the graticule,
   the scanlines and the tick rails, plain borders for the bracket
   corners. There is no image file in this stylesheet, no `url()` of
   any kind, and there is not meant to be one.

   ACCESSIBILITY. The overlay is `pointer-events: none` and carries no
   text. The flicker is off under `prefers-reduced-motion`. Nothing in
   here relies on colour alone: brackets, rules and rails are shape.
   ================================================================ */

/* ----------------------------------------------------------------
   The palette, re-pointed.
   ---------------------------------------------------------------- */

html[data-surface="cogitator"] {
    color: var(--cog-ink);

    --bb-bg-base: var(--cog-void);
    --bb-bg-surface: var(--cog-ground);
    --bb-bg-elevated: var(--cog-ground-lit);
    --bb-bg-input: var(--cog-well);
    --bb-text-primary: var(--cog-ink);
    --bb-text-secondary: var(--cog-ink-dim);
    --bb-text-muted: var(--cog-ink-faint);
    --bb-accent-primary: var(--cog-phosphor);
    --bb-border: var(--cog-line);
    --bb-border-focus: var(--cog-phosphor);

    /* Alerts keep their own colour, because a refusal that reads as
       phosphor is a refusal nobody sees. But they keep the PLATE's
       colour, not the app's: #e53e3e is a web red and sits at 4.85:1 on
       the void, where --cog-alert is 6.52:1 and belongs to the palette.

       Repointed here rather than written as rules naming the four
       classes that show errors. Two of them WERE written that way, and
       the other two were red - `.ce-load-error` and
       `.ce-inline-message.ce-message-error` read the token and nobody
       had thought of them. Every alias resolves through this too:
       `--danger`, `--error` and `--color-error` at the foot of
       bb-tokens.css are all `var(--bb-accent-danger)`, and a custom
       property substitutes in the context of the element that uses it,
       so all three follow the override into this scope. */
    --bb-accent-danger: var(--cog-alert);
}

/* SELECTED STATES ARE FILLED, AND THAT IS DELIBERATE.
   Jesse's call, 2026-09-13.

   About twenty-five rules across the app say "this one is selected" with
   `background: var(--bb-accent-primary)` and near-black text. Under this
   surface that becomes a block of #3dfba2 - a lit slab, 127 times the
   luminance of the plate behind it, and by a distance the brightest
   thing on any screen it appears on.

   An audit will flag it, and the alternative was built and looked at: a
   --cog-key-lit wash with a phosphor border and phosphor text, the same
   treatment `.btn-primary` gets below. Both are legible - 14.8:1 filled,
   7.42:1 outlined, against 5.75:1 for ordinary body text here - so this
   was never a contrast question, and the slab was chosen on how it
   reads. A screen meant to look lit should have something on it that is
   actually lit.

   So do not "fix" this. If it ever does need to change, the fix is a
   `--bb-accent-fill` token defaulted to `--bb-accent-primary` and
   re-pointed here - NOT twenty-five class names in this file, which is
   the mistake the alert colour above was rescued from. */

/* ----------------------------------------------------------------
   The ground: a lit void behind a graticule.

   Painted on whichever element is actually the backdrop. Site-wide
   that is `body`, because `bb-layout.css` gives body an opaque
   `--bb-bg-base` and a gradient on `html` would sit behind it,
   invisible.
   ---------------------------------------------------------------- */

html[data-surface="cogitator"] body {
    /* The void itself stays on `body`, so there is never a moment or a
       corner where the page is the browser's white. */
    background: var(--cog-void);
}

/* THE GROUND IS FIXED TO THE VIEWPORT, NOT TO THE DOCUMENT.
   ----------------------------------------------------------------
   It used to be four layers on `body`, which means the background
   positioning area is the whole scrolling document. On a long page the
   bloom was stretched out of existence and the graticule ran on for
   thousands of pixels, and the result reads as tiling rather than as a
   screen. Jesse, 2026-09-16: "the background for cogitator has a
   gradient, light green to black, but it repeats through a long page
   which just makes it look like a cheap tile job."

   A tube does not scroll. The bloom belongs to the GLASS, so it stays
   where the glass is and the text moves under it.

   A fixed pseudo-element rather than `background-attachment: fixed`,
   which is unreliable on mobile Safari - and this is the pattern the
   file already uses for the scanlines directly below, for the same
   reason and with the same caveat about transformed ancestors. */
html[data-surface="cogitator"] body::before {
    content: '';
    pointer-events: none;
    position: fixed;
    inset: 0;
    /* Behind everything the app draws, in front of the void. */
    z-index: -1;
    background:
        /* The lit centre of the tube, brightest where a face would be. */
        radial-gradient(
            120% 80% at 50% 0%,
            var(--cog-bloom) 0%,
            transparent 60%
        ),
        /* The graticule. Two hairline grids, faint enough to read as
           texture rather than as a table. */
        repeating-linear-gradient(
            0deg,
            var(--cog-grid) 0 1px,
            transparent 1px var(--cog-grid-step)
        ),
        repeating-linear-gradient(
            90deg,
            var(--cog-grid) 0 1px,
            transparent 1px var(--cog-grid-step)
        );
}

/* ----------------------------------------------------------------
   The overlay: scanlines, then a vignette, above everything and deaf
   to taps.

   It hangs off `body` and is FIXED, so the scanlines stay put over a
   scrolling page — which is what a screen actually does. It sits over
   the header, the nav and any modal, all of which are part of the
   instrument.

   `body` and not the screen mount, because the shell transforms
   screens during transitions and a fixed pseudo-element inside a
   transformed ancestor is positioned against that ancestor rather than
   the viewport. On a mount it would work until the day someone
   animated a screen in, and then quietly stop. The shell never
   transforms `body`.
   ---------------------------------------------------------------- */

html[data-surface="cogitator"] body::after {
    content: '';
    pointer-events: none;
    background:
        repeating-linear-gradient(
            0deg,
            rgba(0, 0, 0, var(--cog-scan-alpha)) 0 1px,
            transparent 1px var(--cog-scan-step)
        ),
        radial-gradient(
            140% 100% at 50% 50%,
            transparent 45%,
            rgba(0, 0, 0, var(--cog-vignette)) 100%
        );
}

html[data-surface="cogitator"] body::after {
    position: fixed;
    inset: 0;
    /* Above the shell chrome and above a modal. It takes no taps, so
       the only thing it changes about what is underneath is the tint. */
    z-index: 9000;
}

/* The tube's own unsteadiness. A few hundredths of an opacity step,
   slowly — enough that the screen is never quite still, not enough to
   notice unless you look for it. */
@media (prefers-reduced-motion: no-preference) {
    html[data-surface="cogitator"] body::after {
        animation: cog-breathe 7s ease-in-out infinite;
    }
}

@keyframes cog-breathe {
    0%, 100% { opacity: 1; }
    50%      { opacity: 0.94; }
}

/* ----------------------------------------------------------------
   Panels.

   The corners are two L-shaped brackets rather than four, drawn with
   borders on the panel's own pseudo-elements. Two is what the
   reference plates actually do, it reads as deliberate rather than as
   a box someone forgot to close, and it needs no extra markup — which
   matters, because these rules are applied to panels written months
   before this stylesheet existed.

   WHICH CLASSES GET THEM, AND WHY THOSE. The framework's own block
   vocabulary - `.section` and `.bb-card` from `bb-components.css`,
   `.settings-section`, and the campaign engine's `.ce-panel`. That is
   four names for one idea because the app grew that way, not because
   they mean four things, and consolidating them is a different job
   from painting them.

   NOT the cards INSIDE those blocks. A What's New list is six cards
   inside one section; bracketing each of them is twelve corner marks
   on one screen, which stops reading as an instrument and starts
   reading as a fence. Inner cards already pick up the accent on their
   left edge from the token re-point, which is the quieter half of the
   same idea.
   ---------------------------------------------------------------- */

html[data-surface="cogitator"] .ce-panel,
html[data-surface="cogitator"] .cog-panel,
html[data-surface="cogitator"] .bb-card,
html[data-surface="cogitator"] .section,
html[data-surface="cogitator"] .settings-section {
    position: relative;
    background: var(--cog-ground);
    border: 1px solid var(--cog-line);
    border-radius: 0;
    box-shadow: inset 0 0 24px var(--cog-inner-glow);
}

html[data-surface="cogitator"] .ce-panel::before,
html[data-surface="cogitator"] .ce-panel::after,
html[data-surface="cogitator"] .cog-panel::before,
html[data-surface="cogitator"] .cog-panel::after,
html[data-surface="cogitator"] .bb-card::before,
html[data-surface="cogitator"] .bb-card::after,
html[data-surface="cogitator"] .section::before,
html[data-surface="cogitator"] .section::after,
html[data-surface="cogitator"] .settings-section::before,
html[data-surface="cogitator"] .settings-section::after {
    content: '';
    position: absolute;
    width: 16px;
    height: 16px;
    /* 2px, and offset far enough out to sit PROUD of the panel's own
       border rather than on top of it. At 1px and flush the bracket
       and the border are the same line in nearly the same colour, and
       the corner just looks very slightly brighter - which is not a
       bracket, it is a smudge. */
    border: 2px solid var(--cog-phosphor);
    pointer-events: none;
}

html[data-surface="cogitator"] .ce-panel::before,
html[data-surface="cogitator"] .cog-panel::before,
html[data-surface="cogitator"] .bb-card::before,
html[data-surface="cogitator"] .section::before,
html[data-surface="cogitator"] .settings-section::before {
    top: -3px;
    left: -3px;
    border-right: 0;
    border-bottom: 0;
}

html[data-surface="cogitator"] .ce-panel::after,
html[data-surface="cogitator"] .cog-panel::after,
html[data-surface="cogitator"] .bb-card::after,
html[data-surface="cogitator"] .section::after,
html[data-surface="cogitator"] .settings-section::after {
    right: -3px;
    bottom: -3px;
    border-left: 0;
    border-top: 0;
}

/* ----------------------------------------------------------------
   Type.

   Headings are ruled and tracked out. Data is monospaced, because the
   thing a campaign screen is mostly showing is columns of numbers that
   want to line up.
   ---------------------------------------------------------------- */

html[data-surface="cogitator"] .ce-section-title,
html[data-surface="cogitator"] .cog-title,
html[data-surface="cogitator"] .section-title,
html[data-surface="cogitator"] .settings-section-title {
    position: relative;
    padding: 0 0 var(--bb-space-1) var(--bb-space-2);
    border-left: 2px solid var(--cog-phosphor);
    border-bottom: 1px solid var(--cog-line);
    color: var(--cog-phosphor);
    font-family: var(--cog-font-display);
    letter-spacing: 0.14em;
    text-transform: uppercase;
    text-shadow: 0 0 8px var(--cog-glow);
}

html[data-surface="cogitator"] .ce-title,
html[data-surface="cogitator"] .ce-detail-name {
    color: var(--cog-phosphor);
    font-family: var(--cog-font-display);
    letter-spacing: 0.08em;
    text-shadow: 0 0 10px var(--cog-glow);
}

/* Numbers, codes, records, points — anything read as data rather than
   as a sentence. */
html[data-surface="cogitator"] .ce-detail-code,
html[data-surface="cogitator"] .ce-points,
html[data-surface="cogitator"] .ce-rank,
html[data-surface="cogitator"] .ce-schedule-points,
html[data-surface="cogitator"] .ce-pairing-result,
html[data-surface="cogitator"] .ce-nextcard-id,
html[data-surface="cogitator"] .ce-fact-value,
html[data-surface="cogitator"] .cog-readout {
    font-family: var(--cog-font-mono);
    font-variant-numeric: tabular-nums;
    /* Tight, because a monospace face is already wider per character
       than the proportional one it replaces here and a standings row
       carries a name, a tag, a record and a score. Measured at 320,
       360, 390 and 430: no row wraps that did not already wrap without
       the skin. (One did - a withdrawn player at any width - and it
       wrapped before this stylesheet existed. It was a layout bug in
       `.ce-standing` rather than a colour, and the second line added
       on 2026-09-14 is what fixed it.) */
    letter-spacing: 0.02em;
    color: var(--cog-phosphor);
    text-shadow: 0 0 6px var(--cog-glow);
}

/* The one that shares a row with a name. */
html[data-surface="cogitator"] .ce-points {
    font-size: var(--bb-text-sm);
}

/* THE CAPTION UNDER A STANDINGS ROW, 2026-09-14.
 *
 * The record used to sit on the first line beside the name and the
 * points, so it was skinned as a first-line figure: full phosphor,
 * glow, `--bb-text-sm`. It moved to a second line when the victory
 * points joined it - `.ce-standing-detail` - and at that size and
 * brightness the caption outshone the row it explains.
 *
 * Both are data and both keep the monospace face and tabular figures,
 * which is what makes a column of scores line up. They take the dim
 * tone instead, matching the muted role they have on the standard
 * surface, so the two surfaces agree about what this line is FOR even
 * though they disagree about how it looks.
 *
 * (This also retires the wrapping note above: a withdrawn player's row
 * wrapped at every width because a name, a tag, a record and a score
 * shared one line. They no longer do.)
 */
html[data-surface="cogitator"] .ce-record,
html[data-surface="cogitator"] .ce-vp {
    font-family: var(--cog-font-mono);
    font-variant-numeric: tabular-nums;
    letter-spacing: 0.02em;
    color: var(--cog-ink-dim);
}

html[data-surface="cogitator"] .ce-fact-label,
html[data-surface="cogitator"] .form-label,
html[data-surface="cogitator"] .cog-label {
    color: var(--cog-ink-dim);
    font-family: var(--cog-font-mono);
    letter-spacing: 0.12em;
    text-transform: uppercase;
}

/* The decorative marker either side of a heading. It is real text in
   the DOM rather than generated content, so it can carry
   `aria-hidden` — generated content cannot, and a screen reader
   announcing "plus plus plus" before every heading is a worse screen
   than one with no flourish at all. */
html[data-surface="cogitator"] .cog-mark {
    color: var(--cog-phosphor);
    font-family: var(--cog-font-mono);
    opacity: 0.55;
    letter-spacing: 0.2em;
}

/* ----------------------------------------------------------------
   The gradation rail.

   A run of tick marks with a brighter one every fifth, drawn as a
   repeating gradient. Purely decorative: it is the edge of an
   instrument, and it says "this is a readout" faster than any amount
   of colour does.
   ---------------------------------------------------------------- */

html[data-surface="cogitator"] .cog-rail {
    height: 10px;
    flex: 0 0 auto;
    background:
        repeating-linear-gradient(
            90deg,
            var(--cog-phosphor) 0 1px,
            transparent 1px 8px
        ),
        repeating-linear-gradient(
            90deg,
            var(--cog-line) 0 1px,
            transparent 1px 40px
        );
    background-size: 100% 4px, 100% 10px;
    background-position: 0 0, 0 0;
    background-repeat: no-repeat;
    opacity: 0.6;
}

/* A mount that hosts rails. Any screen may wear `cog-surface`; under
   Standard it does nothing at all, which is the whole reason it is a
   separate class from the rails themselves. It replaces the `.cog`
   class the campaign screens used to carry, and the difference is that
   this one only means "rails belong to me", never "draw me as an
   instrument". Nothing about the look is behind it.

   `min-height: inherit` and not `100%`: the mount sits in a block with
   a computed `min-height` and no definite `height`, and a percentage
   min-height against an auto height resolves to auto and does nothing.
   Measured both ways against a real page - 100% left the surface at
   498px of a 728px mount, inherit filled it. A mount with no
   min-height inherits `auto` and this is a no-op. */
html[data-surface="cogitator"] .cog-surface {
    display: flex;
    flex-direction: column;
    min-height: inherit;
}

/* The closing rail belongs at the bottom of the instrument, not
   wherever the content happened to stop. The mount is a flex column,
   so `auto` on the top margin eats the slack. */
html[data-surface="cogitator"] .cog-surface > .cog-rail:last-child {
    margin-top: auto;
}

/* ----------------------------------------------------------------
   Controls.

   Inputs are wells cut into the panel; buttons are bracketed rather
   than filled, which is what the plates do and also what keeps a
   screen this dark from turning into a row of glowing slabs.
   ---------------------------------------------------------------- */

html[data-surface="cogitator"] .form-input,
html[data-surface="cogitator"] .cog-input {
    background: var(--cog-well);
    border: 1px solid var(--cog-line);
    border-radius: 0;
    color: var(--cog-ink);
    font-family: var(--cog-font-mono);
}

html[data-surface="cogitator"] .form-input:focus,
html[data-surface="cogitator"] .cog-input:focus {
    outline: none;
    border-color: var(--cog-phosphor);
    box-shadow: 0 0 0 1px var(--cog-phosphor), 0 0 12px var(--cog-glow);
}

html[data-surface="cogitator"] .btn {
    border-radius: 0;
    font-family: var(--cog-font-mono);
    letter-spacing: 0.1em;
}

html[data-surface="cogitator"] .btn-primary {
    background: var(--cog-key);
    border: 1px solid var(--cog-phosphor);
    color: var(--cog-phosphor);
    text-shadow: 0 0 8px var(--cog-glow);
}

html[data-surface="cogitator"] .btn-primary:hover:not([disabled]) {
    background: var(--cog-key-lit);
    box-shadow: 0 0 14px var(--cog-glow);
}

html[data-surface="cogitator"] .btn-secondary,
html[data-surface="cogitator"] .btn-ghost {
    background: transparent;
    border: 1px solid var(--cog-line);
    color: var(--cog-ink-dim);
}

html[data-surface="cogitator"] .btn-secondary:hover:not([disabled]),
html[data-surface="cogitator"] .btn-ghost:hover:not([disabled]) {
    border-color: var(--cog-phosphor);
    color: var(--cog-phosphor);
}

/* ----------------------------------------------------------------
   Rows.

   A standings table on a readout has ruled rows and no fill. The
   current one is marked on the left edge, so it survives being read
   by someone who cannot separate the two greens.
   ---------------------------------------------------------------- */

html[data-surface="cogitator"] .ce-standing,
html[data-surface="cogitator"] .ce-pairing,
html[data-surface="cogitator"] .ce-schedule-row,
html[data-surface="cogitator"] .ce-challenge,
html[data-surface="cogitator"] .ce-playerrow,
html[data-surface="cogitator"] .ce-campaign {
    background: transparent;
    border-radius: 0;
    border-bottom: 1px solid var(--cog-line);
}

html[data-surface="cogitator"] .ce-campaign {
    border: 1px solid var(--cog-line);
}

html[data-surface="cogitator"] .ce-campaign.active,
html[data-surface="cogitator"] .ce-schedule-current {
    border-left: 3px solid var(--cog-phosphor);
    background: var(--cog-row-lit);
}

html[data-surface="cogitator"] .ce-next {
    border-left: 3px solid var(--cog-phosphor);
}

html[data-surface="cogitator"] .ce-message {
    background: var(--cog-ground);
    border: 1px solid var(--cog-line);
    border-radius: 0;
    font-family: var(--cog-font-mono);
}

/* ----------------------------------------------------------------
   The map is NOT styled from here.

   A canvas renders no pseudo-elements and inherits no colours, so
   every mark on the campaign map — its frame, its gradations, its
   scanlines — is drawn in `static/hh/js/campaign-map.js` with the same
   palette written out as constants. `tests/js/cogitator-palette.test.mjs`
   is what keeps the two copies honest: it reads the values out of
   `bb-tokens.css` and out of the renderer and fails if they drift.

   Left as a note rather than as an empty rule, because the obvious
   next move is to add `.cog-map { ... }` here and wonder for an hour
   why nothing changes.
   ---------------------------------------------------------------- */

/* THE NOTICE BOARD TAKES THE SECOND ACCENT, 2026-09-14.
 *
 * `--bb-accent-notice` is sea green, which is a colour this surface
 * does not have: everything here is one phosphor, and a green panel on
 * a green screen is the flattening `.ce-notices` was already fixed for
 * once. So on the Cogitator the board speaks in `--cog-signal` - amber,
 * period-correct on a green CRT, and NOT `--cog-alert`, because an
 * organiser saying the shop is shut on Thursday is not an alarm.
 *
 * Re-pointing the token rather than restyling the panel, so the two
 * `.ce-notices` rules in `campaign-engine.css` keep working and there is
 * one place this decision lives.
 */
html[data-surface="cogitator"] .ce-panel.ce-notices,
html[data-surface="cogitator"] .ce-notices {
    --bb-accent-notice: var(--cog-signal);
}

html[data-surface="cogitator"] .ce-notices .ce-section-title {
    color: var(--cog-signal);
    text-shadow: 0 0 6px var(--cog-signal-glow);
}

/* THE ROUND TABS AND THE PAGER, 2026-09-14.
 * The selected tab is a LIT BLOCK rather than an outline, which is the
 * ruling this surface already follows everywhere else - see the note on
 * `--cog-key-lit`. An audit that flags filled selected states here is
 * reading the wrong rule.
 */
html[data-surface="cogitator"] .ce-tab {
    font-family: var(--cog-font-mono);
    letter-spacing: 0.04em;
}
html[data-surface="cogitator"] .ce-tab.is-on {
    background: var(--cog-key-lit);
    border-color: var(--cog-phosphor);
    color: var(--cog-phosphor);
    text-shadow: 0 0 6px var(--cog-glow);
}
html[data-surface="cogitator"] .ce-pager-at {
    font-family: var(--cog-font-mono);
    font-variant-numeric: tabular-nums;
    color: var(--cog-ink-dim);
}

/* The bug report line stays quiet on the Cogitator too - dim ink, no
   glow. It is the one control on the screen that should not compete
   with the campaign. */
html[data-surface="cogitator"] .ce-report-bug {
    border-top-color: var(--cog-line);
}
html[data-surface="cogitator"] .ce-report-bug .ce-hint {
    font-family: var(--cog-font-mono);
    color: var(--cog-ink-dim);
}

/* ----------------------------------------------------------------
   THE CHARTS SIT ON THEIR OWN GROUND.

   Jesse, 2026-09-16: "we need a dark grey fill on the charts under
   tools. The grid from cogitator messes with the tables."

   Measured: the chart itself was transparent and its cells were
   `--cog-ground` at 0.72 alpha, so the graticule ran straight through
   every row. Two grids crossing at different pitches is exactly the
   moire the eye cannot read a number out of - and a cross-indexed
   to-hit chart is nothing BUT a grid of numbers.

   `--cog-well` is the token for a recessed panel and it is nearly
   opaque, so the chart reads as something set into the console rather
   than printed on the glass. Put on the wrapper as well as the cells,
   so the gaps a `border-collapse` table leaves at its edges are
   covered too.
   ---------------------------------------------------------------- */
html[data-surface="cogitator"] .bb-ref-matrix-wrap,
html[data-surface="cogitator"] .bb-ref-table-wrap {
    background: var(--cog-chart);
    border: 1px solid var(--cog-line);
    border-radius: var(--bb-radius-md, 6px);
}

html[data-surface="cogitator"] .bb-ref-matrix,
html[data-surface="cogitator"] .bb-ref-table {
    background: var(--cog-chart);
}

html[data-surface="cogitator"] .bb-ref-matrix th,
html[data-surface="cogitator"] .bb-ref-matrix td,
html[data-surface="cogitator"] .bb-ref-table th,
html[data-surface="cogitator"] .bb-ref-table td {
    /* OPAQUE, not a wash. The alpha was the whole defect: `--cog-well`
       is 0.92, and eight percent of a graticule is still a graticule
       when it crosses a grid of numbers at a different pitch. */
    background: var(--cog-chart);
    border-color: var(--cog-line);
}

/* A header row that is still distinguishable now that the wash is
   gone - lit rather than tinted, which is this surface's own idiom.
   OPAQUE like the rest of the chart: `--cog-key-lit` is a translucent
   wash, and using it here would let the graticule back through the one
   row that labels every column. `--cog-chart-head` is that same wash
   already composited onto the chart's ground. */
html[data-surface="cogitator"] .bb-ref-matrix thead th,
html[data-surface="cogitator"] .bb-ref-table thead th {
    background: var(--cog-chart-head);
    color: var(--cog-phosphor);
}
