/* platform.css — one look, for every screen in the Hub.
 * ============================================================================
 *
 * WHY THIS EXISTS
 *
 * The Hub speaks six design languages. The org admin overview (css/ops.css) is
 * the one that reads like an expensive product. Every other screen is plain
 * SaaS: white cards on a grey field, a drop shadow under each one, numbers set
 * in whatever the body font does by default.
 *
 * Miranda, 2026-08-28, on the super admin screenshot: "this is the look of the
 * platform to have a more updated expensive look versus plain. similar to what
 * we did with the overview dashboard... think of how i redesigned homepage by
 * pulling to viewport."
 *
 * WHAT ACTUALLY MAKES ONE LOOK EXPENSIVE AND THE OTHER PLAIN
 *
 * Not color. Color is handled entirely by /js/org-accent.js and the --a
 * triplet, and it is the organization's, not ours. The difference is four
 * things, all measurable in the existing code:
 *
 *   1. HAIRLINES, NOT SHADOWS. ops.css draws every edge with a 13%-opacity
 *      1px border. The plain screens stack drop shadows up to
 *      `0 12px 48px rgba(0,0,0,0.2)`. A shadow says "card floating on a page".
 *      A hairline says "panel in a system". Shadows also multiply: three
 *      shadowed cards in a row read as clutter, three hairlined panels read as
 *      a table of contents.
 *
 *   2. TYPOGRAPHIC DISCIPLINE. Micro-labels are 11px, 700, uppercase, tracked
 *      out to .13em. Display headings are LIGHT (300) and tracked IN to
 *      -.015em. Plain screens use one weight for everything and no tracking at
 *      all. This single pair of moves does more work than any other rule here.
 *
 *   3. TABULAR FIGURES. `font-variant-numeric: tabular-nums` on anything that
 *      is a number. Without it, 223 and 111 are different widths and a column
 *      of figures visibly wobbles. This is the cheapest credibility in the
 *      entire stylesheet and it is missing from every screen but one.
 *
 *   4. SCALE THAT COMMITS. The homepage redesign pulled its sections to
 *      `min-height:100svh` and set display type at 62-68px. Editorial layouts
 *      are not afraid of a big number or an empty margin. Plain layouts hedge
 *      at 40px and fill every gap with a panel that says "No pending
 *      submissions."
 *
 * HOW THE ROLLOUT WORKS
 *
 * Every variant lives here, switched by `data-design` on <html>. Nothing is
 * forked, so a page cannot be half-migrated: it either reads these classes or
 * it does not.
 *
 *   data-design="classic"    what most screens look like today
 *   data-design="editorial"  the direction above
 *
 * /js/platform-design.js sets the attribute before first paint from the value
 * MiRAjO approved. The Design screen in super admin previews both against real
 * components and writes the approved one, and every page picks it up on next
 * load. That is the whole mechanism: preview it, approve it, it is live
 * everywhere, and it is one attribute to roll back.
 *
 * Token names deliberately match css/ops.css, so the two compose on the same
 * screen rather than fighting.
 */

/* ── tokens ──────────────────────────────────────────────────────────────── */

:root {
  /* Accent. Owned by /js/org-accent.js, held as an RGB triplet so a fill, a
     glow and a 6%-opacity wash all come off one number. MiRAjO green is only
     the fallback for an org that has never set a color. */
  --a:            37,107,66;
  --a-2:          109,196,138;

  --ground:       #F5F7FA;
  --panel:        #FFFFFF;
  --panel-2:      #F4F7FA;
  --hair:         rgba(19,26,36,.13);
  --hair-2:       rgba(19,26,36,.07);
  --ink:          #131A24;
  --ink-2:        #414E60;

  /* Was #5D6B7D, which measures 5.43:1 on white. That passes AA on paper and
     failed in practice: Miranda, 2026-08-28, "light mode is good, but very
     light to the point almost unable to read some words."
     Two things were wrong. The ratio assumes ~16px text and this is used at
     12-13px, where AA is not enough. And the same token on the dark surface
     measures 6.99:1, so light was materially weaker than dark for no reason
     anyone chose. #4E5C6E is 6.82:1, which matches dark and keeps the three
     inks visibly distinct.
     NOTE: css/ops.css still carries the old #5D6B7D, so the org admin overview
     has the same weakness in light mode. Same fix, same reason. */
  --ink-3:        #4E5C6E;

  --good:         #1B7A52;
  --warn:         #8A5A0B;

  /* Destructive. Not the same as --warn: warn is "look at this", danger is
     "this cannot be undone". Two lanes independently reached for a red the
     schema did not have and both fell back to a literal #D94040, which is how
     a sixth vocabulary starts. 4.9:1 on white, so it carries small text. */
  --danger:       #C0392B;

  /* Prose is NOT a caption. --ink-3 is for labels and micro-copy; a sentence
     somebody has to READ gets --ink-2 at 8.46:1. Using the tertiary ink for
     body text is what actually made light mode hard to read, more than the
     value of any single token. */
  --prose:        var(--ink-2);
  --prose-size:   13.5px;

  --f:            'Inter', ui-sans-serif, system-ui, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
  --f-display:    'Instrument Serif', Georgia, 'Times New Roman', serif;

  /* One radius scale. Three values, not nine. */
  --r-sm:         8px;
  --r:            12px;
  --r-lg:         16px;

  /* Vertical rhythm. Every gap on a screen is one of these. The plain screens
     use arbitrary margins between 10px and 60px, which is most of why they
     read as unconsidered. */
  --s-1:          6px;
  --s-2:          10px;
  --s-3:          16px;
  --s-4:          24px;
  --s-5:          40px;
  --s-6:          64px;
}

/* ── variant: classic ────────────────────────────────────────────────────────
   Today's look, named so it can be chosen rather than merely inherited, and so
   an approval is reversible with one attribute. */

:root[data-design="classic"] {
  --edge:         none;
  --lift:         0 1px 4px rgba(0,0,0,0.08);
  --panel-pad:    18px 20px;
  --label-size:   11px;
  --label-track:  .04em;
  --label-weight: 700;
  --figure-size:  40px;
  --figure-weight:400;
  --figure-family:var(--f-display);
  --h-weight:     700;
  --h-track:      0;
  --section-min:  auto;
}

/* ── variant: editorial ─────────────────────────────────────────────────────
   The direction. Hairline instead of shadow, light display weight tracked in,
   micro-labels tracked out, figures tabular. */

/* Values taken from hub-super-report.html, the page Miranda named as the look.
   .stat-lbl is 700 10px at .1em; .stat-num is 300 30px at -.025em; the box is a
   1px hairline at 10px radius with 12px 13px padding and no shadow anywhere in
   the file. Matching them exactly is what makes the rest of the platform look
   like that page rather than merely resemble it. */
:root[data-design="editorial"] {
  --edge:         1px solid var(--hair);
  --lift:         none;
  --panel-pad:    12px 13px 13px;
  --label-size:   10px;
  --label-track:  .1em;
  --label-weight: 700;
  --figure-size:  clamp(21px, 2.4vw, 30px);
  --figure-weight:300;
  --figure-family:var(--f);
  --h-weight:     300;
  --h-track:      -.025em;
  --section-min:  100svh;
  --r:            10px;
}

/* Default to editorial when nothing has been approved yet, so a page that
   loads before the attribute resolves is never left unstyled. */
:root:not([data-design]) {
  --edge:         1px solid var(--hair);
  --lift:         none;
  --panel-pad:    12px 13px 13px;
  --label-size:   10px;
  --label-track:  .1em;
  --label-weight: 700;
  --figure-size:  clamp(21px, 2.4vw, 30px);
  --figure-weight:300;
  --figure-family:var(--f);
  --h-weight:     300;
  --h-track:      -.025em;
  --section-min:  100svh;
  --r:            10px;
}

/* ── primitives ──────────────────────────────────────────────────────────── */

.p-panel {
  background: var(--panel);
  border: var(--edge);
  border-radius: var(--r);
  box-shadow: var(--lift);
  padding: var(--panel-pad);
}

/* ── the schema ──────────────────────────────────────────────────────────────
 *
 * Miranda, 2026-08-29: "there is no consistent schema from page to page. this
 * page is the look /hub/platform-report but as i go through it inconsistent."
 *
 * She is right, and the cause is not carelessness on any one page. The look she
 * picked lives INSIDE hub-super-report.html: its own :root, its own .stat-num,
 * its own .section. Nothing else can reach it. Counting this file there are now
 * four copies of the same idea - css/ops.css, css/holo.css, that page's inline
 * block, and here - so of course they drift.
 *
 * The values below are lifted from hub-super-report.html verbatim, because that
 * is the page she named. This file is the schema; that page becomes one more
 * consumer of it rather than the only place it exists.
 *
 * WHAT TO USE, in the order a screen is built:
 *
 *   .p-section          one band of the page          margin below, nothing else
 *   .p-section-title    its heading row               heading left, count right
 *   .p-section-count    "12 organizations"            sits in the title row
 *   .p-section-note     one line under the heading    says what the band means
 *   .p-stats            a row of figures              auto-fit, never clips
 *   .p-stat             one figure                    label + number + caption
 *   .p-label            the small caps above anything
 *   .p-figure           any number a person reads
 *   .p-cap              the line under a figure       what it is counted over
 *   .p-trend            direction, or why there is none
 *   .p-panel            a framed block of content
 *   .p-tablewrap        wide content scrolls inside itself
 *   .p-chip             a status word
 *   .p-btn              one accent action per view
 *   .p-prose            a sentence somebody has to read
 *   .p-empty            nothing here, in one quiet line
 *
 * A page that needs something not on this list needs it adding HERE, not
 * inventing locally. That is the whole point.
 */

/* A label above a number, a section, or a field. 10px/700/.1em, from
   hub-super-report's .stat-lbl. */
.p-label {
  display: block;
  font: var(--label-weight) var(--label-size)/1.3 var(--f);
  letter-spacing: var(--label-track);
  text-transform: uppercase;
  color: var(--ink-3);
}

/* One band of a page. */
.p-section { margin-bottom: 26px; }

/* The heading row: title left, count right. It carried only layout, so every
   page using it had to re-invent its own section typography — which is exactly
   the drift the schema exists to stop. The type below is the reference page's
   own .section-title, copied rather than approximated. */
.p-section-title {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 12px; flex-wrap: wrap;
  font: 700 11px/1 var(--f);
  text-transform: uppercase;
  letter-spacing: .13em;
  color: var(--ink-3);
  padding-bottom: 8px;
  border-bottom: 1px solid var(--hair);
  margin-bottom: 10px;
}

/* The count belongs beside the heading, not inside it: "Organizations  12 of
   15". Deliberately not uppercase and not tracked, so it reads as a fact rather
   than as a second heading. */
.p-section-count {
  font: 400 11px/1.4 var(--f);
  letter-spacing: 0;
  text-transform: none;
  color: var(--ink-3);
  font-variant-numeric: tabular-nums;
}

/* One line saying what the band means, or what its numbers are counted over.
   This is where "Last 30 days, 3 customer organizations" goes. */
.p-section-note {
  font: 400 var(--prose-size)/1.55 var(--f);
  color: var(--prose);
  margin: -2px 0 10px;
  max-width: 68ch;
}

/* The line under a figure. Not a trend: the trend has its own component. This
   is "0 of 6 started a session" - what the number is, said plainly. */
.p-cap {
  font: 400 11.5px/1.4 var(--f);
  color: var(--ink-3);
  margin-top: 6px;
}

/* Any number a person reads as a number. tabular-nums is not optional: a
   column of figures that changes width as it updates looks broken, and this
   is the single cheapest credibility gain available. */
.p-figure {
  font-family: var(--figure-family);
  font-size: var(--figure-size);
  font-weight: var(--figure-weight);
  line-height: 1;
  letter-spacing: -.025em;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}

.p-h {
  font-family: var(--f);
  font-weight: var(--h-weight);
  letter-spacing: var(--h-track);
  color: var(--ink);
  font-size: clamp(20px, 2.2vw, 27px);
  line-height: 1.12;
}

/* A stat: label, figure, and its direction. Built as one component because
   rule 1 of the build plan says a number shows its direction or shows nothing,
   and the only way to guarantee that is to make the number and the trend the
   same object. */
.p-stat { display: flex; flex-direction: column; gap: var(--s-1); min-width: 0; }
.p-stat .p-figure { margin: 2px 0 0; }

.p-trend {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font: 600 11.5px/1 var(--f);
  font-variant-numeric: tabular-nums;
  letter-spacing: .01em;
}
.p-trend.up   { color: var(--good); }
.p-trend.down { color: var(--warn); }
/* The honest third state. When the basis is too small or the history too
   short, this renders instead of an arrow, and it is deliberately quiet
   rather than absent so the reader can tell "we did not measure this" from
   "this did not move". */
.p-trend.hold { color: var(--ink-3); font-weight: 500; }

/* A row of stats that never scrolls sideways. The super admin overview clipped
   its fourth card off the right edge of the viewport; auto-fit with a minimum
   makes that impossible at any width. */
.p-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
  gap: var(--s-2);
}

/* Sections that commit to the viewport, the homepage move. Opt-in per section
   rather than global, because a settings form pulled to 100svh is not
   editorial, it is just empty. */
/* A band sitting close to the one above it.

   The reference page's .section is `margin-bottom: 26px` and nothing else — it
   has no vertical padding at all. A dense working screen like member home wants
   that; only a landing-style page wants the roomier default. Miranda's "too
   many gaps" note was partly this file's own doing, and the member-home lane
   had to declare this locally to render, which is the signal it belongs here. */
.p-section--tight { padding-block: 0; margin-bottom: var(--s-4); }

/* .p-section is declared once, above, at 26px. It used to be declared TWICE —
   26px of margin here and 64px of padding again down here — so two bands sat
   154px apart and every page built on the schema inherited a gap nobody chose.
   Miranda's note on member home was "too many gaps"; this file was one of the
   causes. The viewport-committing move stays where it belongs, on the opt-in
   modifier below. */
.p-section--full {
  min-height: var(--section-min);
  display: flex;
  flex-direction: column;
  justify-content: center;
}

/* A hairline that carries the org's color. One accent element per section is
   enough; this is what replaces a colored header bar. */
.p-rule {
  height: 2px;
  width: 44px;
  border: 0;
  border-radius: 2px;
  background: rgb(var(--a));
  margin: 0 0 var(--s-3);
}

/* An empty state is one quiet line, never a full panel saying nothing. The
   super admin overview gave "No pending submissions." an entire card. */
.p-empty {
  font: 400 var(--prose-size)/1.5 var(--f);
  color: var(--prose);
  padding: var(--s-3) 0;
}

/* Body copy. Anything that is a sentence rather than a label uses this: it
   reads at --ink-2, wraps rather than truncating, and breaks long words instead
   of pushing the panel sideways.
   The wrapping matters as much as the color. Prose set to nowrap with an
   ellipsis silently eats the end of an explanation, which is worse than
   wrapping to three lines. */
.p-prose {
  font: 400 var(--prose-size)/1.6 var(--f);
  color: var(--prose);
  max-width: 68ch;
  overflow-wrap: anywhere;
  hyphens: auto;
}

/* A name in a list. Truncating a long organization name is acceptable where a
   full one would break the row, but it must carry the whole name in a title
   attribute so it is recoverable, and on a narrow screen it wraps instead. */
.p-name {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
@media (max-width: 640px) {
  .p-name { white-space: normal; overflow: visible; text-overflow: clip; }
}

/* Tables. Wide content scrolls inside its own container, never the page. */
.p-tablewrap {
  border: var(--edge);
  border-radius: var(--r);
  box-shadow: var(--lift);
  background: var(--panel);
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}
.p-table { width: 100%; border-collapse: collapse; font: 400 13.5px/1.45 var(--f); }
.p-table th {
  font: var(--label-weight) var(--label-size)/1 var(--f);
  letter-spacing: var(--label-track);
  text-transform: uppercase;
  color: var(--ink-3);
  text-align: left;
  padding: 13px 16px;
  border-bottom: 1px solid var(--hair);
  white-space: nowrap;
}
.p-table td { padding: 13px 16px; border-bottom: 1px solid var(--hair-2); color: var(--ink-2); }
.p-table tr:last-child td { border-bottom: 0; }
.p-table .num { font-variant-numeric: tabular-nums; }

.p-chip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font: 700 10.5px/1 var(--f);
  letter-spacing: .08em;
  text-transform: uppercase;
  padding: 5px 9px;
  border-radius: 999px;
  background: rgba(var(--a), .11);
  color: rgb(var(--a));
  border: 1px solid rgba(var(--a), .18);
}

.p-btn {
  font: 700 13px/1 var(--f);
  padding: 12px 20px;
  border-radius: var(--r-sm);
  border: 1px solid rgb(var(--a));
  background: rgb(var(--a));
  color: #fff;
  cursor: pointer;
  transition: opacity .15s;
}
.p-btn:hover { opacity: .9; }
.p-btn--quiet { background: transparent; color: rgb(var(--a)); }

/* ── dark ───────────────────────────────────────────────────────────────────
   Rule 5 of the build plan: bright is the working surface, dark is the
   presentation surface. Same primitives, so a board screen is the same code as
   a Tuesday morning. */

/* Values lifted verbatim from css/ops.css [data-ops-theme="dark"], which is the
   surface the org admin overview already presents in and the one Miranda
   pointed at as the look she wants everywhere. Copying them rather than
   inventing a second dark palette means the two screens cannot drift, and a
   dark panel from either file can sit on the same page. */
.p-dark, :root[data-theme="dark"] {
  --ground:  #070B11;
  --panel:   #111823;
  --panel-2: #161F2C;
  --hair:    rgba(190,214,240,.14);
  --hair-2:  rgba(190,214,240,.075);
  --ink:     #F0F4F9;
  --ink-2:   #C0CCDB;
  --ink-3:   #93A4B8;
  --good:    #4CD49B;
  --warn:    #E5AC57;
  /* 8.70:1 on this panel. The light value, #C0392B, measures 3.28:1 here and
     would be unreadable; --good and --warn already carry the same pattern. */
  --danger:  #FF9A8C;
}

/* ── motion ─────────────────────────────────────────────────────────────────
   Anyone whose system asks for less motion gets none. */
@media (prefers-reduced-motion: reduce) {
  .p-btn { transition: none; }
}
