/* xd.css — the Exec Dashboard mocks' OWN layer, on top of portal-lift.css (the athlete
   portal's rules, scoped under `.xd` by lift.mjs).
   ===========================================================================
   THE RULE THIS FILE OBEYS. Nothing here invents a visual idea. Every rule is one of:
     (a) a portal component reused with a ROLE SWAP (red / amber in place of green), the
         launcher-mocks practice (`.pill-stuck.lx-red`);
     (b) composition the portal ships no single rule for — a grid template, a flex row —
         built from the portal's own spacing values;
     (c) a depiction of something that is not portal UI at all (the phone lock screen).
   Sizes and spacing come from the portal's own scale; census.mjs checks every px value
   below against the values app/globals.css already uses.

   NAMING + SCOPE. Every selector begins `.xd`; every class introduced here begins `xd-`.
   census.mjs proves 0 unscoped selectors and 0 collisions between `xd-*` and the lift.
   No drop shadow outside a modal (launcher.css §01.7: a panel with a shadow is a bento
   tile wearing the system's tokens).

   FONTS. The portal declares @font-face with ABSOLUTE /fonts URLs (resolve to the
   filesystem root under file://), so lift.mjs leaves them out and the same faces are
   declared here with paths relative to this sheet. */

@font-face { font-family: "Inter"; src: url("fonts/inter-latin-400-cfb4190f.woff2") format("woff2"); font-weight: 400; font-display: block; }
@font-face { font-family: "Inter"; src: url("fonts/inter-latin-600-6a4ec1e3.woff2") format("woff2"); font-weight: 600; font-display: block; }
@font-face { font-family: "Inter"; src: url("fonts/inter-latin-700-f27e2f0d.woff2") format("woff2"); font-weight: 700; font-display: block; }
@font-face { font-family: "Bio Sans"; src: url("fonts/bio-sans.woff2") format("woff2"); font-weight: 400 600; font-display: block; }
@font-face { font-family: "Bio Sans"; src: url("fonts/bio-sans-bold.woff2") format("woff2"); font-weight: 700; font-display: block; }

/* THE next/font BRIDGE (launcher.css, measured there): g:47 declares
   --font-display: "Bio Sans", var(--font-display-web), …; an UNDEFINED var() with no
   fallback invalidates the whole declaration at computed-value time and every display
   heading silently falls back to Inter. Declaring the variable restores the stack. */
.xd { --font-display-web: "Exo 2"; }

/* Grid items default to min-width:auto; the portal cures wide content the same way
   (`.trackgsec{min-width:0}` g:638, `.setmain .panel{min-width:0}` g:1398). */
.xd .main, .xd .frame, .xd .gsec, .xd .gcell { min-width: 0; }
.xd .xd-grow { flex: 1; }
.xd .xd-sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

/* ── grid templates (composition, (b)) — `.two` (g:535) is 1.6fr 1fr; these are its
      siblings at the column counts these screens need. All collapse at the portal's
      own 940 breakpoint, as `.two` and `.statgrid` do (g:816). ── */
.xd .xd-g2 { grid-template-columns: 1fr 1fr; }
.xd .xd-gwide { grid-template-columns: 1.6fr 1fr; }
.xd .xd-g4 { grid-template-columns: repeat(4, 1fr); }
.xd .xd-gpush { grid-template-columns: 420px 1fr; }
@media (max-width: 940px) {
  .xd .xd-g2, .xd .xd-gwide, .xd .xd-gpush { grid-template-columns: 1fr; }
  .xd .xd-g4 { grid-template-columns: 1fr 1fr; }
}

/* ── the page head. `.hcell` (g:842) for every drill-down; the back control is the
      portal's `.ic` icon button (g:976) leading the text column. ── */
.xd .hcell.xd-head { align-items: center; }
.xd .xd-htext { min-width: 0; flex: 1; }
.xd .hcell .xd-htext h1 { font-family: var(--font-display); font-size: 27px; font-weight: 700; letter-spacing: -.02em; text-wrap: balance; margin: 6px 0 0; }
/* (round 1's Home bell + count, `.xd-hact` / `.xd-bell` / `.xd-count`, removed by D3766
   ruling 14 — Alerts lives in the sidebar and the phone tab bar) */

/* the selector + source-status row — `.calbar` (g:982) holding `.segtab` (g:848) */
.xd .xd-ctl { justify-content: space-between; }

/* ── DeltaChip as a `.statuspill` (g:1415-1418) — role swaps for the two non-green
      tones, the launcher's `.pill-stuck.lx-red` move. ── */
.xd .statuspill.xd-bad { background: color-mix(in oklch, var(--red) 10%, transparent); color: var(--red); }
.xd .statuspill.xd-warn { background: color-mix(in oklch, var(--amber) 14%, transparent); color: var(--amber); }
.xd .xd-delta { white-space: nowrap; }
.xd .xd-arr { font-size: 9.5px; }
.xd .xd-cmp { font-weight: 500; opacity: .8; }

/* the per-cell status dot (HomeCard.tsx:76-79) — `.statuspill .dot` geometry (g:1418) */
.xd .xd-sdot { margin-left: auto; display: inline-flex; }
.xd .xd-sdot .dot { width: 6px; height: 6px; border-radius: 50%; background: var(--green); }
.xd .statk { gap: 8px; }
/* a chip carried inside an uppercase label keeps its own case and tracking — the
   product's "breach · > 0.5%" and "0.36 ratio" are not micro-labels */
.xd .statk .chip-proofs, .xd .statk .statuspill { text-transform: none; letter-spacing: normal; }

/* ── consequence chips. `.chip-proofs` (g:1875) IS the amber pending pill; the
      critical variant swaps --red in. ── */
.xd .chip-proofs.xd-crit { border-color: color-mix(in oklch, var(--red) 34%, transparent); background: color-mix(in oklch, var(--red) 12%, transparent); color: var(--red); }
.xd .side .nav a .badge.xd-crit { background: color-mix(in oklch, var(--red) 18%, transparent); color: var(--red); }
.xd .side .nav a.on .badge.xd-crit { background: color-mix(in oklch, var(--on-green-fill) 18%, transparent); color: var(--on-green-fill); }

/* ══════════════════════════════════════════════════════════════════════════════
   THE ANOMALY CELL — rank 1 on Home. Not a card among cards: a full-width cell
   directly under the head, the only cell on the screen that carries a ground colour.
   Its parts are portal parts: `.reji` (g:1880) as the severity glyph, `.statk` as the
   label, the `.detail .big .n` figure (g:1698, 42px display) in --red, `.chip-proofs`
   for the counts. The ground + left rule is `.tile.attn.active` (g:1651) with the
   --red role swapped in for --amber.
   ══════════════════════════════════════════════════════════════════════════════ */
/* THE TINT IS LAYERED, NOT MIXED. color-mix(in oklch, red 9%, --c-base) interpolates HUE
   by weight: against the near-neutral teal ground (hue 194) a 9% red lands at hue ≈179 —
   a teal tint, measured in the first raster. The portal's own red tints mix with
   `transparent` (`.rejitem` g:1879), which keeps the hue; that tint is laid over --c-base. */
.xd .gcell.xd-alarm { background-color: var(--c-base); background-image: linear-gradient(color-mix(in oklch, var(--red) 9%, transparent), color-mix(in oklch, var(--red) 9%, transparent)); box-shadow: inset 3px 0 0 var(--red); }
/* (round 1 also swapped --red into the Home greeting's glow while a critical was active,
   `.hero.xd-crit`. D3766 ruling 13 replaced the glow with a clean dark-to-green gradient,
   so the greeting no longer turns red; this cell alone carries the alarm.) */
.xd .xd-alarm-in { display: flex; align-items: center; gap: 20px; padding: 18px 22px; text-decoration: none; color: inherit; flex-wrap: wrap; }
.xd .xd-alarm-in .statk { color: var(--red); }
.xd .xd-alarm-fig { font-family: var(--font-display); font-size: 42px; font-weight: 700; line-height: 1; letter-spacing: -.02em; color: var(--red); font-variant-numeric: tabular-nums; }
.xd .xd-alarm-main { flex: 1; min-width: 220px; display: flex; flex-direction: column; gap: 8px; }
.xd .xd-alarm-chips { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.xd .xd-note { font-size: 12.5px; color: var(--fg3); line-height: 1.5; }
.xd .xd-note b { color: var(--fg); font-weight: 600; }
/* the arrow (→) — D3766 ruling 12: in the label row, pushed to its right end, which is the
   panel's top-right corner (the inner edge of `.xd-alarm-in`'s padding). It replaced the
   red status dot that sat there. */
.xd .xd-go { margin-left: auto; color: var(--red); flex-shrink: 0; }
.xd .xd-go svg { width: 18px; height: 18px; display: block; }
.xd .reji.xd-lg { width: 30px; height: 30px; }
.xd .reji.xd-lg svg { width: 15px; height: 15px; }

/* the same treatment, amber, for a BLOCKED source (Acquisition's B-003 block) — one
   rung down the consequence ladder: data withheld, not a breach. */
.xd .gcell.xd-attn { background-color: var(--c-base); background-image: linear-gradient(color-mix(in oklch, var(--amber) 8%, transparent), color-mix(in oklch, var(--amber) 8%, transparent)); box-shadow: inset 3px 0 0 var(--amber); }
.xd .xd-attn .reji { background: color-mix(in oklch, var(--amber) 12%, transparent); color: var(--amber); border-color: color-mix(in oklch, var(--amber) 34%, transparent); }
.xd .xd-attn-in { display: flex; align-items: flex-start; gap: 14px; padding: 16px 20px; flex-wrap: wrap; }
.xd .xd-attn-in .rejmain { min-width: 240px; }
.xd .xd-attn-t { font-family: var(--font-display); font-size: 15.5px; font-weight: 700; color: var(--fg); }
/* the green twin — a ratified default awaiting review (Rules / Push) */
.xd .gcell.xd-okcell { background-color: var(--c-base); background-image: linear-gradient(color-mix(in oklch, var(--green) 6%, transparent), color-mix(in oklch, var(--green) 6%, transparent)); box-shadow: inset 3px 0 0 var(--green); }
.xd .xd-okcell .reji { background: color-mix(in oklch, var(--green) 12%, transparent); color: var(--green-quiet); border-color: color-mix(in oklch, var(--green) 34%, transparent); }
.xd .xd-okcell .xd-attn-t { color: var(--green-quiet); }

/* ── stat cells. `.statcell` / `.statk` / `.statv` / `.statsub` (g:493-527) carry every
      headline; the hero figure takes the 42px rung the portal gives its biggest number. ── */
.xd .statv.xd-hero-v { font-size: 42px; }
/* the Total MRR trend at the cell's width — Sparkline.tsx's own polyline maths at a
   larger box (the product draws it 132x40); no new chart type, no new series. */
.xd .xd-trendbox { margin-top: auto; padding-top: 14px; }
.xd .xd-trendbox .xd-spark { width: 100%; height: 96px; }
.xd .statv.xd-red { color: var(--red); }
.xd .statv.xd-dimv { color: var(--fg2); }
.xd .xd-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.xd .xd-row .xd-spark { margin-left: auto; }
.xd .xd-pair { display: flex; gap: 30px; flex-wrap: wrap; align-items: flex-end; }
.xd .xd-pair > div { display: flex; flex-direction: column; gap: 8px; }
.xd .statsub b { color: var(--fg2); font-weight: 600; }

/* the sparkline (Sparkline.tsx geometry, rail-family stroke) */
.xd .xd-spark { display: block; overflow: visible; flex-shrink: 0; }
.xd .xd-spark .xd-ln { fill: none; stroke: var(--green); stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; vector-effect: non-scaling-stroke; }
.xd .xd-spark .xd-ar { fill: color-mix(in oklch, var(--green) 10%, transparent); }
.xd .xd-spark.xd-neg .xd-ln { stroke: var(--red); }
/* --green measures 3.02:1 against light surfaces (g:1225-1231); the portal swaps
   --green-press in for meaningful light-theme graphics, and so does this line. */
.xd[data-theme="light"] .xd-spark .xd-ln { stroke: var(--green-press); }
.xd[data-theme="light"] .xd-spark.xd-neg .xd-ln { stroke: var(--red); }

/* ── StreamBars as `.mrow` (g:1781-1788). The value column widens to a currency figure
      (the portal's `.mn` is a 26px count column); pending rows take --amber. ── */
.xd .xd-bars { gap: 3px; }
.xd .xd-bars .mrow .mn { width: auto; min-width: 58px; }
.xd .xd-bars .mrow .flag { width: 120px; }
.xd .xd-bars .mrow.xd-pending .flag, .xd .xd-bars .mrow.xd-pending .mn { color: var(--amber); }
.xd .xd-bars .mrow.xd-pending .barf { background: var(--amber); }

/* ── panel rows. `.panel .prow` (g:1406-1412) carries every KPI table; inside a grid cell
      the panel's own border would double the cell hairline, so it is dropped. ── */
.xd .panel.xd-flush { border: 0; background: transparent; }
.xd .xd-kv { font-family: var(--font-display); font-size: 15.5px; font-weight: 600; letter-spacing: -.01em; }
.xd .xd-kv .xd-unit { font-family: var(--font-body); font-size: 12.5px; font-weight: 500; color: var(--fg3); }
.xd .xd-kv.xd-dimv { color: var(--fg3); }
.xd .prow .pr { gap: 10px; }
.xd .prow.xd-block { flex-direction: column; align-items: stretch; }
.xd .xd-lbl { font-size: 10.5px; letter-spacing: .1em; color: var(--fg3); font-weight: 600; }
.xd .xd-pills { display: flex; flex-wrap: wrap; gap: 8px; }
.xd .xd-padded { padding: 16px 20px; }

/* THE EXPANDABLE ROW (D3762 ruling 5) — every Revenue row is a native <details>; the
   summary IS the `.prow`. Open = `.atable tbody tr.arow.pressed` (g:1967-1968): the green
   9% ground and the 2px accent rule are the portal's own "this row is open" state. The
   caret is the affordance that makes "tap a row to expand" visible on a closed row. */
.xd .xd-kd > summary { cursor: pointer; list-style: none; }
.xd .xd-kd > summary::-webkit-details-marker { display: none; }
.xd .xd-kd > summary:hover { background: var(--c-surface); }
.xd .xd-kd > summary:focus-visible { outline: 2px solid var(--green); outline-offset: -2px; }
.xd .xd-kd[open] > summary, .xd .xd-kd[open] > .xd-drill { background: color-mix(in oklch, var(--green) 9%, var(--c-surface)); box-shadow: inset 2px 0 0 var(--green); }
.xd .xd-kd:last-child:not([open]) > summary { border-bottom: none; }
.xd .xd-kd:last-child > .xd-drill { border-bottom: none; }
.xd .xd-caret { display: grid; place-items: center; color: var(--fg3); }
.xd .xd-caret svg { width: 15px; height: 15px; transition: transform .2s var(--ease); }
.xd .xd-kd[open] .xd-caret svg { transform: rotate(180deg); color: var(--fg2); }
.xd .xd-drill { padding: 4px 16px 16px; display: flex; flex-direction: column; gap: 12px; border-bottom: 1px solid color-mix(in oklch, var(--line-soft) 55%, transparent); }
.xd .xd-drill .xd-row { justify-content: space-between; }
.xd .xd-tagline { display: flex; align-items: center; gap: 8px; font-size: 12px; color: var(--fg3); flex-wrap: wrap; }

/* the timestamp foot (DrillDownView.tsx:84-93) — `.lx-foot`'s treatment */
.xd .xd-foot { padding: 14px 20px; font-size: 11.5px; color: var(--fg3); text-align: center; }

/* ── Alert Centre events — `.rejitem` (g:1879-1886) is the critical card; warning swaps
      in --amber, acknowledged drops to the neutral hairline. Consequence by colour AND by
      the glyph's ground, never colour alone: each card also carries its severity word. ── */
.xd .xd-events { padding: 16px 20px; display: flex; flex-direction: column; gap: 9px; }
.xd .rejitem.xd-ev { padding: 14px 16px; gap: 13px; }
.xd .rejitem.xd-warn { border-color: color-mix(in oklch, var(--amber) 34%, transparent); background: color-mix(in oklch, var(--amber) 5%, transparent); }
.xd .rejitem.xd-warn .reji { background: color-mix(in oklch, var(--amber) 12%, transparent); color: var(--amber); border-color: color-mix(in oklch, var(--amber) 34%, transparent); }
.xd .rejitem.xd-done { border-color: var(--line-soft); background: transparent; }
.xd .rejitem.xd-done .reji { background: var(--c-surface); color: var(--fg3); border-color: var(--line-soft); }
.xd .xd-evhead { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
.xd .xd-ev .rejn { font-size: 13.5px; }
.xd .xd-evbody { font-size: 12.5px; color: var(--fg2); line-height: 1.5; margin-top: 8px; }
.xd .xd-ack { display: flex; align-items: center; gap: 6px; font-size: 11.5px; color: var(--fg3); margin-top: 8px; }
.xd .xd-ack svg { width: 13px; height: 13px; }
.xd .xd-plot { margin-top: 10px; border: 1px solid var(--line-soft); background: var(--c-void); padding: 12px 13px; }
.xd .xd-plot .xd-spark { width: 100%; }
.xd .xd-plot .xd-note { margin-top: 6px; font-size: 11.5px; }
.xd .xd-evacts { display: flex; gap: 10px; margin-top: 12px; flex-wrap: wrap; }

/* ── form rows: the editor is `.fld` / `.fl` / `.in` (g:790-795) in `.setgrid` (g:1441);
      the affixed inputs reuse `.in` as the box with the glyph inside it. ── */
.xd .xd-in { display: flex; align-items: center; gap: 8px; }
.xd .xd-in input { all: unset; flex: 1; min-width: 0; color: var(--fg); font-weight: 600; font-size: 13.5px; }
.xd .xd-in .xd-aff { color: var(--fg3); }
.xd .xd-in svg { width: 15px; height: 15px; color: var(--fg3); flex-shrink: 0; }
.xd .xd-full { grid-column: 1 / -1; }
.xd .xd-actions { display: flex; gap: 10px; justify-content: flex-end; }
.xd .chip.xd-sel { background: var(--green-fill); color: var(--on-green-fill); border-color: var(--green-dim); }
.xd .xd-rulecell { padding: 16px 20px; display: flex; flex-direction: column; gap: 14px; }
.xd .panel.xd-editor { padding: 16px; display: flex; flex-direction: column; gap: 14px; }
.xd .xd-ruletop { display: flex; align-items: flex-start; gap: 14px; }
.xd .xd-ruletop .pmain { flex: 1; min-width: 0; }
/* the editor's head row is not a `.prow`, so `.prow .pmain .n` (g:1409) is restated */
.xd .xd-ruletop .n { font-size: 13.5px; font-weight: 600; color: var(--fg); display: flex; align-items: center; gap: 9px; flex-wrap: wrap; }
.xd .xd-ruleform { border-top: 1px solid var(--line-soft); padding-top: 14px; }
.xd .xd-cond { font-size: 11.5px; color: var(--muted); margin-top: 3px; font-variant-numeric: tabular-nums; }
.xd .btn.xd-block { width: 100%; }

/* ── the audit rows — `.panel .prow` with a fixed tabular timestamp column ── */
.xd .xd-ts { flex: 0 0 96px; font-size: 12px; color: var(--fg3); font-variant-numeric: tabular-nums; align-self: flex-start; padding-top: 1px; }
.xd .xd-ip { font-size: 11px; color: var(--muted); margin-top: 3px; font-variant-numeric: tabular-nums; }
.xd .statuspill svg { width: 12px; height: 12px; }
.xd .xd-filters { gap: 9px; }
.xd .mapfilter.xd-ico svg { position: absolute; left: 11px; width: 13px; height: 13px; color: var(--fg3); pointer-events: none; }
.xd .mapfilter.xd-ico select { padding-left: 30px; }
.xd .chip.xd-static { height: 30px; font-size: 12px; cursor: default; }

/* ── the data-pending state (LISA-proposed): `.statv.awaiting` (g:524) carries the em-dash;
      the pill names the census class. The DASHED rule is the portal's structure-not-colour
      mark for an unknown (`.loadbar.lb-unread` g:1236), given to "not recorded yet". ── */
.xd .xd-pendpill { display: inline-flex; align-items: center; gap: 6px; }
.xd .xd-pendpill svg { width: 12px; height: 12px; stroke: currentColor; fill: none; stroke-width: 2; }
.xd .statuspill.xd-dashed { border: 1px dashed var(--event-unknown); background: transparent; }
.xd .mechtag.xd-pendpill { font-size: 11px; padding: 3px 10px; color: var(--fg2); text-transform: none; letter-spacing: normal; font-weight: 600; }
.xd .xd-pending-cell .statsub + .statsub { margin-top: 0; }

/* ── the loading skeleton — admin/loading.tsx:63 (`animate-pulse rounded bg-surface-2`),
      inside the SAME frame/gsec/gcell chain the loaded screen renders (its D1911 cure). ── */
.xd .xd-skel { display: block; border-radius: 4px; background: var(--c-surface-2); animation: xd-pulse 2s cubic-bezier(.4, 0, .6, 1) infinite; }
@keyframes xd-pulse { 50% { opacity: .5; } }
@media (prefers-reduced-motion: reduce) { .xd .xd-skel { animation: none; } }
.xd .xd-skelcell { padding: 16px 20px; display: flex; flex-direction: column; gap: 12px; min-height: 104px; }

/* ── the login (D3762 ruling 2: no hero image, plain) — the portal's own sign-in surface
      as it ships (app/login/page.tsx:83-140): one 420px entry frame (`max-w-[420px]`),
      a centred head cell (`px-7 pt-9 pb-8`, gap-3.5) over the form cell (`px-7 py-7`,
      gap-4), with the frame's corner ticks and seam ticks (g:1898-1912, :2413-2442). ── */
.xd .xd-entry { min-height: 100dvh; display: grid; place-items: center; padding: 24px; }
.xd .xd-entry .entryframe { width: 100%; max-width: 420px; flex: none; }
.xd .xd-entryhead { padding: 36px 28px 32px; display: flex; flex-direction: column; align-items: center; gap: 14px; text-align: center; }
.xd .xd-brandgrp { display: flex; flex-direction: column; align-items: center; gap: 8px; }
.xd .xd-entryhead .xd-wm { height: 24px; width: auto; color: var(--green); display: block; }
.xd .xd-entryhead h1 { font-family: var(--font-display); font-size: 32px; font-weight: 700; letter-spacing: -.02em; line-height: 1.05; margin: 0; }
.xd .xd-entryhead .xd-lead { font-size: 14px; color: var(--fg3); line-height: 1.6; max-width: 300px; }
.xd .xd-form { padding: 28px; display: flex; flex-direction: column; gap: 16px; }
.xd .xd-form form { display: flex; flex-direction: column; gap: 14px; }
.xd .xd-form .xd-small { font-size: 12.5px; color: var(--fg3); line-height: 1.55; }
.xd .xd-form .xd-small a { color: var(--green-quiet); font-weight: 600; text-decoration: none; }
.xd .xd-form .xd-foot2 { display: flex; align-items: center; gap: 8px; font-size: 12px; color: var(--fg3); border-top: 1px solid var(--line-soft); padding-top: 14px; }
.xd .xd-form .xd-foot2 svg { width: 15px; height: 15px; flex-shrink: 0; }
.xd .xd-form .xd-tag { font-size: 11px; color: var(--muted); }
.xd .xd-form .xd-tag b { color: var(--fg3); }
/* the error strip — the portal login's own (app/login/page.tsx:105-107) */
.xd .xd-err { border: 1px solid color-mix(in oklch, var(--red) 40%, transparent); background: color-mix(in oklch, var(--red) 9%, transparent); padding: 12px 16px; font-size: 13.5px; line-height: 1.4; color: var(--red); }
@media (max-width: 940px) {
  .xd .xd-entry { padding: 16px; place-items: start center; }
  .xd .xd-entryhead { padding: 30px 20px 26px; }
  .xd .xd-entryhead h1 { font-size: 28px; }
  .xd .xd-form { padding: 22px 20px; }
}

/* ── Push Preview: the phone is a DEPICTION of iOS, not portal UI ((c)). Ported from
      the product's own lock screen (styles/globals.css:808-941) and kept dark in both
      themes — a lock screen does not follow the dashboard's theme. The app-icon fills
      are the ShredFast app's own colours, literal for the same reason. ── */
.xd .xd-devicecell { padding: 24px 26px; }
.xd .xd-lock { position: relative; border-radius: 28px; overflow: hidden; border: 1px solid var(--line); aspect-ratio: 393 / 740; max-width: 360px; margin: 0 auto; }
.xd .xd-lock .xd-wall { position: absolute; inset: 0; background: #111 url("assets/workout-hero-1600.jpg") center / cover; filter: brightness(.34) saturate(.85); }
.xd .xd-lock .xd-wall::after { content: ""; position: absolute; inset: 0; background: linear-gradient(180deg, rgba(0, 0, 0, .35), rgba(0, 0, 0, .55)); }
.xd .xd-lockin { position: relative; z-index: 1; height: 100%; display: flex; flex-direction: column; padding: 30px 16px 18px; }
.xd .xd-lk { display: grid; place-items: center; color: rgba(255, 255, 255, .8); margin-bottom: 8px; }
.xd .xd-lk svg { width: 22px; height: 22px; }
.xd .xd-ltime { font-size: 64px; font-weight: 700; letter-spacing: -.03em; text-align: center; line-height: 1; color: #fff; }
.xd .xd-ldate { font-size: 14px; font-weight: 600; text-align: center; color: rgba(255, 255, 255, .85); margin-top: 6px; }
.xd .xd-notifs { margin-top: auto; display: flex; flex-direction: column; gap: 9px; }
.xd .xd-notif { background: rgba(36, 38, 43, .72); border: 1px solid rgba(255, 255, 255, .08); border-radius: 18px; padding: 11px 13px; display: flex; gap: 10px; }
.xd .xd-notif .xd-nico { width: 34px; height: 34px; border-radius: 9px; background: #4FFF8B; color: #06210f; display: grid; place-items: center; flex: none; padding: 6px; }
.xd .xd-notif.xd-crit .xd-nico { background: #FF6B6B; color: #fff; }
.xd .xd-notif .xd-nico svg { width: 100%; height: 100%; }
.xd .xd-nbody { flex: 1; min-width: 0; }
.xd .xd-nhead { display: flex; justify-content: space-between; gap: 8px; font-size: 12px; }
.xd .xd-napp { font-weight: 700; color: #fff; }
.xd .xd-ntime { color: rgba(255, 255, 255, .6); font-weight: 500; }
.xd .xd-nsev { font-size: 9.5px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: #E8B54A; }
.xd .xd-notif.xd-crit .xd-nsev { color: #FF6B6B; }
.xd .xd-nmsg { font-size: 12.5px; color: rgba(255, 255, 255, .9); line-height: 1.4; margin-top: 2px; }
.xd .xd-policy { padding: 24px 26px; display: flex; flex-direction: column; gap: 14px; }
.xd .panel.xd-pp { padding: 16px 20px; display: flex; flex-direction: column; gap: 10px; }
.xd .xd-pt { font-family: var(--font-display); font-size: 15.5px; font-weight: 700; letter-spacing: -.01em; display: flex; align-items: center; gap: 9px; }
.xd .xd-pp p { font-size: 13px; color: var(--fg2); line-height: 1.55; margin: 0; }
.xd .xd-pp p b { color: var(--fg); font-weight: 600; }
.xd .xd-ex { display: flex; gap: 10px; align-items: flex-start; font-size: 12.5px; color: var(--fg2); line-height: 1.5; }
.xd .xd-ex b { color: var(--fg); }
.xd .xd-callout { display: flex; align-items: flex-start; gap: 14px; border: 1px solid color-mix(in oklch, var(--green) 34%, transparent); background: color-mix(in oklch, var(--green) 6%, transparent); padding: 16px 20px; }
.xd .xd-callout .reji { background: color-mix(in oklch, var(--green) 12%, transparent); color: var(--green-quiet); border-color: color-mix(in oklch, var(--green) 34%, transparent); }
.xd .xd-callout .xd-attn-t { color: var(--green-quiet); }
.xd .xd-callout .xd-note { margin-top: 3px; }
.xd .xd-callout { flex-wrap: wrap; }
.xd .xd-callout .rejmain { min-width: 200px; }
@media (max-width: 940px) {
  .xd .xd-devicecell, .xd .xd-policy { padding: 18px 16px; }
}

/* ── the modal overlay (Add new rule) — `.mscrim` + `.modal` + `.mcard` (g:774-787)
      at the portal's wider 560px step (`.mcard.mwide`, g:930). ── */
.xd .mcard.xd-wide { width: 560px; }
.xd .mbody .setgrid { gap: 14px; }
.xd .mfoot .xd-tag { font-size: 11px; color: var(--muted); margin-right: auto; align-self: center; }

/* ── narrow-width glue ── */
/* the portal's ≤700 craft pass pins a row's `.statuspill` top-right (g:2545); a rule row's
   enable switch is the same kind of row-level state, so it takes the same pin. */
@media (max-width: 700px) {
  .xd .panel .prow .pr .tgl { position: absolute; top: 16px; right: 16px; }
}
/* the portal's ≤700 craft pass gives `.tools` a full row (g:2549); a lone icon control
   (Sort) stays in the head row instead, beside the title it acts on. */
@media (max-width: 700px) {
  .xd .hcell.xd-head:not(.xd-headwrap) { flex-wrap: nowrap; }
  .xd .hcell.xd-head:not(.xd-headwrap) .tools { width: auto; margin-left: auto; }
}
@media (max-width: 940px) {
  .xd .xd-ctl { flex-wrap: wrap; }
  .xd .xd-ts { flex-basis: 100%; }
  .xd .panel .prow.xd-audit { flex-wrap: wrap; }
  .xd .xd-bars .mrow .flag { width: 104px; }
}
@media (max-width: 560px) {
  .xd .setgrid { grid-template-columns: 1fr; }
  .xd .xd-g4 { grid-template-columns: 1fr; }
  .xd .mfoot { flex-wrap: wrap; }
  .xd .mfoot .xd-tag { flex-basis: 100%; }
  .xd .hero.xd-homehead { padding: 24px 20px; }
}

/* ══════════════════════════════════════════════════════════════════════════════
   ROUND 2 (D3762) — the Kage's rulings of 2026-10-01 13:03 GST.
   ══════════════════════════════════════════════════════════════════════════════ */

/* ── THE PHONE TAB BAR (ruling 6) — composition (b). The portal ships no bottom bar, so
      this is built from the rail's own parts: the `.nav a` row's ink, its "on" state
      (`.nav a.on` g:354 — green fill, on-green ink, a 2px accent rule, here on the TOP edge
      because the bar runs horizontally), the rail glyph family, and the `.mobar`'s ground
      and hairline (g:736) mirrored to the bottom. Hidden above the portal's 940
      breakpoint, where the rail is always visible. ── */
.xd .xd-tabbar { display: none; }
@media (max-width: 940px) {
  .xd .main { padding-bottom: calc(52px + env(safe-area-inset-bottom)); }
  .xd .xd-tabbar { display: grid; grid-template-columns: repeat(5, 1fr); position: fixed; left: 0; right: 0; bottom: 0; z-index: 56; background: var(--c-base); border-top: 1px solid var(--line-soft); padding-bottom: env(safe-area-inset-bottom); }
}
.xd .xd-tab { position: relative; display: flex; flex-direction: column; align-items: center; gap: 3px; padding: 7px 0 8px; font-family: var(--font-body); font-size: 10.5px; font-weight: 600; color: var(--fg3); text-decoration: none; background: transparent; border: 0; cursor: pointer; }
.xd .xd-tab svg { width: 18px; height: 18px; }
.xd .xd-tab.on { background: var(--green-fill); color: var(--on-green-fill); box-shadow: inset 0 2px 0 var(--green); }
.xd .xd-tl { line-height: 13px; }
/* the count: solid red while a critical is active — the treatment round 1 gave the Home
   bell's count (the bell itself was removed in round 3, D3766 ruling 14); this is the badge
   a phone reader's thumb lands on */
.xd .xd-tbadge { position: absolute; top: 3px; left: calc(50% + 5px); min-width: 16px; height: 16px; padding: 0 5px; border-radius: 60px; display: grid; place-items: center; font-size: 10px; font-weight: 700; background: color-mix(in oklch, var(--amber) 20%, transparent); color: var(--amber); font-variant-numeric: tabular-nums; }
.xd .xd-tbadge.xd-crit { background: var(--red); color: var(--on-red); }

/* ── THE RETENTION CURVE (ruling 8). One series: the line wears the trend's own green
      (--green-press on light, as `.xd-spark`), no area fill, 10px
      markers with a 2px surface ring, a direct label on every point, a recessive
      quarter grid. The pending checkpoint is a hollow amber marker on a dashed segment
      — the product's own amber row, carried by shape and dash, not colour alone. ── */
.xd .xd-curve { display: grid; grid-template-columns: 40px 1fr; grid-template-rows: 180px auto; column-gap: 10px; row-gap: 10px; padding-top: 24px; }
.xd .xd-cy { position: relative; }
.xd .xd-cy span { position: absolute; right: 0; transform: translateY(-50%); font-size: 11px; color: var(--fg3); font-variant-numeric: tabular-nums; }
.xd .xd-cplot { position: relative; }
.xd .xd-cplot svg { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
.xd .xd-cgrid line { stroke: var(--line-soft); stroke-width: 1; vector-effect: non-scaling-stroke; }
.xd .xd-cgrid line.xd-cbase { stroke: var(--line); }
.xd .xd-cln { fill: none; stroke: var(--green); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; vector-effect: non-scaling-stroke; }
.xd .xd-cln.xd-cdash { stroke: var(--amber); stroke-dasharray: 5 5; }
.xd[data-theme="light"] .xd-cln { stroke: var(--green-press); }
.xd[data-theme="light"] .xd-cln.xd-cdash { stroke: var(--amber); }
.xd .xd-cpt { position: absolute; width: 10px; height: 10px; border-radius: 50%; transform: translate(-50%, -50%); background: var(--green); box-shadow: 0 0 0 2px var(--c-base); }
.xd[data-theme="light"] .xd-cpt { background: var(--green-press); }
.xd .xd-cpt.xd-cpend, .xd[data-theme="light"] .xd-cpt.xd-cpend { background: var(--c-base); border: 2px solid var(--amber); }
.xd .xd-cval { position: absolute; transform: translate(-50%, calc(-100% - 9px)); font-size: 12.5px; font-weight: 600; color: var(--fg); font-variant-numeric: tabular-nums; white-space: nowrap; }
.xd .xd-cx { grid-column: 2; position: relative; height: 16px; }
.xd .xd-cx span { position: absolute; transform: translateX(-50%); font-size: 11.5px; color: var(--fg3); white-space: nowrap; }

/* ── HQ ATHLETE REACH (ruling 9). The total line is a strip of five figures in the team's
      collection order, Accounts reached carrying the weight (it is the ranking key) by
      size and the 2px accent rule, never by colour on the text. The table is the
      portal's roster table (`.tcell` + `.atable` + `th.so` + `.ar`, g:1918-1923) with
      plain rows: nothing in a row opens, so no `.arow` pointer and no hover ground. ── */
.xd .ptitle .xd-sample { text-transform: none; }
.xd .xd-reachhead { display: flex; flex-direction: column; gap: 12px; }
.xd .xd-rtl { margin-top: 4px; }
.xd .xd-reachsum { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 1px; background: var(--line-soft); border: 1px solid var(--line-soft); }
.xd .xd-rs { background: var(--c-base); padding: 12px 14px; display: flex; flex-direction: column; gap: 6px; }
.xd .xd-rs .statv { font-size: 21px; }
.xd .xd-rs.xd-rs-hl { box-shadow: inset 0 2px 0 var(--green); }
.xd .xd-rs.xd-rs-hl .statv { font-size: 27px; }
.xd .xd-left { text-align: left; }
.xd .atable.xd-reach { min-width: 720px; }
.xd .xd-reach tbody tr, .xd .xd-plat tbody tr { border-bottom: 1px solid color-mix(in oklch, var(--line-soft) 55%, transparent); }
.xd .xd-reach tbody tr:last-child, .xd .xd-plat tbody tr:last-child { border-bottom: none; }
.xd .xd-reach tbody th { padding: 11px 20px; font-weight: 600; color: var(--fg); text-align: left; white-space: nowrap; }
.xd .xd-reach td { color: var(--fg2); }
.xd .xd-reach .xd-num { text-align: right; }
.xd .xd-reach .xd-rk { color: var(--fg3); }
.xd .xd-reach .xd-rv { color: var(--fg); font-weight: 600; }
.xd .xd-reach th.so:focus-visible { outline: 2px solid var(--green); outline-offset: -2px; }
/* the reach share under the ranking figure — the coverage bar (`.mrow .bar/.barf`
   g:1785-1786) at the thickness a table row can carry */
.xd .xd-rbar { display: block; height: 4px; margin-top: 6px; margin-left: auto; width: 96px; background: var(--c-surface-2); overflow: hidden; }
.xd .xd-rbarf { display: block; height: 100%; background: linear-gradient(90deg, color-mix(in oklch, var(--green) 50%, var(--c-surface)), var(--green)); }
@media (max-width: 940px) {
  .xd .xd-reachsum { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .xd .xd-rs:last-child { grid-column: 1 / -1; }
}
/* a phone restacks each row into a card: rank + page on the first line, the five figures
   below under their own labels, three to a line — so the ranking figure is never off
   screen (the first 390 raster scrolled it out of view). The header row stays for
   assistive tech, off screen; re-ranking is a desktop affordance, so its hint hides. */
@media (max-width: 700px) {
  .xd .atable.xd-reach { min-width: 0; }
  .xd .xd-reach thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
  .xd .xd-reach, .xd .xd-reach tbody { display: block; }
  .xd .xd-reach tbody tr { display: flex; flex-wrap: wrap; align-items: baseline; row-gap: 12px; padding: 14px 16px; }
  .xd .xd-reach tbody td, .xd .xd-reach tbody th { padding: 0; }
  .xd .xd-reach tbody .xd-rk { flex: 0 0 26px; }
  .xd .xd-reach tbody th.xd-pg { flex: 1 1 calc(100% - 26px); }
  .xd .xd-reach tbody td.xd-num { flex: 0 0 33.333%; text-align: left; }
  .xd .xd-reach .xd-rbar { margin-left: 0; }
  .xd .xd-deskonly { display: none; }
}

/* ── THE PIPELINE AS A PLAIN LIST (ruling 10): no pill box, no fill, no pointer — text in
      a grid, each with a decorative --dim dot (the portal's DECORATIVE-only ink). ── */
.xd .xd-plainlist { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 10px 24px; }
.xd .xd-plainlist li { display: flex; align-items: center; gap: 10px; font-size: 13.5px; color: var(--fg2); cursor: default; }
.xd .xd-plainlist li::before { content: ""; width: 4px; height: 4px; border-radius: 50%; background: var(--dim); flex-shrink: 0; }

/* ── PLATFORMS (ruling 11) — the portal's `.atable` at its natural width; at ≤700 each
      row restacks into a two-column card with its own field labels (`.xd-ml`), and the
      header row is kept for assistive tech but taken off screen. ── */
.xd .atable.xd-plat { min-width: 0; }
.xd .xd-plat td { vertical-align: top; }
.xd .xd-plat td.xd-pv, .xd .xd-plat td.xd-pd { white-space: nowrap; }
.xd .xd-plat .n { font-size: 13px; font-weight: 600; color: var(--fg); }
.xd .xd-plat .d { font-size: 11.5px; color: var(--muted); margin-top: 3px; line-height: 1.45; }
.xd .xd-plat .xd-pdv { font-size: 13.5px; font-weight: 600; color: var(--fg); }
.xd .xd-repo { display: flex; align-items: center; gap: 6px; font-size: 12.5px; font-weight: 600; color: var(--green-quiet); text-decoration: none; white-space: nowrap; }
.xd .xd-repo + .xd-repo { margin-top: 6px; }
.xd .xd-repo:hover { text-decoration: underline; }
.xd .xd-repo svg { width: 13px; height: 13px; flex-shrink: 0; }
.xd .xd-ml { display: none; }
@media (max-width: 700px) {
  .xd .xd-plat thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
  .xd .xd-plat, .xd .xd-plat tbody { display: block; }
  .xd .xd-plat tbody tr { display: grid; grid-template-columns: 1fr 1fr; gap: 12px 14px; padding: 14px 16px; }
  .xd .xd-plat td { padding: 0; }
  .xd .xd-plat td.xd-pn, .xd .xd-plat td.xd-prepo { grid-column: 1 / -1; }
  .xd .xd-ml { display: block; padding-bottom: 4px; font-size: 10px; letter-spacing: .12em; text-transform: uppercase; color: var(--fg3); font-weight: 600; }
}

/* ── narrow-width glue for the expandable rows: the portal's ≤700 craft pass pins a row's
      pill top-right (g:2545); the caret pins bottom-right, beside the value line. ── */
@media (max-width: 700px) {
  .xd .xd-kd > summary .xd-caret { position: absolute; right: 16px; bottom: 16px; }
}

/* ══════════════════════════════════════════════════════════════════════════════
   ROUND 3 (D3766) — the Kage's rulings of 2026-10-01 13:47 GST.
   ══════════════════════════════════════════════════════════════════════════════ */

/* ── THE GREETING BAND (ruling 13): a clean dark-to-green gradient.
   WHY ROUND 2 READ MUDDY — two faults, both measured in the browser:
   (1) the portal's `.hero` (g:394) writes its glow with the `background` SHORTHAND, which
       also resets background-color to transparent. The hero cell therefore drops the
       `.gcell` ground (g:375) and the frame's hairline colour shows through it
       (`.frame`/`.gsec` are painted --line-soft so their 1px gaps draw the grid, g:372-373):
       a flat grey band, lighter than every cell beneath it. The athlete portal's own
       greeting carries the same fault.
   (2) round 1 swapped --red into that glow while a critical was active (`.hero.xd-crit`);
       a red wash over the grey is the brown.
   THE PORTAL'S OWN HERO GRADIENT is that glow — an 8% --green radial at the top-left
   corner. Lifted as it ships, it reproduces fault (1), and 8% never reaches the green
   family the ruling names. So the band is BUILT from the portal's own tokens instead:
     · an OPAQUE ground, --c-base (the cell ground every other Home cell stands on);
     · a left-to-right gradient from --c-base (near-black, oklch .172) to --green-fill
       (oklch .30 .075 153 — the portal's dark green fill: the active nav row, the avatar);
     · interpolated IN OKLCH. Both ends sit at hue 152/153, so the path holds its hue and
       only lightness and chroma climb: there is no grey or brown midpoint. The first
       declaration is the fallback for an engine without gradient interpolation spaces:
       the same path as three stops, the midpoint mixed in OKLCH by color-mix.
   The greeting sits on the dark end; the empty right side (the bell and the "LP" square are
   gone) carries the colour. Text contrast is measured over the rendered band by census.mjs
   (R13), at the band's lightest point. ── */
.xd .hero.xd-homehead {
  background-color: var(--c-base);
  background-image: linear-gradient(90deg, var(--c-base), color-mix(in oklch, var(--c-base), var(--green-fill)), var(--green-fill));
  background-image: linear-gradient(in oklch 90deg, var(--c-base), var(--green-fill));
}
/* The light twin, the same move in the light palette: near-white --c-base into a pale
   marine teal (the light theme's green family, --green #04998f), mixed in OKLCH. The teal
   end stops at 12% because the date line is set in the theme's teal ink (--green-quiet,
   #027770, 4.77:1 on --c-void): a deeper end would take that line under AA. */
.xd[data-theme="light"] .hero.xd-homehead {
  background-image: linear-gradient(90deg, var(--c-base), color-mix(in oklch, var(--c-base), color-mix(in oklch, var(--green) 12%, var(--c-base))), color-mix(in oklch, var(--green) 12%, var(--c-base)));
  background-image: linear-gradient(in oklch 90deg, var(--c-base), color-mix(in oklch, var(--green) 12%, var(--c-base)));
}

/* ── THE SIGN-OUT SEPARATOR (ruling 15): a hairline above
   "Sign out", in every frame's sidebar and the phone drawer. The token is the portal's own
   hairline, --line-soft — the same rule the portal draws above the identity block directly
   over it (`.who`, g:356), so the account block now reads as one framed unit. ── */
.xd .side .signout { border-top: 1px solid var(--line-soft); }
