/* ═══════════════════════════════════════════════════════════════════════
   RCOS Online — design system.

   An aviation operations and compliance console, not a dashboard product.
   Colour is information: navy is structure, blue is action, teal is the
   single accent (focus, current position, live emphasis), and the five
   status colours are reserved exclusively for status. Nothing here is
   decorative — every tint on this page means something an operator or an
   authority reviewer has to act on.

   Two rules govern the whole file:
     1. Every colour, size, space and radius comes from a token below.
     2. Direction is expressed with logical properties, never left/right,
        because the Arabic UI ships with dir="rtl" on <html> and there is
        no mirror stylesheet.
   ═══════════════════════════════════════════════════════════════════════ */


/* ══ TOKENS ═══════════════════════════════════════════════════════════ */

:root{
  --navy-900:#0A1A30; --navy-800:#11294A; --navy-700:#1A3A66; --navy-600:#234A80;
  --blue-600:#2660A8; --blue-500:#3277C4; --blue-100:#E3EDF9;
  --teal-700:#0A6E70; --teal-600:#0E8A8C; --teal-500:#14A3A5; --teal-100:#DFF2F2;
  --ink-900:#0F1720; --ink-700:#28323F; --ink-600:#3D4855; --ink-500:#5A6573; --ink-400:#7C8794;
  --line-300:#CFD7E1; --line-200:#DFE5EC; --line-100:#EDF1F5;
  --surface:#FFFFFF; --surface-2:#F7F9FC;

  /* ── PHASE C6 — the approved global colour identity (Direction B, PO
     final ruling, 30 Aug 2026). RCOS's primary identity is a confident
     aviation blue; the retired dark navy remains ONLY as dark-neutral
     text (headings, values, data), never as brand or interactive colour.
     Values are the ruling's tokens verbatim — do not re-derive them.
       primary      #1F5FB8  filled controls, brand, hero fills (white text 6.20:1)
       hover        #1B54A4  · active #17478B
       soft         #EAF2FE  hover/selected washes
       nav          #FFFFFF bar · #D9E6F8 hairline · #E7F0FE active chip
       interactive  #2266CC  links and link-styled text (5.22:1 on the tint)
       icon accent  #2F80ED  icons and large accents ONLY — never small
                             white-text controls (3.87:1 is icon-grade)
       teal         #14A3A5  unchanged, the single live accent
       focus        #2F80ED
       page tint    #F6FAFF                                              */
  --pri-600:#1F5FB8; --pri-700:#1B54A4; --pri-800:#17478B;
  --pri-soft:#EAF2FE;
  --nav-hairline:#D9E6F8; --nav-active:#E7F0FE;
  --link-600:#2266CC;
  --accent-ic:#2F80ED;
  --bg:#F6FAFF;
  --st-ready-fg:#0E6B3F; --st-ready-bg:#E6F4EC; --st-ready-line:#B9DEC9;
  --st-attention-fg:#8A5A00; --st-attention-bg:#FDF3E2; --st-attention-line:#EDD6A8;
  --st-blocked-fg:#94231F; --st-blocked-bg:#FBEAE9; --st-blocked-line:#EFC4C1;
  --st-progress-fg:#1D4E86; --st-progress-bg:#E8F0FA; --st-progress-line:#C2D6ED;
  --st-idle-fg:#4B5563; --st-idle-bg:#F1F3F6; --st-idle-line:#DBE0E7;
  /* PHASE C6 — focus moved off the teal accent onto the ruling's focus
     blue, so the accent stays reserved for live emphasis. */
  --focus:#2F80ED;

  /* ── PHASE C (Batch C1) — elevation & shape tokens ─────────────────────
     Approved Phase C foundation (PO final visual-direction ruling, 29 Aug
     2026). Two elevation levels only: level 1 for standard cards/tiles,
     level 2 for menus/dialogs and hover emphasis. Nothing decorative. */
  --shadow-1:0 1px 2px rgba(10,26,48,.05), 0 2px 8px rgba(10,26,48,.06);
  --shadow-2:0 4px 10px rgba(10,26,48,.10), 0 10px 28px rgba(10,26,48,.12);
  --r-pill:999px;

  /* ── the UI typeface ───────────────────────────────────────────────────
     Calibri is the Program Owner's preferred UI face and is asked for first,
     for English and for Arabic alike — Calibri carries both scripts, so a
     machine that has it renders the whole product, both languages, in one
     family.

     NO FONT FILE IS SHIPPED. There is no @font-face here, no webfont, no CDN
     and no network request for type anywhere in this product. Calibri is
     licensed with Windows and Office and may not be packaged, embedded or
     redistributed, so it is used if and only if the operating system already
     has it installed. This is a licensing constraint, deliberately met, not
     an omission — and the stack below is written so the product is complete
     and visually stable on a machine that has never seen Calibri.

     The fallbacks, in order and for a reason:
       Carlito      metric-compatible with Calibri, free, and already present
                    on most Linux desktops and CI images. Same set widths, so
                    a Linux operator gets the intended measure with no file
                    added here.
       Segoe UI     Windows without Office. Carries Arabic.
       system-ui /  the platform UI face on macOS, iOS, Android and ChromeOS.
       -apple-system
       Roboto, Helvetica Neue
                    Latin-only faces; CSS falls through them per character,
                    so an Arabic string never stops here.
       Noto Sans Arabic, Geeza Pro, Dubai, Tahoma
                    the realistic Arabic UI faces, named explicitly and ahead
                    of Arial and of the generic keyword, so an Arabic screen
                    can never land on a serif or on a face with no Arabic
                    coverage. Arabic matters as much as English here.

     DOCUMENT GENERATION IS NOT AFFECTED BY THIS LINE. The frozen DOCX
     generator carries its own controlled document typography and is a
     separate, governed design concern; nothing in this stylesheet reaches
     it. Do not "make them consistent" — they are deliberately not. */
  --font-ui:Calibri,Carlito,"Segoe UI",system-ui,-apple-system,BlinkMacSystemFont,Roboto,"Helvetica Neue","Noto Sans Arabic","Geeza Pro","Dubai",Tahoma,Arial,sans-serif;

  /* Unchanged, and it stays unchanged: project ids, document ids, hashes,
     coordinates, rule references and ISO dates are set in this stack and
     nowhere else. Calibri never appears here. */
  --font-mono:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;

  /* ── the scale, compensated for Calibri ────────────────────────────────
     Measured, not assumed (1ex per em, as the engine resolves it):

       Calibri / Carlito  0.4775      DejaVu Sans      0.5469
       Segoe UI           0.50        Liberation Sans  0.5283
       SF (macOS)         ~0.52       FreeSans         0.524

     Calibri sets a smaller x-height than every face in the outgoing stack,
     and a narrower one again, so keeping the old px values would have made
     the whole interface read a step smaller and — a smaller x-height inside
     the same 1.55 leading — noticeably looser. Two deliberate compensations,
     and they are the compensation; the font-size-adjust below is a
     correction on top of them, not a substitute for them:

       1. every step of the scale is up ~3.5% (15→15.5, 13.5→14, 12.5→13,
          11.5→12, 17→17.5, 20→21, 24→25, 30→31). 0.4775 × 15.5px = 7.40px
          of x-height against the outgoing Segoe UI's 0.50 × 15px = 7.50px,
          so Calibri alone now lands within 1.3% of the old rendering even in
          a browser that implements no adjustment at all;
       2. body leading is down from 1.55 to 1.5 (see html, body below), which
          is where the "looser" half of the problem was.

     The two lifted headline steps (20→21, 24→25, 30→31) are lifted a little
     harder than the body, because a narrow face loses more at display size
     than at reading size. */
  --fs-xs:12px; --fs-sm:13px; --fs-md:14px; --fs-base:15.5px;
  --fs-lg:17.5px; --fs-xl:21px; --fs-2xl:25px; --fs-3xl:31px;

  /* The x-height every UI face is held to. 0.48 × 15.5px = 7.44px, which is
     the outgoing Segoe UI rendering to within 1%. What it actually buys is
     the FALLBACKS, not Calibri: measured against this target Calibri moves
     by +0.5% (it is already right, from the scale above), but DejaVu Sans is
     pulled in by 12% and Liberation Sans by 9%. Without it the same screen
     is a tenth larger on a Linux operator's machine than on the Program
     Owner's, which is exactly the instability this brief is about. */
  --x-height:0.48;

  --sp-1:4px; --sp-2:8px; --sp-3:12px; --sp-4:16px; --sp-5:20px; --sp-6:24px; --sp-7:32px; --sp-8:40px; --sp-9:56px;
  --r-1:3px; --r-2:5px; --r-3:8px;
  --shadow-1:0 1px 0 rgba(16,24,40,.04), 0 1px 2px rgba(16,24,40,.06);
  --shadow-2:0 2px 4px rgba(16,24,40,.05), 0 10px 24px rgba(16,24,40,.06);
  --topbar-h:58px; --page-max:1180px;

  /* The inset of a plate. Named because three things have to agree with it
     exactly: the plate's own padding, the sticky save bar that bleeds to the
     plate's edge, and the next-question marker that bleeds the other way. It
     is redefined once, at the tablet breakpoint. */
  --card-pad:var(--sp-6);

  /* ── border hierarchy ──────────────────────────────────────────────────
     Three deliberate levels, so that a border can say how important the
     thing it encloses is. Before this every line in the product was one of
     two nearly identical greys and nothing read as more structural than
     anything else.

       --edge-strong  an edge you are meant to see and often to act on: form
                      controls, the rule under a table head, the outline of a
                      raised surface, a dashed "not built" outline.
       --edge         a separation between groups: the rule under a section
                      heading, <hr>, a fieldset, .sep.
       --hairline     structure inside one group: table rows, list rows, the
                      line between two interview questions. Never an outline.

     One rule constrains the hierarchy: THE BOUNDARY OF AN INTERACTIVE
     CONTROL NEVER GOES BELOW --edge-strong. Fields, .opt answers, .btn.ghost
     and the designer's palette buttons all stay where they were, because a
     control's outline is the thing that says it can be operated and the
     refinement is not allowed to spend that. Everything that stepped down a
     level is a read-out, a separator or a group edge.

     Nothing else in this file states a line colour directly. */
  --edge-strong:var(--line-300);
  --edge:var(--line-200);
  --hairline:var(--line-100);
}

/* Contrast notes, measured against the tokens above (WCAG 2.1 ratios):
     • Every --st-*-fg on its own --st-*-bg clears 4.5:1 (lowest is
       attention at 5.39:1), so no status token needed adjusting.
     • --ink-400 reaches only 3.65:1 on --surface. It is therefore used for
       non-text marks and disabled affordances only — every piece of
       secondary body text uses --ink-500 (5.93:1 on white, 5.37:1 on --bg).
     • --teal-600 reaches only 4.17:1 on white, so teal *text* always uses
       --teal-700 (6.04:1). --teal-600 is used as a fill behind white. */

/* Two derived names the issued block does not carry. Both appear in a dozen
   places and must not be allowed to drift apart, so they are named rather
   than written out:
     --on-navy is the foreground on any navy surface (topbar, primary button,
       hero cell). It resolves to the same white as --surface; it is a
       separate name because it is a foreground role, not a panel.
     --overlay-* are the translucent whites used for hover and current state
       on navy. The issued palette has no alpha values, and a solid tint here
       would have to be re-picked for every navy step. */
:root{
  --on-navy:var(--surface);
  --overlay-1:rgba(255,255,255,.08);
  --overlay-2:rgba(255,255,255,.10);
  --overlay-3:rgba(255,255,255,.12);
  --overlay-line:rgba(255,255,255,.32);
}

/* Legacy token aliases. signin.html carries its own <style> block that
   still resolves var(--navy) and var(--muted), and it loads this file for
   the rest of its styling. Dropping these names would break that page, so
   they are kept as one-line aliases onto the new scale rather than as a
   second palette. Nothing in this file should use them. */
:root{
  --navy:var(--navy-800);
  --navy-deep:var(--navy-900);
  --ink:var(--ink-900);
  --muted:var(--ink-500);
  --line:var(--line-200);
  --card:var(--surface);
  --ok:var(--st-ready-fg);
  --warn:var(--st-attention-fg);
  --stop:var(--st-blocked-fg);
  --radius:var(--r-2);
  --shadow:var(--shadow-1);
}


/* ══ RESET & BASE ═════════════════════════════════════════════════════ */

*, *::before, *::after{ box-sizing:border-box; }

html{
  color-scheme:light;
  -webkit-text-size-adjust:100%;
}

html, body{
  margin:0;
  background:var(--bg);
  color:var(--ink-900);
  font-family:var(--font-ui);
  font-size:var(--fs-base);
  /* Down from 1.55. Calibri sets a smaller x-height inside the same leading,
     which is read as loose rather than as airy; the air the interface gained
     is between groups, where it means something, not between lines. */
  line-height:1.5;
  /* Holds the x-height steady across Calibri and every fallback. Inherited,
     and switched off again on the monospaced runs below. */
  font-size-adjust:var(--x-height);
  -webkit-font-smoothing:antialiased;
}

/* The product is read on 24" operations displays and on tablets in the
   field; never let a long project id or a coordinate blow the layout out. */
img, svg, canvas, video{ max-width:100%; }

hr{ border:0; border-block-start:1px solid var(--edge); margin:var(--sp-6) 0; }

code, pre, kbd, samp{ font-family:var(--font-mono); font-size:var(--fs-sm); }
pre{ overflow:auto; background:var(--surface-2); border:1px solid var(--edge);
  border-radius:var(--r-2); padding:var(--sp-3); }

/* Every monospaced run in the product, gathered once. The mono stack is not
   changing and is already internally consistent, so the UI x-height
   normalisation is switched off here: a project id, a rule reference or a
   coordinate renders at exactly the size it is asked for, whichever mono face
   the machine resolves. This is the only reason the list exists — no mono
   family, size or colour is set here. */
code, pre, kbd, samp,
.mono, .pid, .qid, .mid, .bid,
.trace .step, .trace .rule, .findings .fq, .dz-find .c,
.jrny .jn{ font-size-adjust:none; }


/* ══ TYPOGRAPHY ═══════════════════════════════════════════════════════ */

/* Calibri is already a narrow face; the -.01em tracking the old stack needed
   to stop a wide grotesque from sprawling now closes the headings up. It is
   dropped rather than reversed. */
h1, h2, h3, h4{ color:var(--navy-900); font-weight:650; letter-spacing:normal; }
h1{ font-size:var(--fs-2xl); margin:0 0 var(--sp-1); line-height:1.22; }

/* h2 is a section rule, not a headline — it labels a group, so it sits at
   body scale in small caps rather than shouting above the content. It is now
   the main thing that establishes a group: where a group used to be told by
   its border, it is told by this label, the hairline under it, and the air
   above it. */
h2{ font-size:var(--fs-sm); margin:0 0 var(--sp-4); letter-spacing:.08em;
  text-transform:uppercase; color:var(--ink-600); font-weight:700; }
h3{ font-size:var(--fs-md); margin:0 0 var(--sp-2); }

p{ margin:0 0 var(--sp-3); }

/* C6 — interactive text is the ruling's interactive blue (5.22:1 even on
   the page tint), darkening into the primary family on hover. */
a{ color:var(--link-600); text-underline-offset:2px; }
a:hover{ color:var(--pri-700); }

b, strong{ font-weight:650; }

.lede{ color:var(--ink-500); margin:0; font-size:var(--fs-md); }
.meta{ color:var(--ink-500); font-size:var(--fs-sm); }
.wnote{ font-size:var(--fs-sm); font-weight:400; color:var(--ink-500);
  letter-spacing:0; text-transform:none; }
.req{ color:var(--st-blocked-fg); }


/* ══ LAYOUT & LANDMARKS ═══════════════════════════════════════════════ */

/* ── whitespace ────────────────────────────────────────────────────────
   The rule for the whole product, and the reason several numbers on this
   page went up while others went down: AIR BETWEEN GROUPS, TIGHTNESS INSIDE
   THEM. A group used to be told apart from its neighbour by an outline, so
   the gap between two groups could be the same as the gap between two rows
   inside one. With the outlines mostly gone, the gap is the grouping — so
   the space between groups is now a clear step larger (sp-6/sp-7) than any
   space inside one (sp-2/sp-3), and no ambiguous middle value is used at a
   group boundary. */

/* ── ER2-UAT-UX-01 — the large-screen / ultrawide shell strategy ─────────
   One tiered width system for the whole application, not a per-screen patch:

     READING TIER  (--page-max)   forms, the interview, project setup —
                                  professional line lengths first; grows
                                  moderately with the display.
     WIDE TIER     (--page-wide)  data-dense surfaces — Dashboard, Projects,
                                  Documents, project Overview — where more
                                  columns genuinely aid comprehension. The
                                  route sets `wide` on <main> (route()).

   Nothing ever spans the full viewport: both tiers stay capped, gutters
   scale with the display, and the topbar aligns its contents to the SAME
   width system so header and content read as one page on every display
   (1280 · 1440 · 1920 · ~3440 verified). */
:root{
  --page-wide:var(--page-max);
  --shell-pad:var(--sp-6);
}
@media (min-width:1600px){
  :root{ --page-max:1360px; --page-wide:1720px; --shell-pad:var(--sp-8); }
}
@media (min-width:2200px){
  :root{ --page-max:1520px; --page-wide:2080px; --shell-pad:var(--sp-9); }
}

main{
  max-width:var(--page-max);
  margin-inline:auto;
  padding:var(--sp-8) var(--sp-5) var(--sp-9);
}
main.wide{ max-width:var(--page-wide); }

.page-head{
  display:flex; align-items:flex-start; justify-content:space-between;
  gap:var(--sp-5); margin-block-end:var(--sp-7);
}

.crumb{ font-size:var(--fs-sm); color:var(--ink-500); margin-block-end:var(--sp-2);
  letter-spacing:.02em; }
.crumb a{ text-decoration:none; }
.crumb a:hover{ text-decoration:underline; }

.grid{ display:grid; gap:var(--sp-5); }
.grid.tiles{ grid-template-columns:repeat(auto-fit, minmax(190px, 1fr)); }
.grid.tiles.five{ grid-template-columns:repeat(auto-fit, minmax(178px, 1fr)); }
.grid.two{ grid-template-columns:1fr 1fr; align-items:start; }

.row{ display:flex; gap:var(--sp-2); flex-wrap:wrap; align-items:center; }


/* ══ TOPBAR · BRAND · NAV · SESSION ═══════════════════════════════════ */

/* PHASE C6 — the topbar is a light instrument bezel, not a navy slab: white
   ground, a soft blue hairline, ink navigation and the primary-blue brand
   chip. It still carries the brand, the product areas and the signed-in
   operator, and it must survive 560px without hiding any of the three. */
.topbar{
  background:var(--surface); color:var(--ink-900);
  display:flex; align-items:center; gap:var(--sp-5);
  /* ER2-UAT-UX-01 — the bar's contents align to the same width system as
     the content below it: on an ultrawide the brand, navigation and session
     block no longer fly to the physical screen edges. */
  padding-inline:max(var(--shell-pad), calc((100vw - var(--page-wide) - 2 * var(--sp-5)) / 2));
  min-height:var(--topbar-h);
  position:sticky; inset-block-start:0; z-index:20;
  flex-wrap:wrap;
  /* C6 — the bezel hairline is now the ruling's nav hairline blue, and it
     is what separates the white bar from a white card scrolled up under it. */
  box-shadow:inset 0 -1px 0 var(--nav-hairline);
  border-block-end:1px solid var(--nav-hairline);
}

.brand{ display:flex; align-items:center; gap:var(--sp-2); flex:none; }
.brand .mark{
  inline-size:30px; block-size:30px; border-radius:var(--r-2); flex:none;
  background:var(--pri-600); color:#fff;
  display:grid; place-items:center;
  font-weight:700; font-size:var(--fs-lg); letter-spacing:.5px;
  /* The mark is a plate, not a bubble — square-ish corners keep it in the
     instrument-panel register rather than the app-icon one. */
}
.brand .name{ font-weight:650; letter-spacing:.02em; line-height:1.2; }
.brand .sub{ color:var(--ink-500); font-size:var(--fs-sm); line-height:1.3; }

.topbar .brand .mark{ background:var(--pri-600); color:#fff; }
.topbar .brand .name{ color:var(--ink-900); }
.topbar .brand .sub{ color:var(--ink-500); opacity:.95; font-size:12px;
  letter-spacing:.015em; margin-block-start:1px;
  /* PHASE C er6 §1 — readability polish only: the dynamic tag reads as a
     deliberate identity line, not compressed metadata. Same DOM, same
     dynamic /api/build value, no height change (brand block ≤ 36px in a
     58px bar), EN+AR single-line behaviour untouched. */ }

.topbar nav{ display:flex; gap:var(--sp-1); margin-inline-start:var(--sp-4); flex:1 1 260px; }
.topbar nav a{
  color:var(--ink-600); text-decoration:none;
  padding:var(--sp-2) var(--sp-3); border-radius:var(--r-2);
  font-size:var(--fs-md); font-weight:550; white-space:nowrap;
  border-block-end:2px solid transparent;
}
.topbar nav a:hover{ background:var(--pri-soft); color:var(--ink-900); }
/* C6 — current area is the ruling's nav-active chip, and it KEEPS the
   accepted teal keel: chip says where you are, keel says it is live. */
.topbar nav a[aria-current="page"]{
  color:var(--pri-800); background:var(--nav-active);
  border-block-end-color:var(--teal-500);
}

.who{ display:flex; align-items:center; gap:var(--sp-2);
  font-size:var(--fs-md); color:var(--ink-600); flex:none; }
.who .avatar{
  inline-size:30px; block-size:30px; border-radius:50%; flex:none;
  background:var(--pri-600); color:#fff; display:grid; place-items:center;
  font-size:var(--fs-sm); font-weight:650;
}
.who .who-name{ font-weight:600; color:var(--ink-900); line-height:1.25; }
.who .who-title{ color:var(--ink-500); font-size:var(--fs-sm); line-height:1.25; }
.who button{
  background:transparent; border:1px solid var(--line-300);
  color:var(--ink-600); border-radius:var(--r-2);
  padding:var(--sp-1) var(--sp-3); font:inherit; font-size:var(--fs-sm);
  font-size-adjust:var(--x-height); cursor:pointer;
}
.who button:hover{ background:var(--pri-soft); color:var(--ink-900); border-color:var(--nav-hairline); }

/* ── PHASE C (Batch C1) — topbar maturity ──────────────────────────────
   1. Navigation carries the D2 product icons beside its labels (icons
      SUPPLEMENT words — the label never leaves). They appear from 1500px
      up so the bar's content budget still fits BOTH languages on one line
      at 1280–1499px.
   2. The P1-4 Arabic wrap fix is structural: at desktop widths the bar may
      not wrap; the session block sheds its second line first (the role
      title), then the brand sub-line — identity degrades before geometry
      does. Below 900px the original wrapping behaviour returns unchanged.  */
#nav a .d2{ display:none; }
@media (min-width:1500px){
  #nav a{ display:inline-flex; align-items:center; gap:7px; }
  #nav a .d2{ display:inline-block; inline-size:18px; block-size:18px; flex:none; }
}
@media (min-width:900px){
  .topbar{ flex-wrap:nowrap; }
  .topbar nav{ min-inline-size:0; overflow:hidden; }
  .who{ min-inline-size:0; }
}
@media (max-width:1699px){ .who .who-title{ display:none; } }
/* PHASE C (C3 correction §1) — the build identity stays VISIBLE at every
   width: the .sub line under the brand carries the dynamic build tag and is
   subordinate by size/opacity, not by disappearing. The AR one-line budget
   is kept by the nav-icon threshold and the who-title rule above. */
@media (max-width:899px){
  .topbar{ flex-wrap:wrap; }
  .who .who-title{ display:block; }
}


/* ══ GROUPING: SURFACES, PANELS & PLATES ══════════════════════════════

   The old file had one grouping treatment — a bordered, rounded, shadowed
   .card — and used it for everything, nested inside itself where a screen
   had sub-groups. Ten of them down a page is what makes a product read as a
   collection of bordered administrative forms rather than as a console: no
   surface was more important than any other, so none of them meant anything.

   There are now four levels, and only the first is an object:

     .card.raised   A GENUINELY ELEVATED SURFACE. Border, shadow, sits above
                    the page. At most one per screen — it is for something
                    that is over the content rather than in it (the sticky
                    save bar already works this way). Use it and you are
                    saying "this floats".
     .card          The default plate: a white working surface on the cool
                    ground, no outline and no shadow. The surface and the air
                    around it do the grouping; the heading does the naming.
     .card.flat     No plate. The group sits on the page ground and is told
                    by its heading and by the space around it; its inner
                    padding is kept so its content still lines up with the
                    plates above and below it.
     .card.bare     No plate, no padding. Pure typographic grouping, flush
                    to the page grid. This is the lightest thing that is
                    still a group.

   `.panel` is `.card.bare` under a name the shell can use on new markup that
   was never a card. `.sep` is a hairline for the case where a heading and
   space genuinely are not enough.

   Everything above keeps working unchanged where it is already used: .card
   on its own is still a group, it is simply a quieter one. */

.card{
  background:var(--surface); border:0;
  border-radius:var(--r-2); box-shadow:none;
  padding:var(--sp-5) var(--card-pad) var(--card-pad);
  margin-block-end:var(--sp-6);
}

/* A card heading routinely carries a count or a control on the far side.
   The hairline under it is the group's only line: it replaces the outline
   the card used to draw around all four of its sides. */
.card > h2{
  display:flex; align-items:center; justify-content:space-between;
  gap:var(--sp-3); flex-wrap:wrap;
  border-block-end:1px solid var(--edge);
  padding-block-end:var(--sp-2);
  margin-block-end:var(--sp-4);
}

/* The one elevated level. */
.card.raised{ border:1px solid var(--edge); box-shadow:var(--shadow-1); }

/* The two lighter levels. */
.card.flat{ background:transparent; }
.card.bare, .panel{ background:transparent; padding:0; }
.panel{ margin-block-end:var(--sp-7); }
.panel > h2{
  display:flex; align-items:center; justify-content:space-between;
  gap:var(--sp-3); flex-wrap:wrap;
  border-block-end:1px solid var(--edge);
  padding-block-end:var(--sp-2);
}

/* A group inside a group is never a second box. Nesting a card was the
   commonest way the old file ended up with an outline inside an outline;
   now the inner one flattens automatically and is told by its heading, so
   the shell does not have to remember to ask for it. */
.card .card, .card .panel, .panel .card{
  background:transparent; border:0; box-shadow:none;
  padding-inline:0; padding-block-start:0;
  margin-block-end:var(--sp-5);
}
.card .card:last-child, .panel .card:last-child{ margin-block-end:0; }

/* The hairline between two groups that a heading alone does not separate. */
.sep{ border:0; border-block-start:1px solid var(--edge);
  margin-block:var(--sp-6); block-size:0; }

.card.widget{ margin-block-end:var(--sp-6); }
.card.widget h2{ display:flex; align-items:baseline; gap:var(--sp-2); flex-wrap:wrap; }

.note{
  background:var(--surface-2); border:1px solid var(--edge);
  border-inline-start:3px solid var(--pri-600);
  border-radius:var(--r-2); padding:var(--sp-3) var(--sp-4);
  font-size:var(--fs-md); color:var(--ink-600);
}

/* A tile is a read-out, not a container: it keeps its plate so a row of
   numbers reads as a row of instruments, but loses the outline and the
   shadow along with everything else. */
.tile{
  background:var(--surface); border:0;
  border-radius:var(--r-2); padding:var(--sp-4) var(--sp-5); box-shadow:none;
}
.tile .k{ color:var(--ink-500); font-size:var(--fs-xs);
  text-transform:uppercase; letter-spacing:.07em; font-weight:600; }
.tile .v{ font-size:var(--fs-3xl); font-weight:650; color:var(--navy-800);
  line-height:1.2; margin-block-start:var(--sp-1);
  font-variant-numeric:tabular-nums lining-nums; }
.tile .n{ color:var(--ink-500); font-size:var(--fs-sm); margin-block-start:2px; }

/* Tone on a tile is a 3px edge, never a filled panel: the number stays the
   thing you read, and five tinted boxes in a row would read as a chart. */
.tile.t-ok{ border-inline-start:3px solid var(--st-ready-line); }
.tile.t-warn{ border-inline-start:3px solid var(--st-attention-line); }
.tile.t-bad{ border-inline-start:3px solid var(--st-blocked-line); }
.tile.t-bad .v{ color:var(--st-blocked-fg); }


/* ══ THE STATUS SYSTEM ════════════════════════════════════════════════ */

/* One vocabulary, five states, used product-wide. Each state is defined
   once as a set of custom properties; every presentation (pill, stage tile,
   row tint, finding code) reads those properties instead of restating the
   colours. The frozen uppercase s-* tokens the engines emit are aliased
   onto the five states in the same selector lists, so adding a token later
   is one line, not a new colour.

   Colour is never the only signal. Each state also carries a glyph and a
   distinct border weight, so the five remain tellable apart in greyscale,
   in print, and for a reviewer with a colour vision deficiency.

   PHASE C (Batch C1): the dashed/dotted border styles are retired — the er3
   audit found the dashed "In Preparation" pill read as an INPUT, not a
   status. Greyscale distinguishability is preserved by what remains: five
   distinct glyphs (masked icons) and the weight/inner-rule ladder:

     ready      ✓   1px solid
     attention  ▲   2px solid
     blocked    ✕   2px solid + inner rule (reads as a double line)
     progress   ◆   1px solid
     idle       –   1px solid                                             */

.st-ready,
.pill.s-COMPLETE, .pill.s-COMPLETED, .pill.s-VALID, .pill.s-APPROVED,
.pill.s-READY_FOR_GACA_SUBMISSION, .pill.s-OPERATIONALLY_READY,
.pill.s-GENERATED, .pill.s-SATISFIED{
  --st-fg:var(--st-ready-fg); --st-bg:var(--st-ready-bg); --st-line:var(--st-ready-line);
  --st-glyph:"\2713"; --st-ic:var(--ic-check); --st-bw:1px; --st-bs:solid; --st-inner:0 0 0 0 transparent;
}

.st-attention,
.pill.s-ACTION_REQUIRED, .pill.s-REQUIRES_REVIEW, .pill.s-NEAR_EXPIRY,
.pill.s-INCOMPLETE, .pill.s-INSUFFICIENT_INFORMATION,
.pill.s-DRAFT_GENERATED_ALLOWED, .pill.s-UNKNOWN{
  --st-fg:var(--st-attention-fg); --st-bg:var(--st-attention-bg); --st-line:var(--st-attention-line);
  --st-glyph:"\25B2"; --st-ic:var(--ic-attention); --st-bw:2px; --st-bs:solid; --st-inner:0 0 0 0 transparent;
}

.st-blocked,
.pill.s-MISSING, .pill.s-EXPIRED, .pill.s-NO_CERTIFICATE, .pill.s-INVALID,
.pill.s-NOT_READY, .pill.s-OUT_OF_ENVELOPE, .pill.s-CONFLICT{
  --st-fg:var(--st-blocked-fg); --st-bg:var(--st-blocked-bg); --st-line:var(--st-blocked-line);
  --st-glyph:"\2715"; --st-ic:var(--ic-blocked); --st-bw:2px; --st-bs:solid;
  --st-inner:inset 0 0 0 1px var(--surface);
}

/* PREVIEW and VALIDATED are layout-lifecycle stops before APPROVED. They are
   deliberately not "ready": a validated layout still has an approval gate in
   front of it, and showing it green would tell an operator it is done. */
.st-progress,
.pill.s-IN_PROGRESS, .pill.s-PENDING_EXTERNAL, .pill.s-SUBMITTED,
.pill.s-REQUESTED, .pill.s-PREVIEW, .pill.s-VALIDATED{
  --st-fg:var(--st-progress-fg); --st-bg:var(--st-progress-bg); --st-line:var(--st-progress-line);
  --st-glyph:"\25C6"; --st-ic:var(--ic-pending); --st-bw:1px; --st-bs:solid; --st-inner:0 0 0 0 transparent;
}

.st-idle,
.pill.s-NOT_STARTED, .pill.s-NOT_APPLICABLE, .pill.s-NOT_YET_REQUIRED,
.pill.s-NONE, .pill.s-SUPERSEDED{
  --st-fg:var(--st-idle-fg); --st-bg:var(--st-idle-bg); --st-line:var(--st-idle-line);
  --st-glyph:"\2013"; --st-ic:var(--ic-idle); --st-bw:1px; --st-bs:solid; --st-inner:0 0 0 0 transparent;
}

/* The state classes on their own only colour text, so .st-blocked can be put
   on a heading or a list item without turning it into a chip. */
.st-ready, .st-attention, .st-blocked, .st-progress, .st-idle{ color:var(--st-fg); }


/* ── the pill ──────────────────────────────────────────────────────── */

/* A rectangular tag, not a lozenge. Regulatory documents label things with
   tags; rounded lozenges belong to consumer software. Defaults to idle so a
   status token that is not yet aliased above still renders as a real tag
   rather than as unstyled text.

   STATUS PROMINENCE. Status is the most important thing on nearly every
   screen here and it used to be the smallest type in the product — 11.5px
   against 13.5px body — so it read as an afterthought beside the row it was
   describing. It is now set at --fs-sm and at 700, one step above the body
   text around it rather than one below.

   That is deliberately all that changed. The tint area is not enlarged: the
   padding is unchanged and the box grows only by the height of its own
   label, because five bigger colour blocks per screen would make status
   louder without making it clearer. The prominence is bought instead from
   the things around it — secondary buttons, meta text and group outlines all
   stepped back in this revision — so the pill is now the strongest mark in
   its row without carrying any more colour than before.

   The five states, their five colour pairs, their glyphs and their
   border weights/styles are untouched: greyscale distinguishability and
   the print behaviour below are exactly as they were. */
.pill{
  --st-fg:var(--st-idle-fg); --st-bg:var(--st-idle-bg); --st-line:var(--st-idle-line);
  --st-glyph:"\2013"; --st-ic:var(--ic-idle); --st-bw:1px; --st-bs:solid; --st-inner:0 0 0 0 transparent;
  display:inline-flex; align-items:baseline; gap:var(--sp-1);
  /* PHASE C (Batch C1) — the approved one-pill status language: a lozenge
     carrying icon + governed wording. The label is never a paragraph: long
     explanatory sentences live BESIDE the pill as a caption/meta line, per
     the approved status composition rule. */
  padding-block:3px; padding-inline:var(--sp-2) var(--sp-3); border-radius:var(--r-pill);
  font-size:var(--fs-sm); font-weight:700; letter-spacing:.01em;
  line-height:1.35;
  white-space:nowrap; vertical-align:baseline;
  color:var(--st-fg); background:var(--st-bg);
  border:var(--st-bw) var(--st-bs) var(--st-line);
  box-shadow:var(--st-inner);
}
.pill::before{
  /* Batch 4.D — the mark is drawn from the icon set (masked, currentColor),
     so it renders identically on every platform; the spelled-out label still
     carries the meaning and the mark stays silent to assistive tech. */
  content:''; inline-size:.8em; block-size:.8em; flex:none;
  background:currentColor;
  -webkit-mask:var(--st-ic) center / contain no-repeat;
  mask:var(--st-ic) center / contain no-repeat;
}



/* ══ TABLES ═══════════════════════════════════════════════════════════ */

/* Horizontal rules only. A full grid of borders is what a government paper
   form looks like; an operations table gets its structure from alignment
   and from the row rule, and reads faster for it. */
table{
  inline-size:100%; border-collapse:collapse;
  font-size:var(--fs-md);
}
th{
  text-align:start;
  font-size:var(--fs-xs); text-transform:uppercase; letter-spacing:.08em;
  color:var(--ink-500); font-weight:700;
  padding:0 var(--sp-3) var(--sp-2);
  /* Level 1: the head rule is the strongest line inside a group, because it
     is the one that says "columns start here". */
  border-block-end:1px solid var(--edge-strong);
  white-space:nowrap;
}
td{
  padding:var(--sp-3);
  /* Level 3: a row rule is structure inside one group and must not compete
     with the head rule above it. */
  border-block-end:1px solid var(--hairline);
  /* Centred vertically, so a one-line status sits level with a two-line
     project name instead of floating at the top of the cell. */
  vertical-align:middle;
}
tr:last-child td{ border-block-end:0; }
tbody tr:hover{ background:var(--surface-2); }

/* Column alignment utilities. Short values, statuses and numbers are
   centred; long prose follows the reading direction of the document. */
.t-num{ text-align:center; font-variant-numeric:tabular-nums lining-nums;
  white-space:nowrap; }
.t-status{ text-align:center; white-space:nowrap; }
.t-short{ text-align:center; white-space:nowrap; }
.t-long{ text-align:start; }

/* Headers inherit their column's alignment so the rule above the numbers
   does not sit off to one side of them. */
th.t-num, th.t-status, th.t-short{ text-align:center; }
th.t-long{ text-align:start; }

td .pid{ font-family:var(--font-mono); font-size:var(--fs-sm); color:var(--ink-500);
  direction:ltr; unicode-bidi:isolate; }
td .pname{ font-weight:600; color:var(--link-600); text-decoration:none; }
td .pname:hover{ text-decoration:underline; }
td .opdate{ font-weight:600; color:var(--navy-700); white-space:nowrap;
  direction:ltr; unicode-bidi:isolate; }

/* Operational tables carry long names and site descriptions; give the
   readable columns the room and stop the action buttons from wrapping. */
.card.widget table{ table-layout:auto; }
.card.widget td .btn.small{ white-space:nowrap; }
td.cproj{ min-inline-size:215px; }

/* Row emphasis. Tinted rows say "this one is happening now" or "this one
   needs attention" — never more than two rows in a table should carry it,
   or the tint stops meaning anything. */
tr.row-now td{ background:var(--st-progress-bg); }
tr.row-warn td{ background:var(--st-attention-bg); }
tr.row-now:hover td, tr.row-warn:hover td{ filter:brightness(.985); }

/* Wrap a table in this when the viewport can be narrower than the columns.
   The min-width keeps the columns readable and moves the compromise to a
   scrollbar instead of to crushed text. */
.table-scroll{ overflow-x:auto; overscroll-behavior-x:contain; }
.table-scroll > table{ min-inline-size:640px; }


/* ══ FORMS & FIELDS ═══════════════════════════════════════════════════ */

.field{ margin-block-end:var(--sp-4); }
.field label{ display:block; font-size:var(--fs-md); font-weight:600;
  margin-block-end:var(--sp-1); color:var(--ink-700); }
.field .hint{ color:var(--ink-500); font-weight:400; font-size:var(--fs-sm); }

.field input, .field select, .field textarea,
input[type=text], input[type=date], input[type=time], input[type=number],
select, textarea{
  inline-size:100%; max-inline-size:100%;
  padding:var(--sp-2) var(--sp-3);
  font:inherit; font-size:var(--fs-md); font-size-adjust:var(--x-height); color:var(--ink-900);
  /* Level 1. A control is one of the few things left in the product that is
     genuinely a box, and it should be the clearest box on the screen. */
  border:1px solid var(--edge-strong); border-radius:var(--r-2);
  background:var(--surface);
  /* Fields hold coordinates, altitudes and registration numbers as often as
     words, so give the control a text alignment that follows direction and
     let the .ltr utility pin the technical ones. */
  text-align:start;
}
.field input:hover, .field select:hover, .field textarea:hover,
select:hover, textarea:hover{ border-color:var(--ink-400); }
input[disabled], select[disabled], textarea[disabled]{
  background:var(--line-100); color:var(--ink-500); cursor:not-allowed; }

textarea{ resize:vertical; min-block-size:74px; }

input[type=checkbox], input[type=radio]{ accent-color:var(--pri-600);
  inline-size:auto; margin:0; }
input[type=range]{ inline-size:100%; accent-color:var(--teal-600); }
input[type=file]{ inline-size:100%; font-size:var(--fs-md); }

/* A fieldset is a group, and groups are told by their label and their space
   here, so it keeps a rule under the legend rather than a box around itself. */
fieldset{ border:0; border-block-start:1px solid var(--edge);
  border-radius:0; padding:var(--sp-4) 0 0; margin:0 0 var(--sp-6); }
legend{ font-size:var(--fs-sm); font-weight:700; color:var(--ink-600);
  text-transform:uppercase; letter-spacing:.08em; padding-inline:0; }


/* ══ BUTTONS ══════════════════════════════════════════════════════════ */

/* ACTION PROMINENCE. There is one primary action per screen at most, and
   before this revision it could not be found: the filled navy .btn, the
   outlined .btn.ghost and the dozen .btn.ghost.small controls that open a
   register or jump to a field all carried a box of roughly the same weight,
   so a screen offered fifteen equally loud things to click.

   Three levels now, and they are meant to be obviously unequal:

     .btn         PRIMARY. Filled navy, the only filled control on the page.
                  One per screen. It has grown a step in padding and weight
                  so that it is the darkest and largest mark in its row.
     .btn.ghost   SECONDARY. Outlined, and the outline has stepped back from
                  --edge-strong to --edge so that a row of them reads as a
                  set of options rather than as a row of buttons. It only
                  colours up on hover and focus.
     .btn.quiet   TERTIARY. No box at all — a text action that recedes into
                  the line it sits in and is underlined on hover. For "open",
                  "show", "history" and the other one-click detours that used
                  to be drawn as small outlined buttons.                     */

/* C6 — primary controls wear the ruling's primary trio verbatim:
   #1F5FB8 rest, #1B54A4 hover, #17478B active. White text at 6.20:1. */
.btn{
  display:inline-flex; align-items:center; justify-content:center; gap:var(--sp-2);
  background:var(--pri-600); color:#fff; border:1px solid var(--pri-600);
  padding:var(--sp-2) var(--sp-5); border-radius:var(--r-2);
  font-family:inherit; font-size:var(--fs-md); font-weight:650;
  cursor:pointer; text-decoration:none; white-space:nowrap;
  transition:background-color .12s ease, border-color .12s ease, color .12s ease;
}
.btn:hover{ background:var(--pri-700); border-color:var(--pri-700); color:#fff; }
.btn:active{ background:var(--pri-800); }
.btn[disabled]{ opacity:.5; cursor:not-allowed; }
.btn[disabled]:hover{ background:var(--pri-600); border-color:var(--pri-600); }

.btn.ghost{ background:transparent; color:var(--pri-600); border-color:var(--edge-strong);
  font-weight:600; }
.btn.ghost:hover{ background:var(--pri-soft); border-color:var(--pri-600); color:var(--pri-700); }
/* 0.9.2.8 §14B — the ACTIVE map tool stays visibly pressed (aria-pressed
   carries the state; this is its visual) until finished, cancelled (ESC) or
   switched. */
.btn.tool-active, .btn.ghost.tool-active{
  background:var(--pri-600); border-color:var(--pri-600); color:#fff; }
.btn.tool-active:hover{ background:var(--pri-700); border-color:var(--pri-700); color:#fff; }
.btn.ghost[disabled]:hover{ background:transparent; border-color:var(--edge-strong); }

.btn.quiet{
  background:transparent; border-color:transparent; color:var(--ink-600);
  font-weight:600; padding-inline:0;
}
.btn.quiet:hover{ background:transparent; border-color:transparent;
  color:var(--pri-700); text-decoration:underline; text-underline-offset:3px; }
.btn.quiet[disabled]:hover{ background:transparent; text-decoration:none; }

.btn.small{ padding:var(--sp-1) var(--sp-3); font-size:var(--fs-sm); }
.btn.quiet.small{ padding-inline:0; }

/* The page's own action. .page-head holds the one thing a screen is for —
   "New project", "Generate" — and it is allowed to be the largest control
   on the page so that it is found without being hunted for. */
.page-head > .btn, .page-head .btn:not(.ghost):not(.quiet){
  padding:var(--sp-3) var(--sp-6); font-size:var(--fs-base);
}

/* A button whose label points forward carries a chevron; in RTL the chevron
   has to point the other way, and a glyph cannot be flipped by a logical
   property, so it is mirrored explicitly in the RTL section below. */


/* ══ PILLS, TILES, FACTS, META ════════════════════════════════════════ */

/* Definition pairs. Used for project facts, insurance detail and the
   maintenance record cards, so the key column has to hold an Arabic label
   as comfortably as an English one. */
dl.facts{ display:grid; grid-template-columns:minmax(120px, auto) 1fr;
  gap:var(--sp-1) var(--sp-4); margin:0; align-items:baseline; }
dl.facts dt{ color:var(--ink-500); font-size:var(--fs-sm); }
dl.facts dd{ margin:0; font-size:var(--fs-md); font-weight:600; color:var(--navy-700); }
dl.facts dd.f-ok{ color:var(--st-ready-fg); }
dl.facts dd.f-warn{ color:var(--st-attention-fg); }
dl.facts dd.f-bad{ color:var(--st-blocked-fg); }

.kv{ display:grid; grid-template-columns:168px 1fr; gap:var(--sp-2) var(--sp-4);
  font-size:var(--fs-md); }
.kv dt{ color:var(--ink-500); }
.kv dd{ margin:0; }


/* ══ THE STAGE RAIL & WORKFLOW ════════════════════════════════════════ */

/* The six frozen workflow stages, always in engine order. The rail is the
   primary way through a project, so every tile is a link to that stage. */
.rail{ display:flex; gap:var(--sp-2); flex-wrap:wrap; }
.rail .stage{
  flex:1 1 150px; border:1px solid var(--edge); border-radius:var(--r-2);
  padding:var(--sp-3); background:var(--surface);
  /* A left edge that changes colour with state, so the rail can be scanned
     in one pass without reading six pills. */
  border-inline-start:3px solid var(--edge-strong);
}
.rail .stage .sname{ font-size:var(--fs-sm); font-weight:600;
  margin-block-end:var(--sp-2); color:var(--ink-700); }

.rail .stage.st-COMPLETED{ border-inline-start-color:var(--st-ready-line); background:var(--surface); }
.rail .stage.st-ACTION_REQUIRED{ border-inline-start-color:var(--st-blocked-line); background:var(--surface); }
.rail .stage.st-IN_PROGRESS{ border-inline-start-color:var(--st-progress-line); background:var(--surface); }
.rail .stage.st-NOT_STARTED{ border-inline-start-color:var(--edge-strong); background:var(--surface-2); }

.rail a.stage{ text-decoration:none; color:inherit; display:block; }
.rail a.stage:hover{ border-color:var(--blue-500); border-inline-start-color:var(--blue-500); }
/* Current stage is marked with the accent, matching the topbar's rule for
   "you are here". */
.rail .stage[aria-current="page"]{
  outline:2px solid var(--teal-600); outline-offset:-2px; background:var(--teal-100);
}
.rail .stage.soon{ opacity:.62; }

/* Blockers — named, never a percentage. */
.blockers{ list-style:none; margin:0; padding:0; }
.blockers li{
  padding:var(--sp-3) 0; border-block-end:1px solid var(--hairline);
  display:flex; gap:var(--sp-3); align-items:flex-start;
}
.blockers li:last-child{ border-block-end:0; }
.blockers .bid{
  font-family:var(--font-mono); font-size:var(--fs-xs);
  color:var(--ink-500); flex:0 0 108px; max-inline-size:108px;
  padding-block-start:3px; direction:ltr; unicode-bidi:isolate; text-align:start;
}
.blockers .blabel{ font-weight:600; font-size:var(--fs-md); color:var(--ink-900); }
.blockers .breason{ color:var(--ink-500); font-size:var(--fs-md); margin-block-start:2px; }
.blockers .bhint{ color:var(--ink-500); font-size:var(--fs-sm); margin-block-start:var(--sp-1); }
.blockers .bact{ margin-block-start:var(--sp-2); display:flex; align-items:center;
  gap:var(--sp-2); flex-wrap:wrap; }
/* "Not built yet" is stated with a dashed outline rather than with a
   disabled button, so nobody clicks it expecting something to happen. */
.blockers .soon{
  font-size:var(--fs-sm); color:var(--ink-500);
  border:1px dashed var(--edge-strong); border-radius:var(--r-1);
  padding:2px var(--sp-2);
}

.savebar{
  position:sticky; inset-block-end:0; z-index:10;
  margin-inline:calc(var(--card-pad) * -1); margin-block-end:calc(var(--card-pad) * -1);
  padding:var(--sp-3) var(--card-pad);
  background:var(--surface); border-block-start:1px solid var(--edge);
  border-end-start-radius:var(--r-2); border-end-end-radius:var(--r-2);
  display:flex; align-items:center; justify-content:space-between;
  gap:var(--sp-3); flex-wrap:wrap;
  /* The only lifted surface in the product. It sits over the answers an
     operator is still scrolling through, so it needs to read as floating
     rather than as the last row of the card. */
  box-shadow:var(--shadow-2);
}
.savestate{ font-size:var(--fs-sm); color:var(--ink-500); }
.savestate.bad{ color:var(--st-blocked-fg); font-weight:600; }


/* ══ THE OPERATIONAL INTERVIEW ════════════════════════════════════════ */

.qgroup{ margin-block-end:var(--sp-6); }
/* The section head is the group. It carries the title and the count on one
   line and a rule under both, which is what the group's outline used to do. */
.qgroup > .ghead{ display:flex; align-items:baseline; justify-content:space-between;
  gap:var(--sp-3); margin-block-end:var(--sp-1); }
.qgroup .gtitle{ font-size:var(--fs-lg); font-weight:650; margin:0;
  text-transform:none; letter-spacing:normal; color:var(--navy-900); }
.qgroup .glede{ color:var(--ink-500); font-size:var(--fs-md); margin:0 0 var(--sp-2);
  padding-block-end:var(--sp-3); border-block-end:1px solid var(--edge); }
.qgroup .glede:empty{ border-block-end:0; padding-block-end:0; margin-block-end:0; }
.qgroup .gcount{ font-size:var(--fs-sm); color:var(--ink-500); white-space:nowrap;
  font-variant-numeric:tabular-nums; }

.q{ padding:var(--sp-5) 0; border-block-start:1px solid var(--hairline); }
.q:first-of-type{ border-block-start:0; padding-block-start:var(--sp-2); }
/* .qhead is gone. The interview was inverted in the shell — the operational
   question now leads and the traceability that used to sit above it as a
   title (id, provenance, branch) is a disclosure below the item, emitted as
   .qflags and .qmeta. No element carries .qhead any more, so the rule that
   styled it has been deleted rather than left to rot. */
.qid{ font-family:var(--font-mono); font-size:var(--fs-xs); color:var(--ink-500);
  direction:ltr; unicode-bidi:isolate; }
.qtag{ font-size:var(--fs-xs); color:var(--ink-500);
  border:1px solid var(--edge); border-radius:var(--r-1);
  padding:1px var(--sp-2); }
.qtext{ font-size:var(--fs-base); font-weight:550; margin:0 0 var(--sp-3);
  color:var(--ink-900); }

.opts{ display:flex; flex-wrap:wrap; gap:var(--sp-2); }
.opt{
  display:inline-flex; align-items:center; gap:var(--sp-2); cursor:pointer;
  border:1px solid var(--edge-strong); background:var(--surface); border-radius:var(--r-2);
  padding:var(--sp-2) var(--sp-3); font-size:var(--fs-md); color:var(--ink-700);
}
.opt:hover{ background:var(--surface-2); border-color:var(--ink-400); }
.opt input{ accent-color:var(--pri-600); margin:0; flex:none; }
/* The chosen answer is stated by weight and by a solid navy edge, not by a
   fill alone — the interview is printed as part of the submission package. */
.opt.on{ border-color:var(--pri-600); background:var(--pri-soft);
  color:var(--ink-900); font-weight:600; box-shadow:inset 0 0 0 1px var(--pri-600); }

.q textarea{ inline-size:100%; min-block-size:74px; }

.qwarn{ margin-block-start:var(--sp-2); font-size:var(--fs-md);
  border-radius:var(--r-2); padding:var(--sp-2) var(--sp-3); }
.qwarn b{ font-weight:650; }
.qwarn.w-OUT_OF_ENVELOPE{
  background:var(--st-blocked-bg); border:1px solid var(--st-blocked-line);
  color:var(--st-blocked-fg); }
.qwarn.w-BLOCK_CLASS{
  background:var(--st-attention-bg); border:1px solid var(--st-attention-line);
  color:var(--st-attention-fg); }
.qwarn.w-READINESS{
  background:var(--surface-2); border:1px solid var(--edge);
  color:var(--ink-600); }
/* Build 0.9.2.3a §1 — a value RCOS has withdrawn because it described a
   superseded hospital. Same weight as an out-of-envelope warning: the operator
   is looking at a regulatory table that currently has a hole in it. */
.qwarn.w-BLOCKING{
  background:var(--st-blocked-bg); border:1px solid var(--st-blocked-line);
  color:var(--st-blocked-fg); }

/* A field whose answer RCOS is asking for rather than proposing. The marker is
   on the leading edge so it reads identically in both writing directions. */
.field.needs{
  border-inline-start:3px solid var(--st-blocked-line);
  padding-inline-start:var(--sp-3); }
.field.needs label{ color:var(--st-blocked-fg); }
.qtag.bad{
  border-color:var(--st-blocked-line); color:var(--st-blocked-fg);
  background:var(--st-blocked-bg); font-weight:600; }

/* Build 0.9.2.3a §7.3 — the item Continue stopped on, marked where it lives so
   the operator's eye lands on it after the scroll, not merely near it. */
.needs-now{
  outline:2px solid var(--st-blocked-line); outline-offset:4px;
  border-radius:var(--r-2); scroll-margin-block:120px; }

/* The end-of-step control. Set apart from the cards above it so the bottom of
   a step reads as a completion point rather than as one more panel. */
.card.wizend{ border-color:var(--edge-strong); }
.card.wizend .task-primary{ font-size:var(--fs-md); padding:var(--sp-3) var(--sp-5); }

.q .clear{
  background:none; border:0; color:var(--ink-500); font:inherit; font-size:var(--fs-sm);
  font-size-adjust:var(--x-height);
  cursor:pointer; text-decoration:underline; padding:0; margin-block-start:var(--sp-2);
}
.q .clear:hover{ color:var(--st-blocked-fg); }

/* The next unanswered question is pulled to the card's edge and marked with
   the accent, so an operator returning to a half-finished interview can find
   their place without reading every question above it. */
.q.next{
  background:var(--surface-2);
  border-inline-start:3px solid var(--teal-600);
  margin-inline-start:calc(var(--card-pad) * -1);
  padding-inline-start:calc(var(--card-pad) - 3px);
  padding-inline-end:var(--card-pad);
}


/* ══ THE ASSESSMENT TRACE ═════════════════════════════════════════════ */

.class-grid{ display:grid; grid-template-columns:repeat(auto-fit, minmax(140px, 1fr));
  gap:var(--sp-3); }
.class-grid .c{ border:1px solid var(--hairline); border-radius:var(--r-2);
  padding:var(--sp-3) var(--sp-4); background:var(--surface); }
.class-grid .c .k{ font-size:var(--fs-xs); text-transform:uppercase;
  letter-spacing:.06em; color:var(--ink-500); font-weight:600; }
.class-grid .c .v{ font-size:var(--fs-2xl); font-weight:650; color:var(--navy-800);
  line-height:1.3; font-variant-numeric:tabular-nums lining-nums;
  direction:ltr; unicode-bidi:isolate; }
/* The hero cell is the SAIL — the one number the whole assessment produces. */
.class-grid .c.hero{ background:var(--pri-600); border-color:var(--pri-600); }
.class-grid .c.hero .k{ color:var(--blue-100); opacity:.8; }
.class-grid .c.hero .v{ color:var(--on-navy); }

/* The trace is evidence: it is read line by line against the standard, so
   it keeps monospaced step and rule columns and a plain rule between rows. */
.trace{ list-style:none; margin:0; padding:0; font-size:var(--fs-md); }
.trace li{ display:flex; gap:var(--sp-3); padding:var(--sp-2) 0;
  border-block-end:1px solid var(--hairline); }
.trace li:last-child{ border-block-end:0; }
.trace .step{
  font-family:var(--font-mono); font-size:var(--fs-xs); color:var(--navy-700);
  flex:0 0 132px; max-inline-size:132px; padding-block-start:2px;
  direction:ltr; unicode-bidi:isolate; text-align:start;
}
.trace .rule{
  font-family:var(--font-mono); font-size:var(--fs-xs); color:var(--ink-500);
  flex:0 0 86px; max-inline-size:86px; padding-block-start:2px;
  direction:ltr; unicode-bidi:isolate; text-align:start;
}

.findings{ list-style:none; margin:0; padding:0; font-size:var(--fs-md); }
.findings li{ padding:var(--sp-2) 0; border-block-end:1px solid var(--hairline); }
.findings li:last-child{ border-block-end:0; }
.findings .fq{ font-family:var(--font-mono); font-size:var(--fs-xs); color:var(--ink-500);
  direction:ltr; unicode-bidi:isolate; }
.findings a{ font-size:var(--fs-md); }

/* A stale assessment is a governance problem, not a cosmetic one: it says
   the answers have moved since the classification was produced. */
.stale{
  background:var(--st-attention-bg); border:1px solid var(--st-attention-line);
  color:var(--st-attention-fg); border-radius:var(--r-2);
  padding:var(--sp-3) var(--sp-4); font-size:var(--fs-md); margin-block-end:var(--sp-3);
}


/* ══ THE OPERATIONAL LAYOUT DESIGNER ══════════════════════════════════ */

.dz-wrap{ display:grid; grid-template-columns:minmax(0,1fr) 258px;
  gap:var(--sp-4); align-items:start; }

/* The stage is a map, not text. Its zones are positioned by the editor in
   physical percentages read from pointer coordinates, so the stage is pinned
   to LTR regardless of the document direction — otherwise every drag would
   land on the mirrored side of the site plan. */
.dz-stage{
  position:relative; inline-size:100%; direction:ltr;
  background:var(--line-100); border:1px solid var(--edge-strong);
  border-radius:var(--r-2); overflow:hidden; user-select:none; touch-action:none;
}
.dz-stage.placing{ cursor:crosshair; }
.dz-stage img.bg{ position:absolute; inset:0; inline-size:100%; block-size:100%;
  object-fit:fill; }
.dz-stage .plain{
  position:absolute; inset:0; display:flex; align-items:center; justify-content:center;
  color:var(--ink-500); font-size:var(--fs-md); text-align:center; padding:var(--sp-5);
  /* The empty-state sentence is prose and may be Arabic, so it is allowed to
     resolve its own direction inside the LTR stage. */
  unicode-bidi:plaintext;
}

.dz{ position:absolute; border:2px solid; box-sizing:border-box; cursor:move; }
.dz .dz-tag{
  position:absolute; left:50%; top:50%; transform:translate(-50%, -50%);
  font-size:var(--fs-xs); font-weight:650;
  /* A scrim, not a surface: the zone name has to stay readable over an
     arbitrary satellite image, and no palette token carries an alpha. */
  background:rgba(255,255,255,.88); color:var(--ink-900);
  padding:1px var(--sp-1); border-radius:var(--r-1); white-space:nowrap;
  pointer-events:none; unicode-bidi:plaintext;
}
.dz.sel{ outline:2px dashed var(--pri-700); outline-offset:3px; }
/* Build 0.9.2.1 — the object the current task conflicts WITH. Marked so that
   "it overlaps the Launch Area and the Control Station" is seen and not only
   read. Purely presentational: nothing about the zone or its findings changes. */
.dz.conflict{ outline:2px solid var(--danger, #b42318); outline-offset:3px;
  box-shadow:0 0 0 4px rgba(180,35,24,.14); }

/* ── the operator task card ─────────────────────────────────────────────── */
.task-card h2{ margin-bottom:var(--sp-2); }
.task{ padding:var(--sp-3) 0; }
.task + .task{ border-block-start:1px solid var(--line); }
.task-primary-block{
  background:var(--surface-2, #f6f8fb); border:1px solid var(--line);
  border-radius:var(--r-2); padding:var(--sp-3); margin-block-end:var(--sp-2);
}
.task-title{ font-weight:700; font-size:var(--fs-md); margin-block-end:2px; }
.task-why{ margin:0 0 var(--sp-2); color:var(--ink-700); }
.task-q{ margin:0 0 var(--sp-2); font-weight:600; }
.task-list{ margin:0 0 var(--sp-2); padding-inline-start:1.15em; color:var(--ink-700); }
.task-answers{ display:flex; gap:var(--sp-2); flex-wrap:wrap; }
/* One visually dominant action at a time. Other legitimate tasks stay visible
   and keep their own controls — they are simply not styled as the primary. */
.btn.task-primary{ font-size:var(--fs-md); padding:10px 18px; font-weight:700; }
.task-h3{ font-size:var(--fs-sm); text-transform:uppercase; letter-spacing:.04em;
  color:var(--ink-600); margin:var(--sp-3) 0 0; }
.task-others{ margin-block-start:var(--sp-2); }
.task-opt{ margin-block-start:var(--sp-3); }
.task-opt > summary{ cursor:pointer; color:var(--ink-700); font-weight:600; }
.task-elsewhere{ margin:var(--sp-3) 0 0; padding-block-start:var(--sp-2);
  border-block-start:1px solid var(--line); color:var(--ink-700);
  display:flex; align-items:center; gap:var(--sp-2); flex-wrap:wrap; }
details.tech > summary{ cursor:pointer; font-weight:600; color:var(--ink-700); }
details.tech .tech-body{ margin-block-start:var(--sp-3); }
details.tech .card{ border:0; padding:0; margin-block-start:var(--sp-3); box-shadow:none; }
/* The grip is a physical corner handle inside an LTR stage and is dragged
   with raw pointer deltas, so it stays right/bottom in both directions. */
.dz .grip{
  position:absolute; right:-7px; bottom:-7px; inline-size:13px; block-size:13px;
  background:var(--surface); border:2px solid var(--pri-700);
  border-radius:var(--r-1); cursor:nwse-resize;
}

/* The route layer spans the whole stage, so it must not swallow clicks meant
   for the zones beneath it or for placing the next zone on the map. Only the
   route itself is clickable. */
.dz-svg{ position:absolute; inset:0; inline-size:100%; block-size:100%;
  overflow:visible; pointer-events:none; }
.dz-svg polyline{ fill:none; stroke-width:3; stroke-dasharray:9 6;
  cursor:move; pointer-events:stroke; }
.dz-svg circle{ pointer-events:none; }

.dz-pal{ display:flex; flex-wrap:wrap; gap:var(--sp-1); margin-block-end:var(--sp-2); }
.dz-pal button{
  display:flex; align-items:center; gap:var(--sp-2);
  border:1px solid var(--edge-strong); background:var(--surface);
  border-radius:var(--r-2); padding:var(--sp-1) var(--sp-3);
  font:inherit; font-size:var(--fs-md); font-size-adjust:var(--x-height);
  cursor:pointer; color:var(--ink-700);
}
.dz-pal button:hover{ background:var(--surface-2); border-color:var(--ink-400); }
.dz-pal button[aria-pressed="true"]{
  border-color:var(--pri-600); background:var(--pri-soft);
  color:var(--ink-900); font-weight:650;
  box-shadow:inset 0 0 0 1px var(--pri-600);
}
.dz-pal .sw{ inline-size:11px; block-size:11px; border-radius:var(--r-1);
  border:1px solid rgba(0,0,0,.22); flex:none; }
.dz-pal .n{ color:var(--ink-500); font-size:var(--fs-xs); font-weight:400; }

.dz-side .field{ margin-block-end:var(--sp-3); }
.dz-side input[type=range]{ inline-size:100%; }
.dz-side h3{ font-size:var(--fs-md); margin:0 0 var(--sp-2); }
.dz-row{ display:flex; gap:var(--sp-2); flex-wrap:wrap;
  margin-block-start:var(--sp-2); align-items:center; }
.dz-auth{ color:var(--ink-500); font-size:var(--fs-sm); margin-block-start:var(--sp-3);
  border-block-start:1px solid var(--hairline); padding-block-start:var(--sp-2); }

.dz-find{ list-style:none; margin:0; padding:0; }
.dz-find li{ padding:var(--sp-2) 0; border-block-end:1px solid var(--hairline);
  font-size:var(--fs-md); display:flex; gap:var(--sp-3); align-items:flex-start; }
.dz-find li:last-child{ border-block-end:0; }
.dz-find .c{
  font-family:var(--font-mono); font-size:var(--fs-xs); font-weight:650;
  padding:2px var(--sp-2); border-radius:var(--r-1); white-space:nowrap; flex:none;
  direction:ltr; unicode-bidi:isolate;
}
/* Blocking and advisory findings use the same two states as everything else,
   with the same border weights, so a finding code reads like a status. */
.dz-find .c.blk{ background:var(--st-blocked-bg); color:var(--st-blocked-fg);
  border:2px solid var(--st-blocked-line); }
.dz-find .c.adv{ background:var(--st-attention-bg); color:var(--st-attention-fg);
  border:2px solid var(--st-attention-line); }

/* The four layout lifecycle stops, shown as a progress read-out. */
.dz-steps{ display:flex; gap:var(--sp-2); align-items:center; flex-wrap:wrap;
  margin:var(--sp-1) 0 var(--sp-3); }
.dz-steps .step{
  font-size:var(--fs-sm); padding:var(--sp-1) var(--sp-3); border-radius:var(--r-1);
  border:1px dotted var(--edge); color:var(--ink-500);
}
.dz-steps .step.done{
  background:var(--st-ready-bg); border:1px solid var(--st-ready-line);
  color:var(--st-ready-fg); font-weight:600;
}
.dz-steps .step.now{
  background:var(--teal-100); border:2px solid var(--teal-600);
  color:var(--teal-700); font-weight:650;
}

.dz-prev{ max-inline-size:100%; border:1px solid var(--edge-strong);
  border-radius:var(--r-2); display:block; }
.dz-derived{
  font-size:var(--fs-sm); color:var(--st-attention-fg);
  background:var(--st-attention-bg); border:1px solid var(--st-attention-line);
  border-radius:var(--r-2); padding:var(--sp-2) var(--sp-3); margin-block-start:var(--sp-3);
}


/* ══ THE MASTER-DATA REGISTER ═════════════════════════════════════════ */

/* Fleet maintenance records and crew certificates. Each record is a card in
   a two-up grid; a superseded record is dimmed by the renderer, so the only
   job here is to keep the record id and its defect line legible. */
ul.maint{ list-style:none; margin:var(--sp-3) 0 0; padding:0; display:grid; gap:var(--sp-2); }
ul.maint li{ border:1px solid var(--hairline); border-radius:var(--r-2);
  padding:var(--sp-2) var(--sp-3); background:var(--surface); }
.mhead{ display:flex; align-items:center; gap:var(--sp-2); flex-wrap:wrap; }
.mid{ font-family:var(--font-mono); font-size:var(--fs-sm); color:var(--navy-700);
  font-weight:650; direction:ltr; unicode-bidi:isolate; }
.mgroup{ font-size:var(--fs-md); font-weight:600; color:var(--navy-700);
  margin-block-start:var(--sp-1); }
/* A recorded defect is the one thing on a maintenance record that changes
   whether the fleet may fly, so it is never plain body text. */
.mdefect{ font-size:var(--fs-sm); color:var(--st-attention-fg);
  font-weight:600; margin-block-start:var(--sp-1); }


/* ══ EMPTY · ERROR · LOADING ══════════════════════════════════════════ */

.empty{ text-align:center; padding:var(--sp-8) var(--sp-5); color:var(--ink-500); }
.empty h3{ color:var(--ink-900); margin:0 0 var(--sp-2); font-size:var(--fs-lg); }

.err{
  background:var(--st-blocked-bg); border:1px solid var(--st-blocked-line);
  border-inline-start:3px solid var(--st-blocked-fg);
  color:var(--st-blocked-fg); border-radius:var(--r-2);
  padding:var(--sp-3) var(--sp-4); font-size:var(--fs-md); margin-block-end:var(--sp-3);
}

.spin{ color:var(--ink-500); padding:var(--sp-8); text-align:center; font-size:var(--fs-md); }


/* ══ UTILITIES ════════════════════════════════════════════════════════ */

/* Project ids, hashes, ISO dates, coordinates and version numbers are
   technical strings. Inside an Arabic sentence the bidi algorithm would
   otherwise reorder their punctuation ("PRJ-2026-001" becoming "001-2026-PRJ"),
   so they are isolated as LTR runs wherever they appear. */
.ltr{ direction:ltr; unicode-bidi:isolate; text-align:start; }
.rtl{ direction:rtl; unicode-bidi:isolate; text-align:start; }
.mono{ font-family:var(--font-mono); font-size:var(--fs-sm);
  direction:ltr; unicode-bidi:isolate; }
.nums{ font-variant-numeric:tabular-nums lining-nums; }
.nowrap{ white-space:nowrap; }

.sr-only{
  position:absolute; inline-size:1px; block-size:1px;
  padding:0; margin:-1px; overflow:hidden;
  clip-path:inset(50%); white-space:nowrap; border:0;
}

/* Keyboard users land on the topbar first; this lets them jump the nav and
   get straight to the screen content. It is off-canvas until focused. */
.skip-link{
  position:absolute; inset-inline-start:var(--sp-3); inset-block-start:calc(var(--sp-3) * -1);
  transform:translateY(-200%);
  z-index:100; background:var(--surface); color:var(--ink-900);
  border:1px solid var(--pri-600); border-radius:var(--r-2);
  padding:var(--sp-2) var(--sp-4); font-size:var(--fs-md); font-weight:600;
  text-decoration:none; box-shadow:var(--shadow-2);
}
.skip-link:focus, .skip-link:focus-visible{
  transform:translateY(0); inset-block-start:var(--sp-2);
}

[hidden]{ display:none !important; }


/* ══ FOCUS ════════════════════════════════════════════════════════════ */

/* Every interactive element, not just text inputs. The accent alone is
   2.79:1 against --bg, which is under the 3:1 that a focus indicator needs,
   so the ring is composite: a 1px navy line hard against the element and the
   teal outline 2px outside it. The pair clears 3:1 on white, on --bg, on the
   tinted rows and on the status backgrounds. The --focus token itself was
   left exactly as issued. */
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
summary:focus-visible,
[tabindex]:not(#view):focus-visible,
label.opt:has(:focus-visible),
.dz:focus-visible{
  outline:2px solid var(--focus);
  outline-offset:2px;
  /* C6 — the companion line is the darkest primary step, so the composite
     ring keeps clearing 3:1 on white, on the page tint and on tinted rows. */
  box-shadow:0 0 0 1px var(--pri-800);
}

/* Batch 1.E — <main id="view"> is focused programmatically after every
   navigation so keyboard and screen-reader users land on the new content
   (mount()). It is a landing target, not an operable control: drawing the
   full-viewport composite ring around the whole page read as a debug frame
   on every screen. Focus itself is kept — only the visible ring is limited
   to meaningful interactive/skip targets. Some engines match programmatic
   focus as :focus-visible, so both states are silenced explicitly. */
main#view:focus, main#view:focus-visible{ outline:none; box-shadow:none; }

/* C6 — the topbar is white now, so the standard composite ring works there
   too; the old light-on-navy focus variant is retired with the navy bar. */

/* A field that is focused should also read as focused without a keyboard,
   so the border darkens on plain :focus as well as on :focus-visible. */
input:focus, select:focus, textarea:focus{ border-color:var(--pri-600); }


/* ══ RTL ADJUSTMENTS ══════════════════════════════════════════════════ */

/* Almost nothing belongs here: the file uses logical properties throughout,
   so RTL falls out of dir="rtl" on <html>. What remains are the cases a
   logical property genuinely cannot express. */

/* x-height is a Latin metric. Arabic script has no x-height, and in a face
   that carries both scripts the `ex` the engine reports is set by the Latin
   glyphs — so normalising an Arabic screen to it measures the wrong thing.
   Measured: with the adjustment on, a line of Arabic set in DejaVu Sans
   renders 12% smaller than asked for and in Liberation Sans 9% smaller,
   while Calibri and Segoe UI barely move. The upside for Arabic is therefore
   nil and the downside is a tenth of the reading size on any Linux machine
   without a Noto Arabic installed, so the Arabic UI takes the px scale
   straight. It is the same scale, and it is the same ~3.5% larger than
   before that the English UI got.

   This is the whole of the Arabic-specific typography. Everything else —
   the stack, the scale, the weights, the hierarchy — is one system for both
   languages, which is what "Calibri for BOTH English and Arabic" asks for.

   The token is retargeted rather than the property overridden, because half
   a dozen controls in this file restate font-size-adjust:var(--x-height) to
   survive their own `font:inherit`, and those restatements are all more
   specific than this selector. Retarget the token and every one of them
   follows in one line. */
[dir="rtl"]{ --x-height:none; font-size-adjust:none; }

/* A chevron is a picture of a direction, not a box edge, so it has to be
   mirrored by hand. Applies to any label ending in an arrow the renderer
   appends (for example "Open organization master data →"). */
[dir="rtl"] .chev,
[dir="rtl"] .btn .chev{ transform:scaleX(-1); display:inline-block; }

/* The status glyphs are marks with a fixed orientation; the check and the
   cross must not be reflected even inside a mirrored line. Already isolated
   on .pill::before, restated here so it survives any later override. */
[dir="rtl"] .pill::before{ transform:none; }

/* Range inputs are mirrored by the engine in RTL, but the layout designer's
   sliders drive physical values on an LTR map (rotation, opacity, scale),
   so they are pinned LTR to keep "drag further" meaning "larger". */
[dir="rtl"] .dz-side input[type=range]{ direction:ltr; }

/* The designer's own resize grip sits at the physical bottom-right of a
   physically positioned box; nothing about it should flip. */
[dir="rtl"] .dz .grip{ right:-7px; left:auto; }


/* ══ RESPONSIVE ═══════════════════════════════════════════════════════ */

/* Desktop is primary. Each step below gives up a fixed column rather than
   hiding information — an operator on a tablet at a launch site needs the
   same blockers the office sees. */

/* ── laptop ── */
@media (max-width:1200px){
  main{ padding-inline:var(--sp-4); }
  .grid.tiles, .grid.tiles.five{ grid-template-columns:repeat(auto-fit, minmax(168px, 1fr)); }
}

/* ── small laptop / large tablet ── */
@media (max-width:980px){
  /* The designer sidebar stops being a sidebar and stacks under the map,
     which is the only way the map stays big enough to place a zone on. */
  .dz-wrap{ grid-template-columns:1fr; }
  .grid.two{ grid-template-columns:1fr; }
  .topbar{ gap:var(--sp-3); padding-inline:var(--sp-4); }
}

/* ── tablet ── */
@media (max-width:760px){
  main{ padding:var(--sp-5) var(--sp-3) var(--sp-8); }
  .page-head{ flex-direction:column; gap:var(--sp-3); }
  /* One redefinition, and the plate, the save bar and the next-question
     marker all follow it. */
  :root{ --card-pad:var(--sp-4); }

  /* Fallback for tables that are not yet wrapped in .table-scroll: let the
     card scroll sideways instead of crushing the columns. Scoped with :has()
     to cards that hold a table directly, so the interview card's sticky
     .savebar is never turned into a scroll container. */
  .card:has(> table){ overflow-x:auto; }

  /* Fixed label columns become their own rows; 168px of key next to 40px of
     value is not a reading experience on a phone-width screen. */
  .kv{ grid-template-columns:minmax(120px, 38%) 1fr; gap:var(--sp-1) var(--sp-3); }

  .trace .step{ flex:0 0 96px; max-inline-size:96px; }
  .trace .rule{ flex:0 0 70px; max-inline-size:70px; }
  .blockers .bid{ flex:0 0 84px; max-inline-size:84px; }
}

/* ── phone ── */
@media (max-width:560px){
  /* The topbar wraps into two rows: identity on top, navigation below it as
     a single scrollable line. Nothing is hidden behind a menu button —
     there are only three areas and an operator needs all of them. */
  .topbar{
    padding:var(--sp-2) var(--sp-3);
    row-gap:var(--sp-2);
    align-items:center;
  }
  .topbar .brand{ order:1; }
  .topbar .who{ order:2; margin-inline-start:auto; }
  .topbar nav{
    order:3; flex:1 0 100%; margin-inline-start:0;
    overflow-x:auto; overscroll-behavior-x:contain;
    padding-block-end:2px; gap:2px;
  }
  .topbar nav a{ padding:var(--sp-1) var(--sp-2); font-size:var(--fs-sm); }
  /* The operator's title is the first thing to go; the name and the sign-out
     control are what the session block is actually for. */
  .who .who-title, .topbar .brand .sub{ display:none; }
  .who .avatar{ inline-size:26px; block-size:26px; }

  h1{ font-size:var(--fs-xl); }
  .tile .v{ font-size:var(--fs-2xl); }
  .tile{ padding:var(--sp-3) var(--sp-4); }

  /* Every fixed two-column definition list becomes one column. */
  .kv, dl.facts{ grid-template-columns:1fr; gap:2px; }
  .kv dt, dl.facts dt{ margin-block-start:var(--sp-2); }

  /* The blocker id moves above its label rather than squeezing a monospace
     column into a third of the screen. */
  .blockers li, .trace li, .dz-find li{ flex-direction:column; gap:var(--sp-1); }
  .blockers .bid, .trace .step, .trace .rule{ flex:none; max-inline-size:none; }

  .btn{ padding:var(--sp-2) var(--sp-3); }
  .row .btn{ flex:1 1 auto; }
}

/* Motion in this product is confined to hover and focus feedback; none of it
   carries meaning, so all of it is safe to remove. */
@media (prefers-reduced-motion: reduce){
  *, *::before, *::after{
    animation-duration:.001ms !important;
    animation-iteration-count:1 !important;
    transition-duration:.001ms !important;
    scroll-behavior:auto !important;
  }
}


/* ══ PRINT ════════════════════════════════════════════════════════════ */

/* Readiness lists and blocker lists get printed and taken to a briefing or
   attached to a submission, so the page has to survive without colour fills
   and without the chrome an operator cannot click on paper.

   This is the one block that does not use the palette tokens. Screen tokens
   are picked for a lit display; on a monochrome office printer the near-white
   surfaces waste toner and the near-black inks come out grey. Print asks for
   pure black on pure white and two neutral rules, so those are stated
   literally rather than bent out of a screen palette. */
@media print{
  html, body{ background:#fff; color:#000; font-size:11pt; }

  .topbar, .topbar nav, .who, .skip-link, .savebar,
  .btn, .q .clear, .dz-pal, .dz-side, .dz-steps{ display:none !important; }

  main{ max-width:none; padding:0; }

  .card, .tile, .note, .rail .stage, ul.maint li, .class-grid .c{
    box-shadow:none; border:1px solid #999; break-inside:avoid;
  }
  .card{ background:#fff; margin-block-end:12pt; padding:8pt; }

  /* Status tints do not survive a monochrome printer; the glyph and the
     border weight set in the status system are what carry the state on
     paper, so the fill is dropped and the outline kept. */
  .pill{ background:#fff !important; color:#000 !important; border-color:#000 !important;
    box-shadow:none !important; }
  tr.row-now td, tr.row-warn td, .qwarn, .stale, .err, .dz-derived,
  .class-grid .c.hero{ background:#fff !important; color:#000 !important; }
  .class-grid .c.hero .k, .class-grid .c.hero .v{ color:#000 !important; }

  /* Groups are now told apart on screen by a heading and the rule under it
     rather than by an outline. That rule is a screen grey and would vanish
     on paper, so it is restated at printer weight — otherwise a printed
     readiness list arrives at a briefing as one undifferentiated column. */
  .card > h2, .panel > h2, .qgroup .glede{
    border-block-end:1px solid #999; color:#000; }

  table{ font-size:10pt; }
  thead{ display:table-header-group; }        /* repeat headers across pages */
  tr, .blockers li, .trace li, .findings li{ break-inside:avoid; }
  th{ border-block-end:1px solid #000; color:#000; }
  td{ border-block-end:1px solid #bbb; }
  .table-scroll{ overflow:visible; }
  .table-scroll > table{ min-inline-size:0; }

  a{ color:#000; text-decoration:underline; }
  /* A printed cross-reference is useless without its target. */
  a[href^="http"]::after{ content:" (" attr(href) ")"; font-size:9pt; color:#444; }
}

/* ── Two rules the shell needed and could not own ──────────────────────────
   A grid item's automatic minimum size is min-content, so a card holding a
   table with a 640px min width pushed the whole page sideways on a phone
   instead of letting the table scroll inside it. Both of these exist so that
   .table-scroll can actually do its job when it is nested in a grid. */
.grid > * { min-inline-size: 0; }
.table-scroll { min-inline-size: 0; }

/* The frozen Readiness Engine's state label is a sentence, not a word
   ("Ready for GACA submission"). .pill is nowrap by design — a status that
   breaks across two lines stops reading as one token — so a pill that is
   knowingly holding a sentence opts out rather than the default changing. */
.pill.wrap { white-space: normal; text-align: start; }

/* ── The RCOS mark as SVG ──────────────────────────────────────────────────
   .brand .mark was a text plate: a coloured box with a letter set in it. The
   mark is now the drawing itself, and it paints its own plate in currentColor
   with the R knocked out in white. So the box styling has to come off, or the
   plate ends up inside a second plate — and `color` becomes the plate colour
   rather than the letter colour, which is the opposite of what it meant.
   Aviation Blue on the navy topbar: dark enough to stay in the same family,
   light enough that the knocked-out R and the teal track both read. */
/* C6 — the drawn mark paints its own plate in currentColor; on the white
   bar it wears the primary itself, which IS the brand colour now. */
svg.mark{ background:none; border-radius:0; color:var(--pri-600); }
.topbar .brand svg.mark{ background:none; color:var(--pri-600); }


/* ── What the shell emits and this file has to meet ────────────────────────

   app.html carries its own page-scoped <style> for the shell-only pieces —
   the language switch, the provenance chips, the ten-step .jrny rail, the
   .dash ordering, .proj-cards, .desk-only, and the inverted interview item
   (.qflags / .qmeta). Those are its rules and they stay there. What follows
   is only the places where a rule in THIS file has to meet one of them. */

/* The `font` shorthand resets font-size-adjust to `none`. Two controls in
   the shell set `font:inherit` — the language switch and the phone journey's
   "all steps" toggle — so they would silently drop the x-height
   normalisation and, under Calibri, render a step small next to everything
   around them. Restated here at a specificity that reaches them. */
.topbar .langsw button,
.jrny-now .jall{ font-size-adjust:var(--x-height); }

/* The control that reveals the rest of Attention Required. The shell emits
   the wrapper; it had no spacing of its own and sat hard against the last
   blocker row. It is a group boundary, so it gets group air. */
.attn-more{ margin-block-start:var(--sp-4); }

/* The stacked project rows the shell shows below 760px in place of the
   .desk-only table. The rows are the shell's; the action inside one is this
   file's .btn, and a wrapped two-word button is what the stacked layout was
   introduced to avoid. */
.proj-cards .pc-row .btn{ white-space:nowrap; }

/* .jrny sets its own rail hairline at --line-200, which is exactly what
   --edge resolves to, so the rail already sits at the right level of the
   border hierarchy and nothing is corrected here. Recorded so that a later
   change to --edge is known to touch both files. */


/* ── Consolidated directive §2 — the one continuous interview surface ────── */
.ivsec{ scroll-margin-block-start:96px; }
.ivsec .ivinline{ margin-block-end:var(--sp-5); padding-block-end:var(--sp-4);
  border-block-end:1px solid var(--edge); }
/* The inline project-fact blocks are part of THIS page, not a visiting screen:
   their own cards lose their frame so the section reads as one thing. */
.ivsec .ivinline .card{ border:0; padding:0; margin:0 0 var(--sp-4); box-shadow:none; background:none; }
.ivsec .ivinline .card + .card{ margin-block-start:var(--sp-4); }

/* §4 — the section roll-up beside the live progress count. */
.ivroll{ list-style:none; margin:var(--sp-4) 0 0; padding:0;
  display:grid; gap:var(--sp-1); }
.ivroll a{ display:flex; align-items:center; gap:var(--sp-2);
  padding:var(--sp-2) var(--sp-2); border-radius:var(--r-1);
  color:var(--ink-800); text-decoration:none; }
.ivroll a:hover{ background:var(--surface-2); }
.ivroll .ivmark{ inline-size:1.2em; text-align:center; font-weight:700; }
.ivroll .ivname{ flex:1; font-weight:550; }
.ivroll li.done .ivmark{ color:var(--st-ok-fg, #1a7f4b); }
.ivroll li.open .ivmark{ color:var(--st-attention-fg); }
.ivroll li.none{ opacity:.55; }

/* ── §9 — the current step must be UNMISTAKABLE ──────────────────────────
   A tiny dot was not enough: the operator must be able to glance at the page
   and know which step they are on. Filled ground, strong border, heavier text
   and a leading marker — four signals, none of them colour alone, so it also
   survives a monochrome print and a colour-vision difference. Logical
   properties throughout, so it reads identically in Arabic. */
.jrny.wiz .jstep.now{
  background:var(--pri-600, #1F5FB8); color:#fff;
  border:2px solid var(--pri-800, #17478B); border-radius:var(--r-2);
  padding-inline:var(--sp-3); padding-block:var(--sp-2);
  font-weight:700; box-shadow:0 1px 0 rgba(0,0,0,.18); }
.jrny.wiz .jstep.now .jname,
.jrny.wiz .jstep.now .jn,
.jrny.wiz .jstep.now .jstat{ color:#fff; }
.jrny.wiz .jstep.now .jn{
  background:#fff; color:var(--pri-800, #17478B);
  border-radius:999px; inline-size:1.6em; block-size:1.6em;
  display:inline-flex; align-items:center; justify-content:center; font-weight:800; }
/* Batch 1.D — the 4px white leading bar rendered as a stray glyph beside the
   current-step chip. The chip itself, the circled number and the written
   "You are here" already carry the state; the bar is removed. */

/* The RECOMMENDED step, where it is not the one the operator is on. A hint,
   deliberately quieter than the current-step treatment above — two different
   facts must not compete for the same emphasis. */
.jrny.wiz .jstep.rec{
  border:1px dashed var(--pri-600, #1F5FB8); border-radius:var(--r-2);
  padding-inline:var(--sp-2); font-weight:650; }


:root{
  --ic-check:url("data:image/svg+xml,%3Csvg xmlns%3D'http://www.w3.org/2000/svg' viewBox%3D'0 0 16 16'%3E%3Cpath d%3D'M3 8.5l3.2 3.2L13 5' fill%3D'none' stroke%3D'black' stroke-width%3D'1.8' stroke-linecap%3D'round' stroke-linejoin%3D'round'/%3E%3C/svg%3E");
  --ic-attention:url("data:image/svg+xml,%3Csvg xmlns%3D'http://www.w3.org/2000/svg' viewBox%3D'0 0 16 16'%3E%3Cpath d%3D'M8 2.5l6 11H2zM8 6.6v3.2M8 12.1v.01' fill%3D'none' stroke%3D'black' stroke-width%3D'1.8' stroke-linecap%3D'round' stroke-linejoin%3D'round'/%3E%3C/svg%3E");
  --ic-blocked:url("data:image/svg+xml,%3Csvg xmlns%3D'http://www.w3.org/2000/svg' viewBox%3D'0 0 16 16'%3E%3Cpath d%3D'M4 4l8 8M12 4l-8 8' fill%3D'none' stroke%3D'black' stroke-width%3D'1.8' stroke-linecap%3D'round' stroke-linejoin%3D'round'/%3E%3C/svg%3E");
  --ic-pending:url("data:image/svg+xml,%3Csvg xmlns%3D'http://www.w3.org/2000/svg' viewBox%3D'0 0 16 16'%3E%3Cpath d%3D'M8 1.8a6.2 6.2 0 1 1-6.2 6.2M8 4.6V8l2.4 1.6' fill%3D'none' stroke%3D'black' stroke-width%3D'1.8' stroke-linecap%3D'round' stroke-linejoin%3D'round'/%3E%3C/svg%3E");
  --ic-idle:url("data:image/svg+xml,%3Csvg xmlns%3D'http://www.w3.org/2000/svg' viewBox%3D'0 0 16 16'%3E%3Cpath d%3D'M3.4 8h9.2' fill%3D'none' stroke%3D'black' stroke-width%3D'1.8' stroke-linecap%3D'round' stroke-linejoin%3D'round'/%3E%3C/svg%3E");
  --ic-arrow:url("data:image/svg+xml,%3Csvg xmlns%3D'http://www.w3.org/2000/svg' viewBox%3D'0 0 16 16'%3E%3Cpath d%3D'M2.2 8h11M9.4 3.4L14 8l-4.6 4.6' fill%3D'none' stroke%3D'black' stroke-width%3D'1.8' stroke-linecap%3D'round' stroke-linejoin%3D'round'/%3E%3C/svg%3E");
  --ic-open:url("data:image/svg+xml,%3Csvg xmlns%3D'http://www.w3.org/2000/svg' viewBox%3D'0 0 16 16'%3E%3Cpath d%3D'M6.4 3H3v10h10V9.6M9.6 3H13v3.4M13 3L7.6 8.4' fill%3D'none' stroke%3D'black' stroke-width%3D'1.8' stroke-linecap%3D'round' stroke-linejoin%3D'round'/%3E%3C/svg%3E");
  --ic-clone:url("data:image/svg+xml,%3Csvg xmlns%3D'http://www.w3.org/2000/svg' viewBox%3D'0 0 16 16'%3E%3Cpath d%3D'M5.6 5.6V3H13v7.4h-2.6M3 5.6h7.4V13H3z' fill%3D'none' stroke%3D'black' stroke-width%3D'1.8' stroke-linecap%3D'round' stroke-linejoin%3D'round'/%3E%3C/svg%3E");
  --ic-download:url("data:image/svg+xml,%3Csvg xmlns%3D'http://www.w3.org/2000/svg' viewBox%3D'0 0 16 16'%3E%3Cpath d%3D'M8 2.2v7.6M4.8 6.6L8 9.8l3.2-3.2M2.6 12.4h10.8' fill%3D'none' stroke%3D'black' stroke-width%3D'1.8' stroke-linecap%3D'round' stroke-linejoin%3D'round'/%3E%3C/svg%3E");
  --ic-admin:url("data:image/svg+xml,%3Csvg xmlns%3D'http://www.w3.org/2000/svg' viewBox%3D'0 0 16 16'%3E%3Cpath d%3D'M8 1.8l5.4 2.2v3.4c0 3.4-2.2 5.6-5.4 6.8-3.2-1.2-5.4-3.4-5.4-6.8V4z' fill%3D'none' stroke%3D'black' stroke-width%3D'1.8' stroke-linecap%3D'round' stroke-linejoin%3D'round'/%3E%3C/svg%3E");
  --ic-info:url("data:image/svg+xml,%3Csvg xmlns%3D'http://www.w3.org/2000/svg' viewBox%3D'0 0 16 16'%3E%3Cpath d%3D'M8 1.8a6.2 6.2 0 1 1 0 12.4A6.2 6.2 0 0 1 8 1.8zM8 7.2v4M8 4.6v.01' fill%3D'none' stroke%3D'black' stroke-width%3D'1.8' stroke-linecap%3D'round' stroke-linejoin%3D'round'/%3E%3C/svg%3E");
  --ic-document:url("data:image/svg+xml,%3Csvg xmlns%3D'http://www.w3.org/2000/svg' viewBox%3D'0 0 16 16'%3E%3Cpath d%3D'M4 1.8h5.4L13 5.4V14.2H4zM9.4 1.8v3.6H13M6 8.4h4.6M6 10.8h4.6' fill%3D'none' stroke%3D'black' stroke-width%3D'1.8' stroke-linecap%3D'round' stroke-linejoin%3D'round'/%3E%3C/svg%3E");
  --ic-map:url("data:image/svg+xml,%3Csvg xmlns%3D'http://www.w3.org/2000/svg' viewBox%3D'0 0 16 16'%3E%3Cpath d%3D'M2.6 3.8L6 2.4l4 1.6 3.4-1.4v10l-3.4 1.4-4-1.6-3.4 1.4zM6 2.4v10.2M10 4v10.2' fill%3D'none' stroke%3D'black' stroke-width%3D'1.8' stroke-linecap%3D'round' stroke-linejoin%3D'round'/%3E%3C/svg%3E");
}

/* ── Batch 4.D — the RCOS icon language ─────────────────────────────────
   One coherent inline set: 1em square, drawn from currentColor through an
   SVG mask, aria-hidden in markup (the words always carry the meaning),
   consistent 1.8 stroke. No icon font, no dependency, no per-platform
   emoji/glyph variance. */
.ic{
  display:inline-block; inline-size:1em; block-size:1em; flex:none;
  vertical-align:-0.15em; background:currentColor;
  -webkit-mask:var(--ic) center / contain no-repeat;
  mask:var(--ic) center / contain no-repeat;
}
.ic-check{ --ic:var(--ic-check); }
.ic-attention{ --ic:var(--ic-attention); }
.ic-blocked{ --ic:var(--ic-blocked); }
.ic-pending{ --ic:var(--ic-pending); }
.ic-idle{ --ic:var(--ic-idle); }
.ic-arrow{ --ic:var(--ic-arrow); }
.ic-open{ --ic:var(--ic-open); }
.ic-clone{ --ic:var(--ic-clone); }
.ic-download{ --ic:var(--ic-download); }
.ic-admin{ --ic:var(--ic-admin); }
.ic-info{ --ic:var(--ic-info); }
.ic-document{ --ic:var(--ic-document); }
.ic-map{ --ic:var(--ic-map); }
/* a direction-bearing icon mirrors on an RTL page; marks do not */
[dir="rtl"] .ic-arrow{ transform:scaleX(-1); }
/* the chevron is the arrow icon; the old text glyph is retired */
.chev{ display:inline-block; inline-size:1em; block-size:1em; flex:none;
  vertical-align:-0.15em; background:currentColor;
  -webkit-mask:var(--ic-arrow) center / contain no-repeat;
  mask:var(--ic-arrow) center / contain no-repeat; }
[dir="rtl"] .chev{ transform:scaleX(-1); }
/* the dashboard attention line under a status pill */
.meta.attn{ color:var(--st-attention-fg); font-weight:600; margin-top:2px; }
/* Batch 4.C — the actions column: never wrapped, never clipped, end-aligned */
td.t-actions{ text-align:end; white-space:nowrap; }
th.t-actions{ text-align:end; }


/* ── ER2 §2 — the Dashboard's stable proportional grid ──────────────────
   table-layout:fixed + declared proportions: the columns align vertically
   on every row no matter how long a status label or a next-action sentence
   runs. The proportions are of the CONTENT width, so the same grid holds
   at 1280, 1440, 1920 and ultrawide. Nothing about what a column SAYS is
   decided here — governed status meaning is untouched. */
.dash-grid{ table-layout:fixed; inline-size:100%; }
.dash-grid th:nth-child(1), .dash-grid td:nth-child(1){ inline-size:24%; }
.dash-grid th:nth-child(2), .dash-grid td:nth-child(2){ inline-size:12%; }
.dash-grid th:nth-child(3), .dash-grid td:nth-child(3){ inline-size:16%; }
.dash-grid th:nth-child(4), .dash-grid td:nth-child(4){ inline-size:34%; }
.dash-grid th:nth-child(5), .dash-grid td:nth-child(5){ inline-size:14%; }
.dash-grid td{ vertical-align:top; overflow-wrap:break-word; }
.dash-grid .pill{ white-space:normal; }          /* a long governed label wraps in place */
.dash-grid .nextcell{ display:flex; flex-direction:column; gap:var(--sp-1); }
.dash-grid .nextlabel{ min-block-size:1.2em; }
.dash-grid .nextbtn .btn{ white-space:nowrap; }   /* the primary control never wraps */


/* ═══ PHASE C — BATCH C1 FOUNDATION (approved 29 Aug 2026) ═══════════════
   The approved Phase C design system: D2 "Signal & Flight-Path" icon
   family (inline SVG sprite in app.html — navy geometry + ONE teal signal
   element), three icon presentation scales, card/tile primitives, the
   single project-orientation component, and the zone grid for wide
   surfaces. Semantics decided elsewhere; this block only presents.      */

/* ── the D2 icon family: base + three scales ──────────────────────────
   .d2       inline/table/nav scale (1.05em, restrained)
   .d2-btn   button/card-header scale (20px)
   .d2-tile  module-tile scale (26px inside a 44px chip)
   Geometry inherits currentColor; the one signal element is drawn by the
   sprite in teal (class d2a inside the symbol). Direction-bearing icons
   mirror under RTL via .d2-flip. */
.d2{ inline-size:1.05em; block-size:1.05em; flex:none; vertical-align:-0.18em; }
.d2-btn{ inline-size:20px; block-size:20px; flex:none; }
.d2-tile{ inline-size:26px; block-size:26px; flex:none; }
svg.d2, svg.d2-btn, svg.d2-tile{ overflow:visible; }
[dir="rtl"] .d2-flip{ transform:scaleX(-1); }

/* the icon chip — the module-tile presentation container (D3-influenced
   shelf presence carrying the SAME D2 glyph, per the ruling) */
.chip2{
  inline-size:44px; block-size:44px; border-radius:var(--r-2); flex:none;
  display:grid; place-items:center;
  background:linear-gradient(160deg, var(--surface-2), var(--pri-soft));
  border:1px solid var(--line-200); color:var(--pri-600);
}
.chip2.gov{ background:linear-gradient(160deg,#F4F1FA,#EAE4F5); color:#5B3E96;
  border-color:#DED5EE; }

/* ── card/tile primitives ─────────────────────────────────────────────── */
.card{ box-shadow:var(--shadow-1); }
.card.quiet{ box-shadow:none; }
/* the hero card: the ONE authoritative next action */
.card.hero{ border-inline-start:4px solid var(--st-attention-fg); }

.tilegrid{ display:grid; grid-template-columns:repeat(2,1fr); gap:var(--sp-5); }
@media (min-width:1600px){ .tilegrid{ grid-template-columns:repeat(3,1fr); } }
@media (min-width:2200px){ .tilegrid{ grid-template-columns:repeat(4,1fr); } }
.tile2{
  display:flex; flex-direction:column; gap:var(--sp-3); margin:0;
  min-block-size:150px;
  transition:border-color .15s ease, box-shadow .15s ease, transform .15s ease;
}
.tile2:hover{ border-color:var(--blue-500); box-shadow:var(--shadow-2); }
.tile2 .trow{ display:flex; align-items:center; gap:var(--sp-3); }
.tile2 .trow h2{ margin:0; border:0; padding:0; font-size:1.02rem; flex:1; min-inline-size:0; }
.tile2 .tdesc{ margin:0; flex:1; }
.tile2 .tact{ display:flex; justify-content:flex-end; border-block-start:1px solid var(--line-100);
  padding-block-start:var(--sp-2); }

/* section heading over a tile group */
.secttl{ display:flex; align-items:center; gap:var(--sp-2);
  margin:var(--sp-7) 0 var(--sp-2); font-size:var(--fs-xl); font-weight:650;
  color:var(--navy-900); }
.secttl:first-of-type{ margin-block-start:var(--sp-4); }
.seccap{ color:var(--ink-500); font-size:var(--fs-md); margin:0 0 var(--sp-4); }

/* ── the zone grid: main work + context rail on wide surfaces ─────────── */
.zones{ display:grid; grid-template-columns:1fr; gap:var(--sp-5); align-items:start; }
.zones .zmain, .zones .zrail{ display:flex; flex-direction:column; gap:var(--sp-5); min-inline-size:0; }
@media (min-width:1600px){ .zones{ grid-template-columns:2fr 1fr; } }
@media (min-width:2200px){ .zones{ grid-template-columns:7fr 5fr; } }

/* ── the single orientation component ─────────────────────────────────
   The five-step wizard rail stays the prominent instrument (unchanged
   semantics). The ten-stage lifecycle detail is SUBORDINATED into a quiet
   disclosure INSIDE the same block: per-stage deep links kept, capability
   -gap placeholders kept, frozen wording verbatim (PHASEC-02 guarantees). */
details.stagedet > summary{
  cursor:pointer; list-style:none; display:flex; align-items:center; gap:var(--sp-2);
  color:var(--ink-500); font-size:var(--fs-sm); font-weight:600;
  padding-block:var(--sp-2);
}
details.stagedet > summary::-webkit-details-marker{ display:none; }
details.stagedet > summary::before{
  content:''; inline-size:.9em; block-size:.9em; flex:none; background:currentColor;
  -webkit-mask:var(--ic-arrow) center / contain no-repeat;
  mask:var(--ic-arrow) center / contain no-repeat;
  transition:transform .15s ease;
}
[dir="rtl"] details.stagedet > summary::before{ transform:scaleX(-1); }
details.stagedet[open] > summary::before{ transform:rotate(90deg); }
details.stagedet > summary:hover{ color:var(--navy-700); }
details.stagedet .jrny{ padding-block-start:var(--sp-2); }

/* ── the hero next-action composition (shell .bact, promoted) ──────────
   PHASE C (C3 correction §3) — SEMANTIC hero color: amber is never
   decorative. An open authoritative item → attention amber; the all-clear
   / positive message → neutral-positive. (Blocked/error surfaces carry
   their own st-blocked treatment where the engines say so.) */
.bact{ display:flex; align-items:center; gap:var(--sp-2); flex-wrap:wrap; }
.card .bact{ border-radius:var(--r-2); padding:var(--sp-3) var(--sp-4);
  background:var(--surface-2); border:1px solid var(--line-200); }
.card .bact-attn{ background:var(--st-attention-bg); border-color:var(--st-attention-line); }
.card .bact-ok{ background:var(--st-ready-bg); border-color:var(--st-ready-line); }

/* ── quiet capability rows (replaces full-card placeholders) ──────────── */
.qrow{ display:flex; align-items:center; gap:var(--sp-3);
  border:1px solid var(--line-200); border-radius:var(--r-2);
  background:var(--surface); padding:var(--sp-2) var(--sp-4);
  color:var(--ink-500); font-size:var(--fs-md); }
.qrow .qt{ font-weight:650; color:var(--ink-600); }
.qrow .pill{ margin-inline-start:auto; }

/* ── D2 signal micro-interaction (approved: one short draw on hover,
     navy geometry stable, nothing continuous) ─────────────────────────── */
.tile2 .d2a, #nav a .d2a{ transition:none; }
@media (prefers-reduced-motion: no-preference){
  .tile2:hover .chip2 svg .d2a,
  #nav a:hover .d2a{
    stroke-dasharray:60; stroke-dashoffset:60;
    animation:d2signal .35s ease forwards;
  }
  @keyframes d2signal{ to{ stroke-dashoffset:0; } }
}

/* ── PHASE C (Batch C2) — dashboard cell composition ──────────────────── */
.dash-grid td.t-short, .dash-grid td .meta{ white-space:normal; }   /* composition, never truncation */
.dash-grid td.dtr{ text-align:start; font-variant-numeric:tabular-nums lining-nums; }
.pcell{ display:flex; gap:var(--sp-2); align-items:flex-start; min-inline-size:0; }
/* PHASE C (C3 correction §4) — same D2 glyph, stronger small-context
   presence: 20px and navy-600 on active rows so the mark is recognizable
   without becoming noise; archived rows stay dim by meaning. */
.pcell > .d2{ margin-block-start:2px; inline-size:20px; block-size:20px; color:var(--accent-ic); }
.pcell .pcol{ min-inline-size:0; }
.pcell > .d2.d2-dim, .d2-dim{ color:var(--ink-400); }

/* ── PHASE C (Batch C2) — card headers carry a D2 mark ────────────────
   The icon leads, the label follows, the state/action sits at the end.
   (The previous space-between geometry separated an icon from its own
   title; flex-start + an auto margin on the first trailing control keeps
   icon+title as one unit and the controls end-aligned as before.) */
.card > h2{ justify-content:flex-start; }
.card > h2 > :is(.btn,.pill,.prov){ margin-inline-start:auto; }
.card > h2 > :is(.btn,.pill,.prov) ~ :is(.btn,.pill,.prov){ margin-inline-start:0; }
.card > h2 > svg{ color:var(--accent-ic); flex:none; }

/* ── PHASE C — the stage-detail disclosure visually joins the orientation
     card above it: one orientation component, two depths. ─────────────── */
.card.stagedet{
  margin-block-start:calc(-1 * var(--sp-6));
  border-start-start-radius:0; border-start-end-radius:0;
  padding-block-start:var(--sp-2);
  box-shadow:var(--shadow-1);
}

/* ── PHASE C (C3 correction §2) — the status composition component ─────
   Pill carries the SHORT state; the explanation is a caption OUTSIDE the
   pill. The two halves together are the governed sentence verbatim; the
   full sentence rides on the component as title + accessible label. */
.stcombo{ display:inline-flex; flex-direction:column; align-items:flex-start; gap:3px; min-inline-size:0; }
.stcombo .pill{ white-space:normal; }        /* a long STATE half may still wrap in place */
.stcombo .stmeta{ margin:0; font-size:var(--fs-sm); color:var(--ink-500); line-height:1.4; }
td .stcombo{ max-inline-size:100%; }
.page-head .stcombo, .pagehead .stcombo{ align-items:flex-start; }

/* ── PHASE C (Batch C3) — the page identity mark ──────────────────────── */
.page-head{ align-items:flex-start; }
.page-head .pagemark{ margin-block-start:2px; margin-inline-end:var(--sp-1); }
@media (max-width:760px){ .page-head .pagemark{ display:none; } }

/* ── PHASE C (Batch C3 §6) — Projects table polish ─────────────────────
   The classification/date cells wrap inside their columns instead of
   truncating; status cells host the composition component start-aligned.
   Presentation only — columns, order and meanings unchanged. */
.desk-only td.t-short, .desk-only td.t-status{ white-space:normal; }
.desk-only td.t-status{ text-align:start; }
.desk-only th.t-status{ text-align:start; }

/* the page-head with an identity mark: chip · title block · action end.
   The TITLE block claims the remaining inline space (margin-inline-end:auto)
   so it always hugs its mark; any trailing action lands at the end — and a
   head with no action never drifts. */
.page-head{ justify-content:flex-start; }
.page-head > div:first-child{ margin-inline-end:auto; }     /* unmarked heads */
.page-head .pagemark + div{ margin-inline-end:auto; }        /* marked heads  */

/* ── PHASE C er6 §2 — dashboard status hierarchy ───────────────────────
   The quiet open-items note under a POSITIVE state pill: visible, neutral,
   subordinate — project actions, not a contradiction of the state. */
.meta.open-note{ color:var(--ink-600); font-weight:500; margin-top:2px; }


/* ═══ PHASE C — BATCH C4 (operational project surfaces; approved 30 Aug) ═══
   Selective application for operational clarity — not decoration. Frozen
   semantics everywhere: these rules only present states that already exist. */

/* ── the journey rail stays the orientation instrument, one step quieter
     than the work surface (PO C4 rail rule) ──────────────────────────── */
.card:has(#wizrail), .card:has(.jrny.wiz){ box-shadow:none; }

/* ── OPERATIONAL INTERVIEW — the highest-priority readability surface ── */
/* group headers scan as bands: mark + frozen title + verdict + count */
.ivsec .ghead{
  background:var(--surface-2); border:1px solid var(--line-100);
  border-radius:var(--r-2); padding:var(--sp-3) var(--sp-4);
  margin-block-end:var(--sp-4);
}
.ivsec .gtitle{ display:flex; align-items:center; gap:var(--sp-2); }
.ivsec .gtitle svg{ color:var(--accent-ic); flex:none; }
/* the operator's decision already leads via the er1 rule (.q > .qtext at
   --fs-lg/600, app.html); supporting material steps back a size here. */
.q .meta{ font-size:var(--fs-sm); }
/* the ONE next unanswered question is unmistakable without shouting */
.q.next{
  background:var(--blue-100); border:1px solid var(--st-progress-line);
  border-radius:var(--r-2); padding-inline:var(--sp-4);
  margin-inline:calc(-1 * var(--sp-2));
}
/* an ANSWERED choice question is recognizable at a glance — read from the
   already-selected option (no semantic state added, nothing stored) */
.q:has(> .opts .opt.on){
  border-inline-start:3px solid var(--st-ready-line);
  padding-inline-start:var(--sp-4);
}
.q:has(> .opts .opt.on) > .qtext::before{
  content:''; display:inline-block; inline-size:.85em; block-size:.85em;
  margin-inline-end:6px; background:var(--st-ready-fg); vertical-align:-1px;
  -webkit-mask:var(--ic-check) center / contain no-repeat;
  mask:var(--ic-check) center / contain no-repeat;
}
/* section index marks in the product icon language, state-tinted */
.ivroll .ivmark{ display:inline-flex; }
.ivroll .ivmark.ok{ color:var(--st-ready-fg); }
.ivroll .ivmark.prog{ color:var(--st-progress-fg); }
.ivroll .ivmark.neu{ color:var(--ink-400); }
.ivroll li.done .ivname{ color:var(--ink-500); }

/* ── REVIEW & GACA — the final operational decision surface ───────────── */
.task-h3{ display:flex; align-items:center; gap:var(--sp-2);
  font-size:var(--fs-md); font-weight:650; color:var(--navy-900);
  border-block-end:1px solid var(--line-100); padding-block-end:var(--sp-2); }
.task-h3 svg{ color:var(--accent-ic); flex:none; }
.task-h3 .gcount{
  margin-inline-start:auto; min-inline-size:22px; text-align:center;
  font-size:var(--fs-sm); font-weight:650; color:var(--st-attention-fg);
  background:var(--st-attention-bg); border:1px solid var(--st-attention-line);
  border-radius:var(--r-pill); padding:1px var(--sp-2);
}

/* ── card headers that carry a D2 mark on the C4 surfaces ─────────────── */
.card > h2 > svg.d2-btn{ inline-size:18px; block-size:18px; }


/* ═══ PHASE C — BATCH C5: the controlled-document workspace ══════════════ */

/* one lifecycle composition per document */
.doclife{ display:flex; flex-direction:column; gap:3px; min-inline-size:0; }
.doclife-row{ display:flex; gap:6px; flex-wrap:wrap; align-items:center; }

/* the document group: current revision leads, history one disclosure away */
.docgrid{ display:grid; grid-template-columns:1fr; gap:var(--sp-4); }
@media (min-width:1600px){ .docgrid{ grid-template-columns:repeat(2,1fr); } }
@media (min-width:2600px){ .docgrid{ grid-template-columns:repeat(3,1fr); } }
.docgroup{ padding:var(--sp-4) var(--sp-5); }
.dg-head{ display:flex; align-items:center; gap:var(--sp-4); flex-wrap:wrap; }
.dg-head > svg{ color:var(--accent-ic); flex:none; }
.dg-title{ flex:1 1 240px; min-inline-size:0; }
.dg-life{ flex:0 1 auto; min-inline-size:0; }
.dg-cur{ text-align:end; flex:none; }
.dg-act{ flex:none; }
.dg-hist{ margin-block-start:var(--sp-3); border-block-start:1px solid var(--line-100);
  padding-block-start:var(--sp-2); }
.dg-hist > summary{ cursor:pointer; font-size:var(--fs-sm); color:var(--ink-600);
  inline-size:fit-content; }
.dg-hist0{ margin-block-start:var(--sp-2); }
/* superseded history rows read subordinate; the current row leads by weight */
.dg-hist .table-scroll{ margin-block-start:var(--sp-2); }
.dg-hist td{ font-size:var(--fs-sm); }

/* §9 quiet capability rows: the gap sentence wraps inside the row */
.qrow{ flex-wrap:wrap; }
.qrow .qrow-gap{ flex:1 1 100%; margin:0; }
.sigok{ margin-inline-start:var(--sp-3); color:var(--st-ready-fg); font-size:var(--fs-xs);
  display:inline-flex; align-items:baseline; gap:3px; }
.sigok .ic{ inline-size:.85em; block-size:.85em; }

/* ══ PHASE C6 — the Command Center (PO final ruling, 30 Aug 2026) ═══════
   Composition only: every number in these blocks is computed live in
   dashboard() from /api/projects and /api/organization/status. Bars are
   proportional readings, never the only carrier — the count is always
   written beside its bar. */

/* the four summary tiles */
.cc-tiles{ display:grid; grid-template-columns:repeat(2,1fr); gap:var(--sp-4);
  margin-block-end:var(--sp-5); }
@media (min-width:1100px){ .cc-tiles{ grid-template-columns:repeat(4,1fr); } }
.cc-tile{ border:1px solid var(--line-100); box-shadow:var(--shadow-1); }
.cc-tile-head{ display:flex; align-items:center; gap:var(--sp-2); }
.cc-tile-head .d2{ inline-size:20px; block-size:20px; color:var(--accent-ic); flex:none; }
.cc-tile .v{ font-size:var(--fs-3xl); }

/* the panel grid: 1 column, 2 from 1100px, 3 on the wide tier. The
   attention card leads and spans where there is room. */
.cc-grid{ display:grid; grid-template-columns:1fr; gap:var(--sp-5);
  margin-block-end:var(--sp-2); align-items:start; }
@media (min-width:1100px){
  .cc-grid{ grid-template-columns:repeat(2,1fr); }
  .cc-attn{ grid-column:span 2; }
}
@media (min-width:1600px){
  .cc-grid{ grid-template-columns:repeat(3,1fr); }
  .cc-attn{ grid-column:span 2; }
}
.cc-grid .card{ margin:0; }
.cc-grid .card h2{ display:flex; align-items:center; gap:var(--sp-2); }

/* Needs Your Attention — category rows that are also the proportional
   next-actions chart */
.ccg{ border-block-start:1px solid var(--line-100); }
.ccg:first-of-type{ border-block-start:0; }
.ccg summary{ display:flex; align-items:center; gap:var(--sp-3);
  padding:var(--sp-3) 0; cursor:pointer; }
.ccg summary::-webkit-details-marker{ display:none; }
.ccg .ccg-label{ font-weight:600; color:var(--ink-900); flex:0 1 auto; min-inline-size:0; }
.ccg .ccg-bar{ flex:1 1 120px; block-size:8px; border-radius:var(--r-pill);
  background:var(--pri-soft); overflow:hidden; min-inline-size:60px; }
.ccg .ccg-fill{ display:block; block-size:100%; border-radius:var(--r-pill);
  background:var(--pri-600); }
.ccg .gcount{ flex:none; font-size:var(--fs-sm); font-weight:650;
  color:var(--pri-800); background:var(--pri-soft);
  border-radius:var(--r-pill); padding:1px var(--sp-3); }
.ccg-list{ list-style:none; margin:0 0 var(--sp-3); padding:0 0 0 var(--sp-2);
  display:grid; gap:var(--sp-1); }
@media (min-width:1100px){ .ccg-list{ grid-template-columns:repeat(2,1fr); } }
@media (min-width:2200px){ .ccg-list{ grid-template-columns:repeat(3,1fr); } }

/* labeled proportional bars (assessment & readiness) */
.ccbar-row{ display:grid; grid-template-columns:minmax(0,1.4fr) minmax(60px,1fr) auto;
  gap:var(--sp-3); align-items:center; padding-block:var(--sp-1); }
.ccbar-label{ font-size:var(--fs-md); color:var(--ink-700); min-inline-size:0; }
.ccbar{ block-size:8px; border-radius:var(--r-pill); background:var(--line-100); overflow:hidden; }
.ccbar-fill{ display:block; block-size:100%; border-radius:var(--r-pill);
  background:var(--pri-600); }
.ccbar.ok .ccbar-fill{ background:var(--st-ready-fg); }
.ccbar.warn .ccbar-fill{ background:var(--st-attention-fg); }
.ccbar-n{ font-size:var(--fs-sm); color:var(--ink-500);
  font-variant-numeric:tabular-nums; white-space:nowrap; }

/* the operations timeline */
.cctl{ list-style:none; margin:0; padding:0; }
.cctl li{ display:flex; gap:var(--sp-3); align-items:baseline;
  padding:var(--sp-2) 0; border-block-start:1px solid var(--line-100); }
.cctl li:first-child{ border-block-start:0; }
.cctl-date{ flex:none; font-weight:650; color:var(--ink-900);
  font-size:var(--fs-md); min-inline-size:7.5em; }
.cctl-acts{ display:flex; flex-wrap:wrap; gap:var(--sp-2) var(--sp-4); min-inline-size:0; }
.cctl-act{ display:inline-flex; align-items:baseline; gap:var(--sp-2); min-inline-size:0; }
/* rehearsal vs show: the WORD carries it; tone assists. */
.ccact{ font-size:var(--fs-xs); font-weight:650; letter-spacing:.03em;
  border-radius:var(--r-pill); padding:1px var(--sp-2);
  background:var(--st-idle-bg); color:var(--st-idle-fg);
  border:1px solid var(--st-idle-line); white-space:nowrap; }
.ccact.show{ background:var(--pri-soft); color:var(--pri-800);
  border-color:var(--nav-hairline); }

/* facts, sublists */
.cc-fact{ margin:0 0 var(--sp-2); font-size:var(--fs-md); font-weight:600;
  color:var(--ink-700); }
.cc-sub{ margin:var(--sp-4) 0 var(--sp-2); font-size:var(--fs-sm);
  text-transform:uppercase; letter-spacing:.06em; color:var(--ink-500); }
.cc-list{ list-style:none; margin:0; padding:0; display:grid; gap:var(--sp-2); }
.cc-list li{ min-inline-size:0; overflow-wrap:anywhere; }

/* ── PHASE C6 — global footer + About RCOS + final polish ─────────────── */

/* the footer: quiet ownership + the dynamic build tag (#buildTag moved
   here from the brand block; same element, same population). */
.appfoot{
  margin-block-start:var(--sp-8);
  padding:var(--sp-4) max(var(--shell-pad), calc((100vw - var(--page-wide) - 2 * var(--sp-5)) / 2));
  border-block-start:1px solid var(--nav-hairline);
  display:flex; align-items:center; gap:var(--sp-2);
  color:var(--ink-500); font-size:12px; letter-spacing:.015em;
  background:var(--surface);
}
.appfoot .sub{ color:var(--ink-500); }

/* the About popover: fixed under the sticky bar, so it is reachable with
   zero scrolling from any screen. */
.who .who-about{ margin-inline-end:var(--sp-1); }
.aboutpop{
  position:fixed; inset-block-start:calc(var(--topbar-h) + 10px);
  inset-inline-end:var(--sp-5); z-index:40;
  background:var(--surface); border:1px solid var(--line-200);
  border-radius:var(--r-3, 8px); box-shadow:var(--shadow-2);
  padding:var(--sp-5) var(--sp-5) var(--sp-4); min-inline-size:300px; max-inline-size:380px;
}
.aboutpop h3{ margin:0 0 var(--sp-3); }
.aboutpop .ab-row{ display:flex; justify-content:space-between; gap:var(--sp-4);
  padding-block:var(--sp-1); font-size:var(--fs-md); }
.aboutpop .ab-k{ color:var(--ink-500); flex:none; }
.aboutpop .ab-v{ font-family:var(--font-mono); font-size:var(--fs-sm);
  color:var(--ink-700); overflow-wrap:anywhere; text-align:end; }
.aboutpop .btn{ margin-block-start:var(--sp-3); }

/* polish (approved register): the portfolio-grid status capsule steps down
   one size — the row's fact hierarchy leads with the project, not the pill. */
.dash-grid td .pill{ font-size:var(--fs-xs); padding-block:1px; }

/* polish: ONE restrained Interview hierarchy improvement — the C4 band
   header carries a primary keel on its start edge, so section boundaries
   read at a glance (the same edge language the provenance chips use).
   Paint only: no layout, no scroll-behaviour change, semantics untouched.
   (A sticky-header variant was tried and REJECTED here: it disturbed the
   accepted answer-without-viewport-jump guarantee in uat-journeys A/§2.) */
.ivsec .ghead{ border-inline-start:3px solid var(--pri-600); }


/* ── C6-CM1 — live-UAT correction pass ─────────────────────────────────── */

/* §12 — the deep-link landing highlight: two quiet pulses of the focus
   ring's own colour, then gone. No layout impact, no second scroll. */
@keyframes dlpulse{
  0%{ box-shadow:0 0 0 0 rgba(47,128,237,.55); }
  70%{ box-shadow:0 0 0 9px rgba(47,128,237,0); }
  100%{ box-shadow:0 0 0 0 rgba(47,128,237,0); }
}
.dl-hit{ animation:dlpulse 1.1s ease-out 2; border-radius:var(--r-2); }
@media (prefers-reduced-motion: reduce){ .dl-hit{ animation:none;
  outline:2px solid var(--focus); outline-offset:2px; } }

/* §8 — lower composition: Recent Document Activity spans the full grid
   width on every multi-column tier, and lays its entries out in columns,
   so no conspicuous dead cell remains beside it. */
.cc-docs{ grid-column:1 / -1; }
@media (min-width:1100px){ .cc-docs .cc-list{ display:grid;
  grid-template-columns:repeat(2,1fr); gap:var(--sp-2) var(--sp-5); } }
@media (min-width:1600px){ .cc-docs .cc-list{ grid-template-columns:repeat(3,1fr); } }

/* §9 — the attention bar reads as a DISTRIBUTION of counts: count chip
   first, then a segmented unit bar (one segment per project, --u set
   inline). Never a continuous progress fill. */
.ccg .ccg-fill{
  background:repeating-linear-gradient(to right,
    var(--pri-600) 0,
    var(--pri-600) calc(100% / var(--u, 1) - 2px),
    transparent calc(100% / var(--u, 1) - 2px),
    transparent calc(100% / var(--u, 1)));
  border-radius:2px;
}
[dir="rtl"] .ccg .ccg-fill{
  background:repeating-linear-gradient(to left,
    var(--pri-600) 0,
    var(--pri-600) calc(100% / var(--u, 1) - 2px),
    transparent calc(100% / var(--u, 1) - 2px),
    transparent calc(100% / var(--u, 1)));
}

/* §10 — summary-card hierarchy, restrained: the D2 mark sits in a soft
   Direction-B chip, the number leads. No gradients shouting, no invented
   context. */
.cc-tile .cc-chip{
  inline-size:38px; block-size:38px; border-radius:var(--r-2); flex:none;
  display:grid; place-items:center;
  background:linear-gradient(160deg, var(--surface-2), var(--pri-soft));
  border:1px solid var(--nav-hairline);
}
.cc-tile .cc-chip .d2{ inline-size:20px; block-size:20px; color:var(--accent-ic); }
.cc-tile .v{ font-weight:700; letter-spacing:-.01em; }


/* ── C6 CLOSURE §3 — the resolution-context banner at a deep-link target.
   Attention-toned, quiet, and transient by construction: it is inserted
   only by a consumed deep-link navigation and vanishes on any re-render. */
.dl-ctx{
  display:flex; align-items:flex-start; gap:var(--sp-3);
  background:var(--st-attention-bg); border:1px solid var(--st-attention-line);
  border-inline-start:3px solid var(--st-attention-fg);
  border-radius:var(--r-2); padding:var(--sp-3) var(--sp-4);
  margin-block:var(--sp-2);
}
.dl-ctx .ic-attention{ margin-block-start:3px; flex:none;
  background-color:var(--st-attention-fg); }
.dl-ctx-body{ flex:1 1 auto; min-inline-size:0; }
.dl-ctx-title{ font-size:var(--fs-xs); font-weight:700; letter-spacing:.05em;
  text-transform:uppercase; color:var(--st-attention-fg); margin-block-end:2px; }
.dl-ctx-text{ font-size:var(--fs-md); color:var(--ink-700); overflow-wrap:anywhere; }
.dl-ctx .btn{ flex:none; align-self:center; }
.dl-ctx-row > td{ padding-block:var(--sp-2); }
