/* OHMIX — ohmix-ui.css · the single design-token and base-component source.
   Every page links this sheet FIRST; page styles may refine components but must
   never redefine tokens. Before this file existed the :root block was pasted
   into five pages and had already diverged (two primary buttons, ten radii,
   disconnected theming) — see docs/LAYOUT-AUDIT.md, phase L1.

   Radius scale: --r-1 (controls) · --r-2 (cards, inputs groups) · --r-3
   (panels, dialogs) · --r-pill. New UI picks from the scale, nothing else.

   ---- contrast ------------------------------------------------------------
   Every colour below is measured, not chosen by eye. The light theme was
   audited 2026-08-13 and five roles failed WCAG AA for normal text; the dark
   theme passed everywhere except --ink-faint. The failures and their fixes:

     role                 was       ratio   now       ratio  where it shows
     --accent as text     #0E9E8E    2.94   #0A7568    4.93  .eyebrow, links, .k
     white on --accent    #0E9E8E    3.33   #0A7568    5.59  EVERY primary button
     --ink-faint          #7C8C9A    3.46   #5A6E80    5.28  hints, price units, tags
     --good               #0E9E5B    3.47   #0B7A47    5.40  success messages
     --warn               #B5730E    3.87   #8A5A08    5.92  warnings, meter bars
     --ink-faint (dark)   #5E6E7E    3.38   #7C8C9A    5.13  same roles, dark

   The accent is ONE value, not a fill colour plus a darker text colour. The
   primary button is white text on the accent, so the accent had to carry 4.5:1
   against white whatever else changed — and once it does, a second lighter teal
   for fills would put two different brand greens on the same screen. #0A7568 is
   the lightest teal that clears 4.5:1 in both directions, so it is the smallest
   move away from the original that is actually legible.

   The omega mark needed no change: it is --bg on --accent, and darkening the
   accent lifted it from 2.94 to 4.93, past the 3:1 a graphical object needs.

   Before changing any of these, run the ratio again. A colour that looks fine
   on your monitor at 100% zoom is not the test. */

:root{
  /* colour — light */
  --bg:#EEF1F4; --bg-2:#F6F8FA; --surface:#FFFFFF;
  --line:rgba(16,40,55,.12); --line-strong:rgba(16,40,55,.20);
  --ink:#0E1922; --ink-dim:#475A6A; --ink-faint:#5A6E80;
  --accent:#0A7568; --accent-soft:rgba(10,117,104,.12); --accent-ink:#FFFFFF;
  --accent-press:#075A50;
  --warn:#8A5A08; --amber:var(--warn); --bad:#C23A3A; --good:#0B7A47;
  /* the oscilloscope screen stays dark in both themes */
  --screen:#080C11; --screen-2:#0B1118; --screen-line:rgba(90,150,150,.13);
  --trace:#3FE0CB; --trace-2:#FFB454; --screen-ink:#DDE8EE; --screen-dim:#7C93A0;
  /* type */
  --font-mono:ui-monospace,"SF Mono","Cascadia Code","JetBrains Mono",Menlo,Consolas,monospace;
  --font-sans:ui-sans-serif,"Segoe UI","Helvetica Neue",Helvetica,Arial,sans-serif;
  /* radius scale */
  --r-1:8px; --r-2:12px; --r-3:16px; --r-pill:999px;
}
@media (prefers-color-scheme:dark){
  :root{
    --bg:#0A0E13; --bg-2:#0C1219; --surface:#101922;
    --line:rgba(120,145,165,.14); --line-strong:rgba(120,145,165,.24);
    --ink:#E7EEF4; --ink-dim:#93A2B2; --ink-faint:#7C8C9A;
    --accent:#3FE0CB; --accent-soft:rgba(63,224,203,.12); --accent-ink:#07100E;
    --accent-press:var(--accent);
    --warn:#FFB454; --bad:#F0736B; --good:#4CD494;
  }
}
:root[data-theme="dark"]{
  --bg:#0A0E13; --bg-2:#0C1219; --surface:#101922;
  --line:rgba(120,145,165,.14); --line-strong:rgba(120,145,165,.24);
  --ink:#E7EEF4; --ink-dim:#93A2B2; --ink-faint:#7C8C9A;
  --accent:#3FE0CB; --accent-soft:rgba(63,224,203,.12); --accent-ink:#07100E;
  --accent-press:var(--accent);
  --warn:#FFB454; --bad:#F0736B; --good:#4CD494;
}
:root[data-theme="light"]{
  --bg:#EEF1F4; --bg-2:#F6F8FA; --surface:#FFFFFF;
  --line:rgba(16,40,55,.12); --line-strong:rgba(16,40,55,.20);
  --ink:#0E1922; --ink-dim:#475A6A; --ink-faint:#5A6E80;
  --accent:#0A7568; --accent-soft:rgba(10,117,104,.12); --accent-ink:#FFFFFF;
  --accent-press:#075A50;
  --warn:#8A5A08; --bad:#C23A3A; --good:#0B7A47;
}

/* ---- base ------------------------------------------------------------- */
*{box-sizing:border-box}
::selection{background:var(--accent);color:var(--bg)}
:focus-visible{outline:2px solid var(--accent);outline-offset:3px;border-radius:2px}
/* [hidden]{display:none} is a USER-AGENT rule, so any author display
   declaration silently beats it. This one author-level rule closes the whole
   trap class product-wide (it has bitten .btn, .chip and #trialChip before). */
[hidden]{display:none !important}
.skip{position:absolute;left:-999px;top:0;background:var(--accent);color:var(--accent-ink);padding:.6rem 1rem;border-radius:0 0 var(--r-1) 0;z-index:60}
.skip:focus{left:0}
.mono{font-family:var(--font-mono)}
.eyebrow{font-family:var(--font-mono);font-size:.72rem;letter-spacing:.18em;text-transform:uppercase;color:var(--accent);font-weight:600}

/* ---- brand lockup ----------------------------------------------------- */
/* The mark is a DRAWN omega (SVG path), not a font glyph — a font Ω rendered
   differently on every OS and shifted baseline per platform. */
.brand{display:flex;align-items:center;gap:.55rem;font-family:var(--font-mono);font-weight:600;letter-spacing:.04em;color:var(--ink);text-decoration:none}
.omega{display:grid;place-items:center;width:28px;height:28px;border-radius:7px;background:var(--accent);color:var(--bg);box-shadow:0 0 0 1px var(--line-strong);flex:none}
.omega svg{width:20px;height:20px;display:block}
.brand-tag{display:block;font-size:.62rem;letter-spacing:.14em;color:var(--ink-faint);font-weight:500;margin-top:.15rem;text-transform:uppercase}

/* ---- buttons — ONE primary style, flat accent ------------------------- */
.btn,.btn-primary,.btn-ghost{display:inline-flex;align-items:center;justify-content:center;gap:.5rem;font-family:var(--font-mono);font-weight:600;font-size:.86rem;letter-spacing:.01em;padding:.62rem 1.05rem;border-radius:var(--r-1);border:1px solid var(--line-strong);background:transparent;color:var(--ink);cursor:pointer;text-decoration:none;transition:transform .12s ease,box-shadow .2s,background .2s,color .2s,border-color .2s}
/* The hover state paints accent text on an --accent-soft fill. Composited over
   --bg that fill resolves to #D3E2E3, and #0A7568 on it measures 4.25:1 — under
   the 4.5:1 a .86rem label needs. The 2026-08-13 audit checked accent on --bg
   (4.93) and never the hover composite. --accent-press (#075A50) is 6.10:1 on
   the same composite; the accent itself stays ONE value, as the header insists,
   and in dark theme --accent-press resolves back to --accent. */
.btn:hover,.btn-ghost:hover{border-color:var(--accent);color:var(--accent-press,var(--accent));background:var(--accent-soft)}
.btn-primary,.btn.primary{background:var(--accent);border-color:transparent;color:var(--accent-ink);box-shadow:0 1px 0 rgba(0,0,0,.06)}
.btn-primary:hover,.btn.primary:hover{transform:translateY(-1px);box-shadow:0 8px 26px -10px var(--accent);background:var(--accent);color:var(--accent-ink)}
.btn.danger{color:var(--bad);border-color:var(--bad)}
.btn.sm{padding:.3rem .6rem;font-size:.74rem}
.btn[disabled],.btn-primary[disabled]{opacity:.5;cursor:default;transform:none;box-shadow:none}

/* ---- plan cards — pricing page, onboarding step, workspace panel ------- */
/* One set of rules for all three surfaces: the module cards are the sales
   argument, and an argument that looks different in three places reads as
   three different products. Rendered by /js/ohmix-plans.js. */
.plan-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:1.1rem;align-items:stretch}
@media (max-width:1000px){.plan-grid{grid-template-columns:1fr;max-width:44rem;margin-inline:auto}}
.plan{display:flex;flex-direction:column;background:var(--surface);border:1px solid var(--line);border-radius:var(--r-3);padding:1.5rem 1.4rem 1.3rem;transition:border-color .18s,box-shadow .18s}
.plan:hover{border-color:var(--line-strong)}
.plan.picked{border-color:var(--accent);box-shadow:0 0 0 1px var(--accent),0 18px 40px -28px var(--accent)}
.plan-head h3{margin:.55rem 0 0;font-size:1.16rem;line-height:1.25;letter-spacing:-.01em;text-wrap:balance}
.plan-lede{margin:.7rem 0 0;color:var(--ink-dim);font-size:.93rem;line-height:1.55}
.plan-points{list-style:none;margin:1.1rem 0 0;padding:0;display:flex;flex-direction:column;gap:.85rem;flex:1}
.plan-points li{display:flex;flex-direction:column;gap:.2rem;padding-left:.9rem;border-left:2px solid var(--accent-soft)}
.plan-points strong{font-size:.9rem;font-weight:650;line-height:1.35}
.plan-points span{font-size:.86rem;color:var(--ink-dim);line-height:1.5}
.plan-foot{margin-top:1.3rem;padding-top:1.05rem;border-top:1px solid var(--line);display:flex;flex-direction:column;gap:.6rem}
.plan-trial{margin:0;font-family:var(--font-mono);font-size:.76rem;letter-spacing:.04em;color:var(--accent);text-transform:uppercase}
.plan-price{margin:0;display:flex;align-items:baseline;gap:.4rem}
.plan-price b{font-size:1.7rem;letter-spacing:-.02em;font-weight:700;font-variant-numeric:tabular-nums}
.plan-price span{font-size:.85rem;color:var(--ink-faint)}
.plan-pick[aria-pressed="true"]{background:var(--accent);border-color:transparent;color:var(--accent-ink)}
.plan-foot .btn{width:100%}

/* The running total. It is deliberately loud about the cap: the dealer should
   see that three modules cost less than the sum before they are asked to pick. */
.plan-total{margin-top:1.3rem;background:var(--bg-2);border:1px solid var(--line);border-radius:var(--r-2);padding:1.05rem 1.2rem;display:flex;flex-wrap:wrap;align-items:center;gap:.8rem 1.4rem}
.plan-total .tl{flex:1;min-width:15rem}
.plan-total .tl b{display:block;font-size:1.5rem;letter-spacing:-.02em;font-variant-numeric:tabular-nums}
.plan-total .tl small{display:block;color:var(--ink-dim);font-size:.85rem;margin-top:.2rem}
.plan-total .strike{text-decoration:line-through;color:var(--ink-faint);font-weight:400;font-size:1rem;margin-left:.45rem}
.plan-total .save{color:var(--good);font-weight:600}

/* Workspace plan panel: same cards, but the number that matters is what is
   left, so the meter carries the weight instead of the price. */
.plan-meters{display:grid;grid-template-columns:repeat(3,1fr);gap:1rem}
@media (max-width:900px){.plan-meters{grid-template-columns:1fr}}
.meter{background:var(--surface);border:1px solid var(--line);border-radius:var(--r-2);padding:1.1rem 1.15rem}
.meter h4{margin:0;font-size:.95rem;display:flex;align-items:center;justify-content:space-between;gap:.6rem}
.meter .tag{font-family:var(--font-mono);font-size:.66rem;letter-spacing:.1em;text-transform:uppercase;padding:.16rem .45rem;border-radius:var(--r-pill);border:1px solid var(--line-strong);color:var(--ink-faint)}
.meter .tag.on{color:var(--accent);border-color:var(--accent);background:var(--accent-soft)}
.meter .tag.out{color:var(--bad);border-color:var(--bad)}
.meter .bar{height:6px;border-radius:var(--r-pill);background:var(--line);margin:.85rem 0 .5rem;overflow:hidden}
.meter .bar i{display:block;height:100%;background:var(--accent);border-radius:inherit}
.meter .bar i.low{background:var(--warn)}
.meter .bar i.none{background:var(--bad)}
.meter .num{font-family:var(--font-mono);font-size:.82rem;color:var(--ink-dim);font-variant-numeric:tabular-nums}
.meter .num b{color:var(--ink)}
