/* F&H Command - the round-3 polish layer
 * ============================================================================
 * Lane OC-3, September 4, 2026. The dark-glass cockpit of the approved mock's
 * section 4 (_documents/ui-review-2026-09-04-deslop/polish-preview-approved.html).
 *
 * WHY THIS IS ITS OWN FILE AND NOT 3,285 EDITS IN dashboard.css. Two lanes read
 * dashboard.css and every mutation anchor in tests/ is a literal slice of the
 * files it names. A separate sheet loaded last moves no existing line, so no
 * anchor in either mutation harness goes stale, and the whole restyle can be
 * read, reviewed or reverted as one thing. It is a LAYER, not a fork: it never
 * redeclares a color of its own, only the tokens in css/tokens.css.
 *
 * THE FOUR CONSTRAINTS THIS FILE WORKS UNDER, in Bryant's words, September 4:
 * do not lose the elegance of the fonts, do not deviate from F&H's color
 * scheme, do not remove watermarks or logos, and fix dark text on dark tiles.
 * So: no font-family is changed anywhere below except where a kicker becomes
 * mono, which is a family the tokens already name; --primary-purple keeps its
 * value; nothing is deleted; and the contrast pass is the point of section 9.
 *
 * ORDER: this sheet is loaded after dashboard.css, so it wins on equal
 * specificity. It uses !important in exactly one place, section 9, and says
 * there why.
 * ==========================================================================*/


/* ==========================================================================
 * 1. THE GROUND
 * A violet wash from the top right, a dark counter-shade in the opposite
 * corner so the dark has depth rather than one spotlight, and the base
 * gradient underneath both. Fixed, so scrolling does not drag the light.
 * ========================================================================*/
body {
  background-color: var(--bg-base);
  background-image: var(--wash-violet), var(--wash-counter), var(--ground);
  background-attachment: fixed;
}


/* ==========================================================================
 * 2. KICKERS
 * Mono, tracked, uppercase, in the violet that is legible as text. The mono
 * family is the one css/tokens.css already declares; no stack changes.
 * ========================================================================*/
.section-eyebrow,
.mrr-eyebrow,
.label-caps,
.trend-header .section-eyebrow,
.briefings-section-label,
.module-cat {
  font-family: var(--font-mono);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--violet-text);
}

.label-caps-muted,
.kpi-label,
.field-label,
.composition-tile-label,
.engagement-card-values .label,
.auth-subtitle,
.brand-tagline {
  font-family: var(--font-mono);
  letter-spacing: 0.15em;
}

.section-subtitle,
.today-opener-tag,
.score-note {
  color: var(--text-tertiary);
}


/* ==========================================================================
 * 3. THE TOP BAR
 * Glass, lit along its top edge, sitting over the wash rather than on a flat
 * fill. The brand emblem is a rounded square, which is the standing house
 * rule for a logo chip: never a circle.
 * ========================================================================*/
.app-header {
  background: var(--glass-fill);
  background-color: rgba(21, 17, 53, 0.72);
  backdrop-filter: var(--glass-blur);
  -webkit-backdrop-filter: var(--glass-blur);
  border-bottom: 1px solid rgba(255, 255, 255, 0.07);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.13), 0 18px 34px -30px rgba(15, 11, 46, 0.9);
}

.brand-logo,
.auth-logo {
  border-radius: 12px;
  box-shadow: 0 4px 12px -5px rgba(107, 79, 187, 0.7), inset 0 1px 0 rgba(255, 255, 255, 0.2);
}

.page-title-main {
  text-shadow: 0 0 28px rgba(184, 164, 232, 0.30);
}


/* ==========================================================================
 * 4. THE LIVE PULSE AND ITS UPDATE STAMP
 * The pulse stays. It gains a mono stamp beside it that says how long ago the
 * app last got an answer from the network. app.js colors the dot by how much
 * session is left and that still works: only the ring is added here, and it
 * is drawn with box-shadow so it inherits nothing from the dot's background.
 * ========================================================================*/
.session-indicator {
  gap: 10px;
  padding: 5px 11px;
  border-radius: 999px;
  background: var(--glass-fill-quiet);
  box-shadow: var(--glass-edge);
}

.session-dot {
  position: relative;
  animation: ocPulse 2.4s ease-out infinite;
}

@keyframes ocPulse {
  0%   { box-shadow: 0 0 0 0 rgba(74, 222, 128, 0.45); }
  70%  { box-shadow: 0 0 0 8px rgba(74, 222, 128, 0); }
  100% { box-shadow: 0 0 0 0 rgba(74, 222, 128, 0); }
}

.live-stamp {
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-secondary);
  white-space: nowrap;
}

.live-stamp.is-stale { color: var(--warn-hot); }

.session-sep { color: var(--text-tertiary); }

#session-time {
  font-family: var(--font-mono);
  font-size: 10.5px;
  letter-spacing: 0.08em;
}


/* ==========================================================================
 * 5. PANELS: THE GLASS RECIPE
 * Blur, a white gradient fill, an inset top highlight, a one-pixel inner
 * hairline, and a violet-tinted shadow sitting under the element. Every
 * surface that reads as a panel gets the same four parts.
 * ========================================================================*/
.card,
.placeholder,
.mrr-meter,
.composition-tile,
.trend-chart,
.engagement-table,
.engagement-card,
.today-row,
.module-card,
.briefing-card,
.briefing-generating,
.toast,
.score-plan,
.heat-card {
  background: var(--glass-fill);
  background-color: rgba(26, 21, 71, 0.55);
  backdrop-filter: var(--glass-blur);
  -webkit-backdrop-filter: var(--glass-blur);
  border: none;
  box-shadow: var(--glass-edge), var(--shadow-under);
}

.placeholder {
  background-image: var(--glass-fill-quiet);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.10),
              inset 0 0 0 1px rgba(255, 255, 255, 0.06),
              var(--shadow-under-sm);
}

.card-callout {
  box-shadow: var(--glass-edge), var(--shadow-under),
              inset 4px 0 0 var(--primary-purple);
  border-left: none;
}

/* Hover is a two pixel lift with a violet border and a tinted shadow, 150ms. */
.card-interactive:hover,
.module-card:hover,
.engagement-card:hover {
  transform: translateY(-2px);
  box-shadow: var(--glass-edge-strong), var(--shadow-under-lift),
              inset 0 0 0 1px rgba(184, 164, 232, 0.35);
  transition: transform var(--lift), box-shadow var(--lift);
}

.card-interactive,
.module-card,
.engagement-card {
  transition: transform var(--lift), box-shadow var(--lift);
}


/* ==========================================================================
 * 6. STAT CELLS
 * The MRR meter's composition tiles and the KPI tiles are the cockpit's stat
 * cells. Glass, with the number set in the mono face so a column of figures
 * lines up, and the amber variant on the one that needs action.
 * ========================================================================*/
.composition-tile,
.kpi-tile {
  padding: 13px 16px;
  border-radius: var(--radius-lg);
  border-left: none;
}

.kpi-tile {
  box-shadow: var(--glass-edge), var(--shadow-under), inset 3px 0 0 rgba(184, 164, 232, 0.55);
}

.composition-tile-value,
.kpi-value,
.mrr-value {
  font-feature-settings: "tnum" 1;
  letter-spacing: 0.005em;
}

.mrr-progress {
  box-shadow: inset 0 1px 2px rgba(15, 11, 46, 0.8), inset 0 0 0 1px rgba(255, 255, 255, 0.07);
}

.mrr-progress-bar {
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.3), 0 0 18px -4px rgba(107, 79, 187, 0.9);
}


/* ==========================================================================
 * 7. TABLE ROWS AS EDGE-LIT PANELS
 * The scoreboard and the pipeline are the two tables on the page. A row is
 * separated by a lit hairline rather than a drawn border, so the surface
 * reads as one piece of glass with lines scored across it.
 * ========================================================================*/
.engagement-table thead,
.score-table thead th {
  background: rgba(255, 255, 255, 0.028);
  box-shadow: inset 0 -1px 0 rgba(255, 255, 255, 0.10);
}

.score-table thead th {
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--text-secondary);
}

.engagement-table th {
  font-family: var(--font-mono);
  border-bottom: none;
}

.engagement-table tbody tr,
.score-table tbody tr td,
.score-table tfoot th {
  border-bottom: none;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.055);
}

.engagement-table tbody tr:hover {
  background: rgba(255, 255, 255, 0.055);
}

.score-table tr.this-week td {
  background: rgba(184, 164, 232, 0.09);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1);
}

.score-table td.num,
.score-table th.num {
  font-family: var(--font-mono);
  font-feature-settings: "tnum" 1;
}

.score-now {
  font-family: var(--font-mono);
  color: var(--violet-text);
}

.score-table {
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: var(--glass-fill-quiet);
  box-shadow: var(--glass-edge);
}


/* ==========================================================================
 * 8. PILLS, CHIPS AND THE AMBER
 * A pill glows softly in its own color: a tinted fill, a ring of the same
 * hue, and a lit top edge. The number that needs action is the overdue count
 * on the Today list, and it is warm amber rather than red, because overdue is
 * work waiting, not an error. Red stays for errors.
 * ========================================================================*/
.pill,
.stage-pill,
.module-status,
.today-count,
.filter-chip-count,
.paused-tag,
.briefing-card-cat {
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.16), inset 0 0 0 1px rgba(255, 255, 255, 0.08);
  font-family: var(--font-mono);
  letter-spacing: 0.09em;
}

.stage-pill { border-color: transparent; }
.stage-pill.stage-lead        { box-shadow: inset 0 1px 0 rgba(255,255,255,.14), inset 0 0 0 1px rgba(184, 164, 232, 0.38); }
.stage-pill.stage-qualified   { box-shadow: inset 0 1px 0 rgba(255,255,255,.14), inset 0 0 0 1px rgba(147, 197, 253, 0.38); }
.stage-pill.stage-proposal    { box-shadow: inset 0 1px 0 rgba(255,255,255,.14), inset 0 0 0 1px rgba(251, 191, 36, 0.38); }
.stage-pill.stage-negotiating { box-shadow: inset 0 1px 0 rgba(255,255,255,.14), inset 0 0 0 1px rgba(245, 158, 11, 0.42); }
.stage-pill.stage-won         { box-shadow: inset 0 1px 0 rgba(255,255,255,.14), inset 0 0 0 1px rgba(74, 222, 128, 0.42); }
.stage-pill.stage-lost        { box-shadow: inset 0 1px 0 rgba(255,255,255,.14), inset 0 0 0 1px rgba(248, 113, 113, 0.38); }

.filter-chip {
  background: var(--glass-fill-quiet);
  border-color: transparent;
  box-shadow: var(--glass-edge);
  transition: box-shadow var(--lift), color var(--lift);
}
.filter-chip:hover { box-shadow: var(--glass-edge-strong), 0 0 0 1px rgba(184, 164, 232, 0.4); }
.filter-chip.active {
  background: var(--glass-fill-strong);
  border-color: transparent;
  box-shadow: var(--glass-edge-strong), 0 0 0 1px rgba(184, 164, 232, 0.7), var(--shadow-under-sm);
}
.filter-chip-count {
  background: rgba(255, 255, 255, 0.10);
  color: var(--text-primary);
}
.filter-chip.active .filter-chip-count {
  background: var(--accent-lavender);
  color: #14102F;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.5);
}

/* THE ONE NUMBER THAT NEEDS ACTION. */
.today-count.overdue {
  background: var(--warn-hot-fill);
  border-color: transparent;
  color: var(--warn-hot);
  box-shadow: var(--glass-edge-hot);
}
.today-count {
  background: var(--glass-fill);
  border-color: transparent;
  color: var(--text-primary);
  box-shadow: var(--glass-edge);
}

.today-row.overdue {
  border-left: none;
  box-shadow: var(--glass-edge-hot), var(--shadow-under), inset 3px 0 0 var(--warn-hot);
}
.today-row.overdue .today-when {
  color: var(--warn-hot);
  font-family: var(--font-mono);
  font-size: 10.5px;
  letter-spacing: 0.09em;
  text-transform: uppercase;
}
.today-when {
  font-family: var(--font-mono);
  font-size: 10.5px;
  letter-spacing: 0.09em;
  text-transform: uppercase;
}
.today-opener {
  border-left-color: var(--violet-text-dim);
}
.today-last,
.today-contact {
  font-size: 12px;
}

.next-action.overdue .next-action-date { color: var(--warn-hot); }


/* ==========================================================================
 * 9. ICON CHIPS AND BUTTONS
 * An icon chip is a gradient-tinted rounded square with an inner ring and a
 * top light. Never a circle: that is the standing rule for a chip in this
 * house, and the two circles left on these screens were the placeholder glyph
 * and the biometric prompt.
 *
 * THE ONE !important IN THIS FILE is the radius on those two, because both
 * carry radius-full from a rule of equal specificity in dashboard.css and the
 * alternative is editing that file, which is what this layer exists to avoid.
 * ========================================================================*/
.placeholder-icon,
.biometric-icon {
  border-radius: 14px !important;
  background: linear-gradient(155deg, rgba(107, 79, 187, 0.34), rgba(107, 79, 187, 0.12));
  box-shadow: inset 0 0 0 1px rgba(184, 164, 232, 0.4),
              inset 0 1px 0 rgba(255, 255, 255, 0.16),
              0 6px 16px -8px rgba(107, 79, 187, 0.8);
  color: var(--violet-text);
}

.btn-primary {
  background: linear-gradient(180deg, var(--primary-purple-hover), var(--primary-purple));
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.26), 0 10px 22px -12px rgba(107, 79, 187, 0.9);
}
.btn-primary:hover:not(:disabled) {
  background: linear-gradient(180deg, #8B6FD8, var(--primary-purple-hover));
}
.btn-secondary,
.btn-ghost {
  border-color: transparent;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.09);
  transition: box-shadow var(--lift), color var(--lift);
}
.btn-secondary:hover:not(:disabled),
.btn-ghost:hover:not(:disabled) {
  background: rgba(255, 255, 255, 0.06);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.14), inset 0 0 0 1px rgba(184, 164, 232, 0.45);
}


/* ==========================================================================
 * 10. SHEETS, MODALS AND THE AUTH CARD
 * The same glass, one step stronger, because they sit above everything else.
 * ========================================================================*/
.touch-sheet,
.modal,
.auth-card {
  background: var(--glass-fill-strong);
  background-color: rgba(26, 21, 71, 0.86);
  backdrop-filter: blur(18px);
  -webkit-backdrop-filter: blur(18px);
  border: none;
  box-shadow: var(--glass-edge-strong),
              0 34px 64px -34px rgba(107, 79, 187, 0.85),
              0 4px 10px -4px rgba(11, 8, 34, 0.9);
}

.touch-backdrop,
.modal-backdrop {
  background: rgba(11, 8, 34, 0.74);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}

.touch-head,
.touch-more,
.touch-next,
.touch-foot,
.modal-header,
.modal-footer {
  border-color: rgba(255, 255, 255, 0.09);
}

.touch-kind,
.touch-result {
  background: var(--glass-fill);
  border-color: transparent;
  box-shadow: var(--glass-edge);
  transition: box-shadow var(--lift), background var(--lift);
}
.touch-kind:hover,
.touch-result:hover {
  box-shadow: var(--glass-edge-strong), 0 0 0 1px rgba(184, 164, 232, 0.4);
}
.touch-kind.on,
.touch-result.on {
  background: linear-gradient(180deg, var(--primary-purple-hover), var(--primary-purple));
  border-color: transparent;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.28), 0 8px 20px -10px rgba(107, 79, 187, 0.95);
}
.touch-step-label { color: var(--text-tertiary); font-family: var(--font-mono); letter-spacing: 0.14em; }

.today-empty {
  border-color: rgba(255, 255, 255, 0.12);
  color: var(--text-secondary);
}

input, textarea, select,
.pin-input,
.touch-field input {
  background: rgba(11, 8, 34, 0.55);
  border-color: transparent;
  box-shadow: inset 0 1px 2px rgba(11, 8, 34, 0.9), inset 0 0 0 1px rgba(255, 255, 255, 0.10);
}
input:focus, textarea:focus, select:focus,
.pin-input:focus {
  border-color: transparent;
  box-shadow: inset 0 0 0 1px var(--accent-lavender), 0 0 0 3px rgba(107, 79, 187, 0.3);
}


/* ==========================================================================
 * 11. SECTION BANDS AND THE FOOTER MARK
 * A band is a mono label, a gradient rule fading right, and the count. The
 * platform footer line stays exactly where it is.
 * ========================================================================*/
.briefings-section-header {
  align-items: center;
  gap: 12px;
}
.briefings-section-header::after {
  content: "";
  flex: 1;
  height: 2px;
  border-radius: 2px;
  background: linear-gradient(90deg, rgba(107, 79, 187, 0.6), rgba(107, 79, 187, 0.05));
}
.briefings-section-sub { order: 3; }

.app-footer {
  border-top: 1px solid rgba(255, 255, 255, 0.07);
}
.app-footer-mark {
  letter-spacing: 0.06em;
}


/* ==========================================================================
 * 12. MOTION
 * One duration for a hover lift. The page already honors prefers-reduced-
 * motion from a block in index.html and auth.html, which zeroes every
 * animation and transition including the pulse.
 * ========================================================================*/
@media (prefers-reduced-motion: reduce) {
  .session-dot { animation: none; }
}


/* ==========================================================================
 * 13. THE SURFACES WHOSE STYLES ARE INJECTED AT RUN TIME
 *
 * js/touches.js and js/prospects.js each append a <style> element to the head
 * when they first render, which is a deliberate choice recorded in their own
 * comments: dashboard.css is 82KB and other lanes read it. An appended style
 * element comes AFTER this stylesheet in document order, so on equal
 * specificity IT wins, and the first draft of this file lost every rule it
 * wrote for a .today-row or a .touch-kind without saying so.
 *
 * So every selector in this section is prefixed with `body`, which costs one
 * element and puts these rules a step above the injected ones. It is not a
 * trick: it is the smallest thing that makes the cascade match the intent,
 * and it is written here in one block rather than scattered so the reason
 * survives. The alternative was !important on forty rules.
 * ========================================================================*/
body .today-row,
body .prospect-box {
  background: var(--glass-fill);
  background-color: rgba(26, 21, 71, 0.5);
  backdrop-filter: var(--glass-blur);
  -webkit-backdrop-filter: var(--glass-blur);
  border: none;
  box-shadow: var(--glass-edge), var(--shadow-under);
}

body .today-row.overdue {
  box-shadow: var(--glass-edge-hot), var(--shadow-under), inset 3px 0 0 var(--warn-hot);
}

/* The late marker is the amber, not the red. Overdue is work waiting, and the page keeps one
   alarm color for actual errors. The injected rule this replaces sets it to --danger and wins
   on document order, which is why this selector carries the body prefix like the rest. */
body .today-row.overdue .today-when {
  color: var(--warn-hot);
  font-family: var(--font-mono);
  font-size: 10.5px;
  letter-spacing: 0.09em;
  text-transform: uppercase;
}
body .today-when {
  font-family: var(--font-mono);
  font-size: 10.5px;
  letter-spacing: 0.09em;
  text-transform: uppercase;
}

body .today-count {
  background: var(--glass-fill);
  background-color: rgba(255, 255, 255, 0.04);
  border: none;
  color: var(--text-primary);
  box-shadow: var(--glass-edge);
  font-family: var(--font-mono);
  letter-spacing: 0.08em;
  padding: 4px 11px;
}
body .today-count.overdue {
  background: var(--warn-hot-fill);
  color: var(--warn-hot);
  box-shadow: var(--glass-edge-hot);
}

body .today-empty {
  border: 1px dashed rgba(255, 255, 255, 0.16);
  background: var(--glass-fill-quiet);
  color: var(--text-secondary);
}

body .today-last,
body .today-opener-tag,
body .score-note,
body .prospect-status { color: var(--text-tertiary); }

body .today-opener { border-left-color: var(--violet-text-dim); }

body .score-table th,
body .score-table td { border-bottom: none; box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.055); }
body .score-table thead th {
  border-bottom: none;
  box-shadow: inset 0 -1px 0 rgba(255, 255, 255, 0.10);
  background: rgba(255, 255, 255, 0.028);
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--text-secondary);
}
body .score-table tr.this-week { background: rgba(184, 164, 232, 0.09); }
body .score-table tr.future td { color: var(--text-tertiary); }
body .score-target td { color: var(--text-secondary); }
body .score-now { color: var(--violet-text); font-family: var(--font-mono); }

body .touch-sheet {
  background: var(--glass-fill-strong);
  background-color: rgba(26, 21, 71, 0.88);
  backdrop-filter: blur(18px);
  -webkit-backdrop-filter: blur(18px);
  border: none;
  box-shadow: var(--glass-edge-strong),
              0 -18px 46px -30px rgba(107, 79, 187, 0.85),
              0 -2px 8px -3px rgba(11, 8, 34, 0.9);
}
body .touch-backdrop { background: rgba(11, 8, 34, 0.74); backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px); }
body .touch-head,
body .touch-more,
body .touch-next,
body .touch-foot { border-color: rgba(255, 255, 255, 0.09); }
body .touch-kind,
body .touch-result {
  background: var(--glass-fill);
  border: none;
  box-shadow: var(--glass-edge);
  transition: box-shadow var(--lift), background var(--lift);
}
body .touch-kind.on,
body .touch-result.on {
  background: linear-gradient(180deg, var(--primary-purple-hover), var(--primary-purple));
  border: none;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.28), 0 8px 20px -10px rgba(107, 79, 187, 0.95);
}
body .touch-step-label {
  color: var(--text-tertiary);
  font-family: var(--font-mono);
  letter-spacing: 0.14em;
}
body .touch-field input,
body .prospect-form input,
body .prospect-form select,
body .prospect-offer-date input {
  background: rgba(11, 8, 34, 0.55);
  border: none;
  box-shadow: inset 0 1px 2px rgba(11, 8, 34, 0.9), inset 0 0 0 1px rgba(255, 255, 255, 0.10);
}
body .prospect-modal-head,
body .prospect-pick-row { border-color: rgba(255, 255, 255, 0.09); }
body .prospect-flag {
  border-color: transparent;
  color: var(--warn-hot);
  background: var(--warn-hot-fill);
  box-shadow: var(--glass-edge-hot);
  font-family: var(--font-mono);
  letter-spacing: 0.09em;
}


/* ==========================================================================
 * 14. THE REVENUE PANEL'S OWN TABLE AND CHART
 * ========================================================================*/
.revenue-lines-table {
  border: none;
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: var(--glass-fill-quiet);
  box-shadow: var(--glass-edge);
}
.revenue-lines-table thead {
  background: rgba(255, 255, 255, 0.028);
  box-shadow: inset 0 -1px 0 rgba(255, 255, 255, 0.10);
}
.revenue-lines-table th {
  font-family: var(--font-mono);
  letter-spacing: 0.13em;
  border-bottom: none;
}
.revenue-lines-table tbody tr {
  border-bottom: none;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.055);
}
.revenue-lines-table tbody tr:hover { background: rgba(255, 255, 255, 0.055); }
.revenue-lines-table td.num { font-family: var(--font-mono); font-feature-settings: "tnum" 1; }

.category-pill {
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.16), inset 0 0 0 1px rgba(255, 255, 255, 0.09);
  font-family: var(--font-mono);
  letter-spacing: 0.08em;
}
.date-range { color: var(--text-tertiary); }

.trend-bar-label,
.trend-y-label { font-family: var(--font-mono); }
.trend-target-label { font-family: var(--font-mono); fill: var(--violet-text); }

.mrr-delta-label { font-family: var(--font-mono); letter-spacing: 0.14em; }


/* ==========================================================================
 * 15. BRIEFINGS AND MODULES
 * The two card grids. Same glass, same lift, and their meta lines take the
 * mono face so a date column reads as data rather than as prose.
 * ========================================================================*/
.briefing-card-day,
.briefing-card-date,
.briefing-card-time,
.briefing-card-cat,
.briefings-last-generated,
.briefings-section-sub,
.module-status {
  font-family: var(--font-mono);
}

.briefing-card-header,
.briefing-sources,
.briefing-qa {
  border-color: rgba(255, 255, 255, 0.08);
}

.briefings-archive,
.briefings-archive-row {
  border-color: rgba(255, 255, 255, 0.08);
}

.module-card-actions { border-top-color: rgba(255, 255, 255, 0.09); }


/* ==========================================================================
 * 16. ONE LAYOUT FIX, NAMED
 * "Show paused" sat at the right end of the pipeline filter row, wrapped to
 * two lines and ran off the edge of the screen at 1280. It did that before
 * this lane and it is a legibility fault on a screen this lane is restyling,
 * so it is fixed here rather than left for somebody to find in a screenshot.
 * Nothing about the control's behavior changes.
 * ========================================================================*/
.filter-toggle {
  flex-shrink: 0;
  white-space: nowrap;
}

/* =========================================================================
   OC-4, September 4, 2026. The two-factor sign-in and the security screen.

   Appended to the polish layer rather than given a sheet of its own, because a
   sixth stylesheet is a sixth request on a phone at a well site and every rule
   below is the same dark glass the rest of OC-3 already established.

   EVERY COLOR HERE IS A TOKEN. Nothing is a hex value and nothing paints text
   with --primary-purple, which measured 2.79:1 as text in OC-3 and which
   tests/verify_contrast.js bans in this file by name. Foregrounds are
   --text-primary, --text-secondary and --text-tertiary, all three of which
   clear their floors on the backdrops recorded in tests/contrast-measured.json.
   ========================================================================= */

/* ----- the sign-in card's second and third screens ----- */

.auth-step-title {
  font-weight: 600;
  color: var(--text-primary);
  margin: 0 0 var(--space-2);
}

.auth-alt {
  margin: var(--space-5) 0 0;
  font-size: var(--text-sm);
  color: var(--text-tertiary);
}

.auth-alt a {
  color: var(--text-secondary);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.auth-alt a:hover,
.auth-alt a:focus-visible {
  color: var(--text-primary);
}

.auth-input {
  width: 100%;
  margin-top: var(--space-3);
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-md);
  border: 1px solid var(--border-accent);
  background: var(--bg-input);
  color: var(--text-primary);
  font-size: var(--text-base);
  letter-spacing: 0.06em;
  text-align: center;
}

.auth-input::placeholder { color: var(--text-tertiary); letter-spacing: 0.04em; }
.auth-input:focus { outline: none; border-color: var(--border-strong); }

/* ----- the security section ----- */

.sec-state {
  margin: 0 0 var(--space-3);
  padding: var(--space-4) var(--space-5);
  border-radius: var(--radius-lg);
  background: var(--glass-fill-quiet);
  box-shadow: var(--glass-edge);
  color: var(--text-primary);
  font-size: var(--text-sm);
  line-height: 1.6;
}

.sec-state.sec-quiet { color: var(--text-secondary); }

.sec-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  margin: var(--space-4) 0 var(--space-3);
}

.sec-msg {
  min-height: 20px;
  margin-bottom: var(--space-3);
  font-size: var(--text-sm);
  color: var(--text-secondary);
}

.sec-empty { color: var(--text-tertiary); font-size: var(--text-sm); }

.sec-table { width: 100%; border-collapse: collapse; font-size: var(--text-sm); }

.sec-table th {
  text-align: left;
  padding: var(--space-2) var(--space-3);
  color: var(--text-tertiary);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-size: var(--text-xs);
  border-bottom: 1px solid var(--border-accent);
}

.sec-table td {
  padding: var(--space-3);
  color: var(--text-secondary);
  border-bottom: 1px solid var(--border-accent);
  vertical-align: middle;
}

.sec-table td.sec-name { color: var(--text-primary); font-weight: 500; }
.sec-table td.sec-act { text-align: right; }

/* A revoked row stays on the screen and is dimmed rather than removed. A row that vanishes when
   it is revoked leaves no way to tell "I revoked that phone in September" from "that phone was
   never here", and after a theft those are very different answers. */
.sec-table tr.sec-dead td { color: var(--text-tertiary); }

.sec-tag {
  display: inline-block;
  margin-left: var(--space-2);
  padding: 1px var(--space-2);
  border-radius: var(--radius-full);
  background: var(--glass-fill);
  color: var(--text-tertiary);
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

.sec-codes-out {
  margin-top: var(--space-5);
  padding: var(--space-5);
  border-radius: var(--radius-lg);
  background: var(--glass-fill);
  box-shadow: var(--glass-edge-strong);
}

.sec-codes-head {
  margin: 0 0 var(--space-4);
  color: var(--text-primary);
  font-size: var(--text-sm);
  line-height: 1.6;
}

.sec-codes-list {
  margin: 0 0 var(--space-4);
  padding-left: var(--space-6);
  columns: 2;
  color: var(--text-primary);
  font-family: var(--font-mono);
  font-size: var(--text-base);
  letter-spacing: 0.08em;
  line-height: 2;
}

/* The codes are meant to end up on paper. On the printed sheet the rest of the console is noise,
   so everything but the code block is dropped and the ink goes on the ten strings. */
@media print {
  body > *:not(.app-main),
  .app-main > .section:not(#section-security) { display: none !important; }
  #section-security .section-header,
  #section-security .sec-actions,
  #section-security .sec-table,
  #section-security #sec-print { display: none !important; }
  .sec-codes-out { background: none; box-shadow: none; }
  .sec-codes-head, .sec-codes-list { color: #000; }
}

@media (max-width: 640px) {
  .sec-table thead { display: none; }
  .sec-table tr { display: block; padding: var(--space-3) 0; border-bottom: 1px solid var(--border-accent); }
  .sec-table td { display: block; border: none; padding: 2px var(--space-1); }
  .sec-table td.sec-act { text-align: left; padding-top: var(--space-2); }
  .sec-codes-list { columns: 1; }
}

/* Function illustrations: the original symbol remains as an offline fallback. */
.fh-function-art{position:relative;display:inline-grid;place-items:center;width:52px;height:52px;flex:0 0 auto}
.fh-function-art>img{position:absolute;inset:0;width:100%;height:100%;object-fit:contain;opacity:0;pointer-events:none}
.fh-function-art.is-ready>img{opacity:1}
.fh-function-art.is-ready>svg{visibility:hidden}

/* Larger recognizable marks, with the existing labeled navigation retained. */
.oc-row .fh-function-art{width:36px;height:36px}
.oc-row{min-height:52px}
.oc-row-t{line-height:1.35}
.oc-row:focus-visible{outline:2px solid var(--violet-text);outline-offset:3px}
.section-subtitle{max-width:60ch;line-height:1.5}
@media(max-width:820px){.oc-row .fh-function-art{width:30px;height:30px}}
