:root{
  --cpt-dark:#1F2124;
  --cpt-gold:#9E8344;
  --cpt-gold-hi:#AD8F4B;
  --cpt-gold-lo:#8E753D;
  --cpt-gold-line:#CBB88A;
  --cpt-gold-soft:#E0D4B8;
  --cpt-surface:#FFFFFF;
  --cpt-field:#FAFAF8;
  --cpt-border:#E5E5E5;
  --cpt-page:#F7F7F7;
  --cpt-req:#CE584C;
  --cpt-ink:#1F2124;
  --cpt-muted:#8A8880;
  --cpt-report-bar:#1F2124;
  --cpt-chip:34px;
  /* Floor raised from the original 84px now that every grid using this
     variable (.cpt-pool-diamond/.cpt-pool-grid2x4 below) sizes its columns
     with minmax(0, ...) rather than a bare fixed size - the grid shrinks
     below this on any viewport too narrow to fit it instead of overflowing,
     so raising the floor to sit inside the requested ~100-115px mobile
     range is safe: worst case on an unusually narrow device is a graceful
     size reduction, never horizontal scroll. */
  --cpt-diamond-cell:clamp(100px, 26vw, 150px);
  /* Tightened from clamp(8px, 3vw, 20px) - smaller gaps read as a tighter,
     more elegant group (still safe re: overflow, same minmax(0,...) grids
     as above, and a smaller gap only ever gives the cells MORE room, never
     less). */
  --cpt-diamond-gap:clamp(6px, 2.4vw, 16px);
  /* The 7-shape CONSCIOUS TEST diamond is 5 rows tall (vs. 3 for the other
     diamonds), so it's the one layout where viewport HEIGHT, not just
     width, is the binding constraint - min(vw, vh) sizing keeps all 5 rows
     on screen without scrolling on short viewports (landscape phones,
     small laptop windows) where a purely width-based size would overflow.
     Floor raised from 68px to sit inside the ~85-128px range the test
     owner asked for once these cards started showing the real uploaded
     shape images (vs. the smaller inline-SVG symbols before) - safe for
     the same reason --cpt-diamond-cell's floor was raised earlier: every
     grid using this variable sizes its columns/rows with minmax(0, ...),
     so a short/narrow viewport that can't fit 85px cells just shrinks them
     (and the page scrolls a little more), it never overflows. */
  --cpt-diamond7-cell:clamp(85px, min(22vw, 11.8vh), 128px);
  --cpt-diamond7-gap:clamp(10px, min(2.6vw, 1.6vh), 20px);
  /* .cpt-tabbar's own rendered height (8px pad + [8px+20px icon+2px gap+
     ~13px label+8px pad] + 8px pad) plus its bottom:14px offset from the
     viewport edge, measured against the live markup/CSS below - used by
     .cpt-wrap's bottom padding so stage content always clears the fixed
     nav, and again by env(safe-area-inset-bottom) for the home-indicator
     area on notched phones the tabbar's own bottom:14px doesn't account for. */
  --cpt-nav-h:82px;
}
.cpt-wrap{max-width:960px;margin:0 auto;padding:22px 16px calc(var(--cpt-nav-h) + 24px + env(safe-area-inset-bottom));overflow-x:hidden}
/* On narrow screens the empty side margin isn't just .cpt-wrap's own 16px
   padding - measured on the live page, most of it (~20px/side) actually
   comes from two THEME defaults that sit outside our control here: the
   browser's default 8px body margin (the theme never resets it) and the
   theme's .row grid wrapper this shortcode happens to render inside, which
   pins an explicit width (90% at this breakpoint, from a theme rule more
   specific than a plain .row override - confirmed by inspecting the live
   computed style, not by reading the theme's source, since overriding just
   max-width left the actual width unchanged). This file only loads on
   pages that contain this shortcode (see Plugin.php's has_shortcode()
   check), so it's safe to reset both here - :has() scopes each override
   precisely to when this component is the thing sitting inside them, so
   nothing else on the page (header/hero, any other .row) is affected; the
   !important on .row is needed to beat that more-specific theme rule. */
@media(max-width:560px){
  .cpt-wrap{padding-left:4px;padding-right:4px}
  body:has(#cpt-root){margin:0}
  .row:has(#cpt-root){width:100%!important;max-width:100%!important;margin-left:0!important;margin-right:0!important}
}
.cpt-wrap *{box-sizing:border-box}
.cpt-wrap h1,.cpt-wrap h2,.cpt-wrap h3{margin:0 0 .4em;line-height:1.3}
.cpt-muted{color:var(--cpt-muted);font-size:.9rem}
.cpt-eyebrow{letter-spacing:.14em;text-transform:uppercase;font-size:.85rem;color:var(--cpt-gold);font-weight:700}

/* The stage's instruction sentence (e.g. "اختر اللون الأكثر تفضيلاً...") is
   the ONLY heading cpt-app.js puts in #cpt-s-title now - the test's internal
   name never renders (see runStage() in cpt-app.js). Sized/weighted here
   explicitly rather than left to the generic .cpt-wrap h2 rule above, since
   this now holds a full sentence (not a 2-3 word test name): a clean,
   elegant question rather than a heavy headline, in the theme's own font
   (font-family: inherit, same as every other element in .cpt-wrap - no
   separate typeface introduced; font-weight:600 now actually renders as
   semibold rather than silently faking up to bold - see the real 600 face
   enqueued in Plugin.php), still visibly more prominent than the gold
   .cpt-eyebrow progress label above it via weight/size/color alone despite
   the lighter 600 weight and compact cap, kept deliberately contained
   (max 24px, ~780px wide) rather than stretching across the wider panel
   above, so it reads as an intentional question, not a banner headline. */
#cpt-s-title{font-size:clamp(22px,1.8vw,24px);font-weight:600;line-height:1.65;text-align:center;color:var(--cpt-ink);max-width:780px;margin:10px auto 28px}
/* Mobile sizing below is NOT a guess: measured against the theme's actual
   IBM Plex Sans Arabic (600) font file with a headless-Chrome render of this
   exact sentence in this exact container, then checked at every width the
   test owner asked for (360/390/400/430px) - font-size:16px alone was still
   3 lines at 360px, so the clamp's 3.3vw term steps it down to ~15px there
   while holding 16px (its ceiling) from ~390px up, which is what actually
   produces a clean 2-line wrap across the whole range instead of just one
   width. width:100%/max-width:none/the reduced 8px side padding below are
   what give the sentence enough room in the first place - the previous
   19px/740px-max-width version physically could not fit this sentence into
   2 lines at any mobile width, no matter how the rest of the page was tuned. */
@media(max-width:560px){#cpt-s-title{width:100%;max-width:none;padding-inline:8px;font-size:clamp(15px,3.3vw + 3px,16px);font-weight:600;line-height:1.65;letter-spacing:0;margin:14px auto 18px}}

.cpt-panel{background:var(--cpt-surface);border:1px solid var(--cpt-border);border-radius:20px;overflow:hidden;box-shadow:0 2px 14px rgba(31,33,36,.06);color:var(--cpt-ink)}
.cpt-panel > header{background:var(--cpt-dark);color:#fff;text-align:center;padding:16px;font-weight:700;font-size:1.1rem;border-bottom:3px solid var(--cpt-gold-line)}
.cpt-panel > .cpt-body{padding:36px}
/* 15px (not the 17px this used briefly) - measured together with
   #cpt-s-title's own padding-inline above, this is what actually gives the
   instruction sentence enough real width to land on 2 lines rather than 3
   at 360-430px; still inside the ~14-18px the test owner asked for. */
@media(max-width:560px){.cpt-panel > .cpt-body{padding:18px 15px}}

/* Welcome note above the intake fields. A quiet gold-tinted panel with a
   rule on the reading edge - border-inline-start, so it sits on the right
   in Arabic and the left in English without a second rule. Deliberately
   restrained: it introduces the form, it should not compete with it. */
.cpt-welcome{background:linear-gradient(180deg,#FBF8F1,#FDFCF9);border:1px solid var(--cpt-gold-soft);border-inline-start:3px solid var(--cpt-gold-line);border-radius:14px;padding:18px 22px;margin:0 0 26px}
.cpt-welcome p{margin:0;color:#5C5A54;font-size:.95rem;line-height:1.9;text-align:start}
.cpt-welcome p+p{margin-top:10px}
@media(max-width:560px){.cpt-welcome{padding:15px 16px;margin-bottom:20px;border-radius:12px}.cpt-welcome p{font-size:.88rem;line-height:1.85}}
.cpt-lead{text-align:center;color:var(--cpt-muted);margin:0 0 22px}
.cpt-wrap label{display:block;font-weight:700;font-size:.92rem;margin:0 0 7px;color:var(--cpt-ink)}
.cpt-wrap label .cpt-req{color:var(--cpt-req)}
.cpt-field{position:relative}
/* The icon is placed with a logical property (inset-inline-end, below), so
   the space reserved for it has to be logical too. This used to be a physical
   `padding:14px 44px 14px 14px`, which only lined up in LTR: in the Arabic
   RTL form the icon moved to the left edge while the 44px reserve stayed on
   the right, so text ran underneath the icon. padding-inline-end always
   reserves on whichever side the icon is actually on. LTR rendering is
   unchanged - inline-end is the right edge there either way. */
.cpt-field input,.cpt-field select{width:100%;padding:14px;padding-inline-end:44px;border:1px solid var(--cpt-border);border-radius:13px;font-family:inherit;font-size:1rem;background:var(--cpt-field);color:var(--cpt-ink)}
.cpt-field input:focus,.cpt-field select:focus{outline:none;border-color:var(--cpt-gold);background:#fff}
.cpt-field .cpt-ic{position:absolute;inset-inline-end:14px;top:50%;transform:translateY(-50%);color:var(--cpt-muted);pointer-events:none;display:flex}
.cpt-grid2{display:grid;grid-template-columns:1fr 1fr;gap:18px}
.cpt-grid2 > div{min-width:0}
@media(max-width:560px){.cpt-grid2{grid-template-columns:1fr;gap:14px}}
.cpt-fieldset{margin-bottom:18px}
/* The one field that spans the full row (job title - see TestShortcode).
   It needs no width rule of its own: .cpt-fieldset is already a block and
   .cpt-field input is already width:100%. The class only names the row so
   the intent stays readable, and so the row keeps the same 18px rhythm. */
.cpt-field-wide .cpt-field input{width:100%}

/* A phone number stays a left-to-right sequence even on the Arabic form, so
   the input carries dir="ltr" (TestShortcode) to keep '+20 100...' from
   being reordered. That makes the input's OWN inline-end the right edge,
   while the icon belongs to .cpt-field and follows the *page* direction -
   the two disagree in RTL, so the padding is spelled out physically here
   rather than logically. Digits stay flush with the row's start edge, which
   is where the text in every neighbouring field starts. */
[dir="rtl"] .cpt-field-tel input[type="tel"]{padding-left:44px;padding-right:14px;text-align:right}
[dir="ltr"] .cpt-field-tel input[type="tel"]{padding-left:14px;padding-right:44px;text-align:left}
/* The placeholder is the longest string the field ever shows; let it shrink
   a touch rather than collide with the icon on narrow screens. */
.cpt-field-tel input[type="tel"]::placeholder{font-size:.94em;opacity:.75}
/* The input is dir="ltr" for the value's sake, and Chrome lays the Arabic
   placeholder out in that LTR context - which parks it against the left edge
   while the typed value (text-align:right) sits against the right, so the
   text appears to jump the moment you start typing. Giving just the
   placeholder the form's own RTL direction keeps 'مثال:' leading and the
   number trailing, both on the same edge the value will use. */
[dir="rtl"] .cpt-field-tel input[type="tel"]::placeholder{direction:rtl;text-align:right}

.cpt-time-field{display:flex;align-items:center;gap:6px;padding-inline-end:44px;border:1px solid var(--cpt-border);border-radius:13px;background:var(--cpt-field);transition:border-color .15s,background .15s}
.cpt-time-field select{border:0;background:transparent;padding:14px 2px;font-family:inherit;font-size:1rem;color:var(--cpt-ink);flex:1;min-width:0;width:auto;appearance:none;-webkit-appearance:none;text-align:center;cursor:pointer}
.cpt-time-field select:focus{outline:none}
.cpt-time-field:focus-within{border-color:var(--cpt-gold);background:#fff}
.cpt-time-sep{color:var(--cpt-muted);font-weight:700}
.cpt-dp-anchor{position:relative}
.cpt-field input[readonly]{cursor:pointer}
.cpt-dp-panel{position:fixed;z-index:9999;width:304px;background:#fff;border-radius:20px;box-shadow:0 20px 50px rgba(31,33,36,.22),0 2px 8px rgba(31,33,36,.08);overflow:hidden;box-sizing:border-box;font-family:'Cairo',system-ui,-apple-system,'Segoe UI',sans-serif}
.cpt-dp-panel *{box-sizing:border-box;opacity:1!important;visibility:visible!important}
.cpt-dp-head{display:flex;gap:8px;padding:16px 16px 14px;background:linear-gradient(180deg,#FDFBF6,#fff);border-bottom:1px solid var(--cpt-border)}
.cpt-wrap .cpt-dp-head select{flex:1;width:auto;padding:9px 30px 9px 12px;border:1px solid var(--cpt-border);border-radius:10px;background:#fff url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="%239E8344" stroke-width="2.2"><path d="M6 9l6 6 6-6"/></svg>') no-repeat left 8px center;background-size:14px;font-family:inherit;font-size:.86rem;font-weight:700;color:var(--cpt-ink);appearance:none;-webkit-appearance:none;cursor:pointer;transition:border-color .15s,box-shadow .15s}
.cpt-wrap .cpt-dp-head select:hover{border-color:var(--cpt-gold)}
.cpt-wrap .cpt-dp-head select:focus{outline:none;border-color:var(--cpt-gold);box-shadow:0 0 0 3px var(--cpt-gold-soft)}
.cpt-dp-body{padding:14px 16px 18px}
.cpt-dp-dow{display:grid;grid-template-columns:repeat(7,1fr);text-align:center;font-size:.66rem;color:var(--cpt-muted);font-weight:700;letter-spacing:.03em;margin-bottom:10px}
.cpt-dp-grid{display:grid;grid-template-columns:repeat(7,1fr);row-gap:5px;column-gap:2px}
.cpt-wrap .cpt-dp-grid button.cpt-dp-day{display:block;width:36px;height:36px;line-height:36px;margin:0 auto;background:none!important;border:0;border-radius:50%;padding:0;font-size:13px!important;font-weight:500;font-family:inherit;color:#1F2124!important;cursor:pointer;transition:background .12s,transform .1s;-webkit-text-fill-color:#1F2124}
.cpt-wrap .cpt-dp-grid button.cpt-dp-day:hover{background:var(--cpt-gold-soft)!important;transform:scale(1.06)}
.cpt-wrap .cpt-dp-grid button.cpt-dp-day:disabled{color:#DAD8D0!important;-webkit-text-fill-color:#DAD8D0;cursor:not-allowed}
.cpt-wrap .cpt-dp-grid button.cpt-dp-day:disabled:hover{background:none!important;transform:none}
.cpt-wrap .cpt-dp-grid button.cpt-dp-day.cpt-dp-sel{background:linear-gradient(180deg,var(--cpt-gold-hi),var(--cpt-gold-lo))!important;color:#fff!important;-webkit-text-fill-color:#fff;font-weight:700;box-shadow:0 4px 12px rgba(158,131,68,.45)}
.cpt-sd-panel{position:fixed;z-index:9999;max-height:280px;overflow-y:auto;background:#fff;border-radius:16px;box-shadow:0 20px 50px rgba(31,33,36,.22),0 2px 8px rgba(31,33,36,.08);border-top:3px solid var(--cpt-gold-line);padding:8px;box-sizing:border-box;font-family:'Cairo',system-ui,-apple-system,'Segoe UI',sans-serif}
.cpt-sd-panel *{box-sizing:border-box;opacity:1!important;visibility:visible!important}
.cpt-wrap .cpt-sd-panel button.cpt-sd-opt{display:block;width:100%;text-align:start;padding:10px 12px;background:none!important;border:0;border-radius:10px;font-size:14px!important;font-weight:400;font-family:inherit;color:#1F2124!important;-webkit-text-fill-color:#1F2124;cursor:pointer}
.cpt-wrap .cpt-sd-panel button.cpt-sd-opt:hover{background:var(--cpt-gold-soft)!important}
.cpt-sd-empty{padding:14px 12px;text-align:center;font-size:.86rem;color:var(--cpt-muted)}
.cpt-dropzone{border:2px dashed var(--cpt-border);background:var(--cpt-field);border-radius:18px;padding:34px 20px;text-align:center;cursor:pointer;transition:border-color .15s,background .15s}
.cpt-dropzone:hover,.cpt-dropzone.cpt-over{border-color:var(--cpt-gold);background:#FDFBF6}
.cpt-dropzone svg{color:var(--cpt-gold)}
.cpt-dropzone b{display:block;margin-top:10px;font-size:1rem}
.cpt-dropzone span{display:block;color:var(--cpt-muted);font-size:.82rem;margin-top:4px}
.cpt-dropzone img.cpt-prev{width:104px;height:104px;object-fit:cover;border-radius:50%;margin:0 auto 8px;display:block;box-shadow:0 0 0 3px var(--cpt-gold-soft)}

.cpt-actions{display:grid;grid-template-columns:1fr 150px;gap:14px;margin-top:24px}
@media(max-width:560px){.cpt-actions{grid-template-columns:1fr}}

/* ---------------- "Powered by HUMAN MAPPING SYSTEM" ----------------
   One block, two placements: under the intake form's action buttons
   (TestShortcode::render()) and at the bottom of the completion screen
   (showThankYou() in cpt-app.js). Both print the same markup from
   Branding::html(), so these rules style both.

   Deliberately NOT button-shaped: no fill, no border box, no pointer
   affordance - just a hairline rule separating it from the buttons above,
   a muted "Powered by" line, and the mark itself. The name is set in the
   report's own gold (--cpt-gold-lo) at a size below the form's body text
   so it reads as a credit line rather than competing with the content.

   The logo sits on a small black plate for the same reason the report
   header's does: the supplied HMS artwork has a solid black background, so
   it needs a deliberate frame to look intentional on a white card. It's an
   <img> at a fixed box with object-fit:contain, so its aspect ratio is
   preserved whatever artwork is dropped in later.

   dir="ltr" is set on the wrapper in PHP: "Powered by HUMAN MAPPING
   SYSTEM" is a Latin brand line and must read left-to-right even inside
   the Arabic (RTL) form. */
.cpt-hms{display:flex;flex-direction:column;align-items:center;gap:7px;margin-top:26px;padding-top:18px;border-top:1px solid var(--cpt-border);text-align:center}
.cpt-hms-label{font-size:.72rem;font-weight:500;letter-spacing:.1em;color:var(--cpt-muted);line-height:1;text-transform:uppercase}
/* The lockup carries its own black field, so the plate is sized to the image
   rather than padded around it - any padding would read as a border of a
   slightly different black. width caps the size on a wide card and shrinks
   with the viewport; height:auto keeps the 2.5:1 ratio at every width. */
.cpt-hms-logo{display:block;border-radius:10px;overflow:hidden;box-shadow:inset 0 0 0 1px var(--cpt-gold-line);line-height:0;max-width:100%}
.cpt-hms-logo img{display:block;width:min(260px,74vw);height:auto;border-radius:10px}
/* Completion screen copy: the success card is already centred and padded,
   so it only needs a little more breathing room from the two buttons above
   it than the form's copy does. */
.cpt-hms-success{margin-top:30px}
/* Phone-width: the lockup already scales with the viewport (74vw), so this
   only tightens the spacing around it. */
@media(max-width:560px){
  .cpt-hms{margin-top:22px;padding-top:16px;gap:8px}
  .cpt-hms-logo img{width:min(220px,78vw)}
}
.cpt-wrap button{font-family:inherit;font-size:1rem;cursor:pointer;border:0;border-radius:14px;padding:16px 20px;font-weight:700}
.cpt-btn-gold{background:linear-gradient(180deg,var(--cpt-gold-hi),var(--cpt-gold-lo));color:#fff;box-shadow:0 6px 16px rgba(158,131,68,.28);text-decoration:none;display:inline-flex;align-items:center;justify-content:center}
.cpt-btn-gold:hover{filter:brightness(1.05)}
.cpt-btn-out{background:#fff;color:var(--cpt-ink);border:1px solid var(--cpt-border);text-decoration:none;display:inline-flex;align-items:center;justify-content:center}
.cpt-btn-out:hover{border-color:var(--cpt-gold)}
.cpt-wrap button:focus-visible{outline:3px solid var(--cpt-gold-soft);outline-offset:2px}
.cpt-err{color:var(--cpt-req);font-size:.86rem;margin-top:12px;display:none;text-align:center}
.cpt-upload-status{margin-top:16px;text-align:center}
.cpt-upload-status #cpt-upload-text{display:block;font-size:.88rem;font-weight:700;color:var(--cpt-gold-lo);margin-bottom:8px}
.cpt-upload-bar{height:8px;border-radius:99px;background:var(--cpt-border);overflow:hidden}
.cpt-upload-bar i{display:block;height:100%;width:0;background:linear-gradient(180deg,var(--cpt-gold-hi),var(--cpt-gold-lo));transition:width .2s;border-radius:99px}
/* Intended for real disabled controls (the intake form's submit button
   mid-upload, etc.) - the stage-10 reference/locked colour card
   deliberately avoids the native `disabled` attribute so it never matches
   this rule; see .cpt-swatch-locked below. */
.cpt-wrap button:disabled{opacity:.65;cursor:not-allowed}
.cpt-btn-gold .cpt-spin{display:inline-block;width:16px;height:16px;border-radius:50%;border:2px solid rgba(255,255,255,.45);border-top-color:#fff;margin-inline-start:8px;vertical-align:-3px;animation:cpt-spin .7s linear infinite}
@keyframes cpt-spin{to{transform:rotate(360deg)}}

.cpt-tabbar{position:fixed;inset-inline:0;bottom:14px;margin:0 auto;max-width:560px;background:#fff;border-radius:22px;box-shadow:0 6px 22px rgba(31,33,36,.12);display:grid;grid-template-columns:repeat(5,1fr);padding:8px;z-index:40}
.cpt-tabbar a,.cpt-tabbar button{display:grid;place-items:center;gap:2px;padding:8px 2px;border-radius:15px;text-decoration:none;color:var(--cpt-muted);font-size:.72rem;font-weight:600;text-align:center;line-height:1.25}
/* The restart control is a <button>, so it arrives with a UA background,
   border and font of its own - stripped here so it is indistinguishable
   from the four links beside it. */
.cpt-tabbar button{background:none;border:0;font-family:inherit;cursor:pointer;-webkit-appearance:none;appearance:none}
.cpt-tabbar a.on{background:var(--cpt-gold-soft);color:#6E5B2C}
.cpt-tabbar a:hover,.cpt-tabbar button:hover{color:var(--cpt-gold-lo)}
.cpt-tabbar a:focus-visible,.cpt-tabbar button:focus-visible{outline:2px solid var(--cpt-gold);outline-offset:-2px}
/* Five labels in a 560px bar leaves ~104px each; on a narrow phone the
   labels are what overflow first, so they shrink before the bar does. */
@media(max-width:400px){.cpt-tabbar{max-width:calc(100vw - 20px)}.cpt-tabbar a,.cpt-tabbar button{font-size:.64rem;padding:8px 1px}}

.cpt-progress{display:flex;align-items:center;gap:10px;margin-bottom:10px}
.cpt-bar{flex:1;height:5px;background:var(--cpt-border);border-radius:99px;overflow:hidden}
.cpt-bar i{display:block;height:100%;background:var(--cpt-gold);transition:width .35s}
.cpt-pool{display:flex;flex-wrap:wrap;gap:16px;justify-content:center;margin:28px 0 8px}
/* Every grid below sizes its columns/rows with minmax(0, var(--cpt-*-cell))
   rather than a bare fixed size - on any viewport too narrow to fit the
   full-size cards at their intended size, the grid shrinks them down to
   fit instead of overflowing the panel (CSS Grid's normal behaviour for a
   flat fixed track size is to overflow its container, not shrink). This is
   what makes it safe to size --cpt-diamond-cell's floor for the ~100-115px
   mobile target without risking horizontal scroll on an unusually narrow
   device - graceful shrink is the worst case, never overflow. */
.cpt-pool-diamond{display:grid;direction:ltr;grid-template-columns:repeat(3,minmax(0,var(--cpt-diamond-cell)));grid-template-rows:repeat(3,minmax(0,var(--cpt-diamond-cell)));grid-template-areas:"tl . tr" ". c ." "bl . br";gap:var(--cpt-diamond-gap);justify-content:center;margin:28px auto 8px}
.cpt-pool-diamond .cpt-swatch{width:100%;height:100%;margin:0}
.cpt-pool-diamond .cpt-swatch[data-pos="tl"]{grid-area:tl}
.cpt-pool-diamond .cpt-swatch[data-pos="tr"]{grid-area:tr}
.cpt-pool-diamond .cpt-swatch[data-pos="c"]{grid-area:c}
.cpt-pool-diamond .cpt-swatch[data-pos="bl"]{grid-area:bl}
.cpt-pool-diamond .cpt-swatch[data-pos="br"]{grid-area:br}
.cpt-pool-grid2x4{display:grid;direction:ltr;grid-template-columns:repeat(2,minmax(0,var(--cpt-diamond-cell)));grid-template-rows:repeat(4,minmax(0,var(--cpt-diamond-cell)));grid-template-areas:"r1c1 r1c2" "r2c1 r2c2" "r3c1 r3c2" "r4c1 r4c2";gap:var(--cpt-diamond-gap);justify-content:center;margin:28px auto 8px}
/* Tighter top margin on mobile - the question's own mobile margin above
   (14px auto 18px) is already smaller than desktop's, so this pairs with
   it for a genuinely compact progress→question→cards composition instead
   of just shrinking the question and leaving the old desktop-sized gap
   before the cards untouched. */
@media(max-width:560px){.cpt-pool-diamond,.cpt-pool-grid2x4{margin-top:18px}}
.cpt-pool-grid2x4 .cpt-swatch{width:100%;height:100%;margin:0}
.cpt-pool-grid2x4 .cpt-swatch[data-pos="r1c1"]{grid-area:r1c1}
.cpt-pool-grid2x4 .cpt-swatch[data-pos="r1c2"]{grid-area:r1c2}
.cpt-pool-grid2x4 .cpt-swatch[data-pos="r2c1"]{grid-area:r2c1}
.cpt-pool-grid2x4 .cpt-swatch[data-pos="r2c2"]{grid-area:r2c2}
.cpt-pool-grid2x4 .cpt-swatch[data-pos="r3c1"]{grid-area:r3c1}
.cpt-pool-grid2x4 .cpt-swatch[data-pos="r3c2"]{grid-area:r3c2}
.cpt-pool-grid2x4 .cpt-swatch[data-pos="r4c1"]{grid-area:r4c1}
.cpt-pool-grid2x4 .cpt-swatch[data-pos="r4c2"]{grid-area:r4c2}
.cpt-pool-diamond7{display:grid;direction:ltr;grid-template-columns:repeat(3,minmax(0,var(--cpt-diamond7-cell)));grid-template-rows:repeat(5,minmax(0,var(--cpt-diamond7-cell)));grid-template-areas:". top ." "r2l . r2r" ". c ." "r4l . r4r" ". bottom .";gap:var(--cpt-diamond7-gap);justify-content:center;margin:14px auto 4px}
.cpt-pool-diamond7 .cpt-swatch{width:100%;height:100%;margin:0}
.cpt-pool-diamond7 .cpt-swatch[data-pos="top"]{grid-area:top}
.cpt-pool-diamond7 .cpt-swatch[data-pos="r2l"]{grid-area:r2l}
.cpt-pool-diamond7 .cpt-swatch[data-pos="r2r"]{grid-area:r2r}
.cpt-pool-diamond7 .cpt-swatch[data-pos="c"]{grid-area:c}
.cpt-pool-diamond7 .cpt-swatch[data-pos="r4l"]{grid-area:r4l}
.cpt-pool-diamond7 .cpt-swatch[data-pos="r4r"]{grid-area:r4r}
.cpt-pool-diamond7 .cpt-swatch[data-pos="bottom"]{grid-area:bottom}
.cpt-swatch{width:104px;height:104px;border-radius:14px;cursor:pointer;border:0;padding:0;transition:transform .2s ease,box-shadow .2s ease;position:relative}
/* Plain colour swatches (not .cpt-swatch-shape, styled separately below)
   get a shadow here on hover too - won't visibly show on the white card
   specifically, since its inline style="...box-shadow:inset 0 0 0 1px
   #DDD" (swatchHTML() in cpt-app.js, kept so it stays visible against the
   panel's own near-white background) always wins over this class rule
   regardless of specificity; the hover lift below still applies to it. */
.cpt-swatch:hover{transform:translateY(-3px);box-shadow:0 6px 16px rgba(31,33,36,.14)}
.cpt-swatch:active{transform:translateY(-1px) scale(.97)}
.cpt-swatch img{width:100%;height:100%;display:block;border-radius:14px}
/*
 * CONSCIOUS TEST cards only (.cpt-swatch-shape, added by swatchHTML() in
 * cpt-app.js when test.shape is true) - every other test's plain colour
 * swatch above is untouched. These are now the test owner's real uploaded
 * shape images (shapeImg() in cpt-app.js, via Stimuli::shape_image_urls()),
 * not a redrawn SVG/CSS approximation - each image already bakes in its
 * own background/framing, so this card gets no background or border of its
 * own (that would just be a second, redundant background behind an image
 * that already has one). border-radius+overflow:hidden only softens the
 * image's own square corners to match this design system's rounding
 * elsewhere - it doesn't touch the artwork itself, and at these images'
 * actual proportions (the drawn shape sits well inside its own margin,
 * confirmed by inspecting the uploaded files) that corner-round never
 * clips into the shape, only the plain background right at the corner.
 */
.cpt-swatch-shape{background:none;border:0;border-radius:16px;overflow:hidden;box-shadow:0 1px 3px rgba(31,33,36,.07);display:flex;align-items:center;justify-content:center;transition:transform .2s ease,box-shadow .2s ease}
.cpt-swatch-shape:hover{box-shadow:0 8px 20px rgba(31,33,36,.12)}
.cpt-shape-svg{width:100%;height:100%;display:block;object-fit:contain}
/*
 * "Selected" flash (see markSwatchLeaving() in cpt-app.js): a picked card
 * gets this gold ring for the same .3s its existing fade/slide-out
 * transition already runs, so a tap reads as a clear, premium confirmation
 * instead of the card just disappearing. Never covers the symbol itself -
 * only an outer ring/shadow, no overlay.
 */
.cpt-swatch-picked{border-color:var(--cpt-gold-hi);box-shadow:0 0 0 3px var(--cpt-gold-soft),0 8px 20px rgba(158,131,68,.28)}
/* Stage 10 (final_pick)'s excluded/reference card - the colour already
   ranked first in COLOUR RANKING, shown checked/locked rather than
   removed so the participant understands why it's unavailable
   (drawSinglePick() in cpt-app.js). Deliberately NOT the native `disabled`
   attribute - button:disabled below (used for the intake form's submit
   button) applies opacity:.65 to ANY disabled button in .cpt-wrap, which
   would wash this card's colour out; a native `disabled` button also picks
   up browser/OS default disabled-control rendering in some browsers on top
   of that. pointer-events:none here is what actually stops mouse/touch
   clicks from reaching it (paired with tabindex="-1" + aria-disabled in
   the markup for keyboard/assistive tech, and a capture-phase click/keydown
   guard in drawSinglePick() as a third layer) - this is still not the real
   enforcement either way, that's server-side
   (RestController::save_answer()'s single_pick branch, which rejects this
   exact colour regardless of what the client sends). No opacity/filter/
   overlay here on purpose - the test owner wants this card's colour shown
   exactly as picked, not washed out; the checkmark below is what marks it
   as the fixed reference, not a faded appearance. */
.cpt-swatch-locked{cursor:not-allowed;pointer-events:none;opacity:1}
.cpt-swatch-locked:hover,.cpt-swatch-locked:active{transform:none;box-shadow:none}
.cpt-swatch-check{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;font-size:clamp(2rem,5vw,3rem);font-weight:700;color:#fff;text-shadow:0 1px 3px rgba(0,0,0,.55)}
/* This strip reads as a sequence - first pick, second pick, third - so it
   has to run left-to-right whatever the page direction is. Left as a plain
   flex row it inherits dir="rtl" from .cpt-wrap on the Arabic side and the
   first choice lands on the right, i.e. the same data reading backwards.
   direction:ltr here is the same treatment .cpt-pool-diamond and
   .cpt-pair-fixed already use for layouts that must stay screen-literal. */
.cpt-picked{display:flex;flex-direction:row;direction:ltr;unicode-bidi:isolate;flex-wrap:wrap;gap:8px;justify-content:center;margin-top:20px;min-height:36px}
.cpt-mini{width:32px;height:32px;border-radius:8px;display:grid;place-items:center;font-size:.75rem;font-weight:700}
.cpt-mini img{width:100%;height:100%;border-radius:8px}
.cpt-mini-shape{background:none;border:0;border-radius:8px;overflow:hidden}
.cpt-mini-svg{width:100%;height:100%;display:block;object-fit:contain}
.cpt-pair{display:flex;gap:26px;justify-content:center;margin:32px 0}
.cpt-pair-fixed{direction:ltr}
.cpt-pair .cpt-swatch{width:150px;height:150px}
/* Only 2 cards side by side here (vs. 3-across for the diamond pools above),
   so there's comfortably enough width even on the narrowest phones to land
   inside the ~100-115px mobile target without needing minmax()'s shrink
   safety net - confirmed by the math (2 cards + 1 reduced gap fits well
   inside any phone width this component targets), not just left at its
   previous, oversized 132px. */
@media(max-width:520px){.cpt-pair{gap:18px}.cpt-pair .cpt-swatch{width:112px;height:112px}.cpt-swatch{width:78px;height:78px}}
/* Picked-card exit animation, shared by every "shrinking pool" stage
   (drawRank()/drawColorRank()/drawSinglePick() in cpt-app.js - mode/
   full_emo/conscious/color_rank/final_pick all use this same
   markSwatchLeaving() helper). More specific than the plain .cpt-swatch
   rule above so it gets its own transition timing instead of inheriting
   the hover-lift one. */
.cpt-swatch-leaving{transition:opacity .3s ease,transform .3s ease;opacity:0;transform:translateY(-14px) scale(.8)}
/* Stage/question entry fade (runStage() for every stage, drawPair() for
   each new pairwise question - see fadeInStageBody() in cpt-app.js). Kept
   short on purpose: this runs on every single step of the quiz, so it
   needs to read as "smooth" rather than as its own wait. */
#cpt-s-body{transition:opacity .2s ease}
#cpt-s-body.cpt-fade-enter{opacity:0}
.cpt-pause{text-align:center;padding:44px 0}
.cpt-count{font-size:4.5rem;font-weight:700;color:var(--cpt-gold);line-height:1}
/* Post-submission success card (showThankYou() in cpt-app.js) - replaces
   the participant-facing report entirely, not just visually: no report
   markup is built or fetched for this screen at all. Centered, generous
   padding on both breakpoints per spec; the cap keeps the confidentiality
   note's line length comfortable to read on wide desktop viewports without
   needing a separate desktop/mobile rule. Widened from 480px to 560px when
   the short "submitted successfully" pair was replaced by that one longer
   paragraph, so it settles into three or four full lines instead of six
   short ones. */
.cpt-success{text-align:center;padding:48px 20px;max-width:560px;margin:0 auto}
.cpt-success-icon{width:72px;height:72px;border-radius:50%;background:linear-gradient(180deg,var(--cpt-gold-hi),var(--cpt-gold-lo));color:#fff;display:grid;place-items:center;margin:0 auto 20px;font-size:2rem;font-weight:900;box-shadow:0 6px 16px rgba(158,131,68,.28)}
/* The confidentiality statement - this screen's only body copy. clamp()
   scales it between the phone and desktop ends on its own, so the
   max-width:560px block below doesn't need a second font-size for it, and
   the generous line-height/line-height-derived spacing keeps a paragraph of
   this length readable in both Arabic and English. */
.cpt-success p{margin:0;font-size:clamp(.98rem,.92rem + .35vw,1.12rem);color:var(--cpt-ink);line-height:1.85;max-width:52ch;margin-inline:auto}
/* Back-to-home + restart, side by side - two peer actions (unlike the
   intake screen's own primary/secondary 1fr/150px split that .cpt-actions
   defaults to), so this overrides just the column split for this context;
   the max-width:560px stacked-single-column rule on the base .cpt-actions
   rule already applies here too since it's the same class. */
.cpt-success .cpt-actions{grid-template-columns:1fr 1fr;margin-top:22px}
.cpt-success .cpt-btn-gold,.cpt-success .cpt-btn-out{padding:16px 24px;font-size:1.02rem}
/* .cpt-success .cpt-actions above (two classes) is MORE specific than the
   base .cpt-actions{grid-template-columns:1fr} mobile rule (one class), so
   without restating it here at the same specificity, that base mobile rule
   would lose and the two buttons would stay side by side even on a narrow
   phone - confirmed by actually rendering this at 390px before fixing it. */
@media(max-width:560px){.cpt-success{padding:36px 16px}.cpt-success .cpt-actions{grid-template-columns:1fr}.cpt-success .cpt-btn-gold,.cpt-success .cpt-btn-out{width:100%}}
/* Loading state for the in-flight answer request (disableStage() in
   cpt-app.js) - dims the stage body while pointer-events are already
   blocked, so a submission (especially the final one, right before this
   same body is replaced by .cpt-success above) visibly reads as
   "processing" instead of just looking unresponsive for that moment. */
#cpt-s-body.cpt-submitting{opacity:.55;transition:opacity .15s ease}

.cpt-report-tools{display:flex;gap:10px;flex-wrap:wrap;margin:0 0 16px}
.cpt-report-tools button,.cpt-report-tools a{padding:12px 18px;font-size:.92rem}
.cpt-sheet{background:#fff;padding:24px 22px 28px;border-radius:16px;box-shadow:0 2px 14px rgba(31,33,36,.06);color:var(--cpt-ink)}
.cpt-rhead{display:flex;align-items:center;justify-content:space-between;gap:12px;border-bottom:1px solid var(--cpt-border);padding-bottom:10px}
.cpt-logo{color:var(--cpt-gold);font-weight:900;font-size:1.35rem}
.cpt-rlogo{height:38px;width:auto}
.cpt-rtitle{text-align:center;min-width:0}
.cpt-rtitle b{display:block;color:var(--cpt-gold);font-size:.8rem;letter-spacing:.18em}
.cpt-rtitle span{font-size:.95rem;font-weight:600;letter-spacing:.04em}
/*
 * "Powered by" + the HMS - Human Mapping System mark, in the header slot
 * the plain-text "C.P.T" word mark used to occupy (ReportShortcode::
 * sheet_html()). The mark is sized at the same 38px as the left-hand
 * .cpt-rlogo - checked by rendering this header and zooming in, not
 * guessed: this artwork is an emblem ABOVE its own small "HMS" wordmark,
 * so anything under ~34px turns that wordmark into an unreadable smudge,
 * while the label above it stays a single tight line (line-height:1) so
 * the stacked block adds only its own ~12px to the header band.
 *
 * .cpt-brand-logo is a real container, not just an <img>: the supplied
 * HMS file is artwork on a solid black background, so it needs to sit on
 * a deliberate dark plate (rounded, thin gold hairline, matching the
 * report's own .cpt-pbar dark bar) to read as a branding panel instead of
 * a stray black square dropped on a white sheet. The img keeps its own
 * aspect ratio - height-driven with width:auto plus object-fit:contain,
 * never a fixed width/height pair that could stretch it - and max-width
 * caps a wider mark if this logo is ever swapped for a non-square one.
 */
.cpt-brand{display:flex;flex-direction:column;align-items:center;gap:4px;flex:0 0 auto;direction:ltr;text-align:center}
/* Sentence case on purpose - these words read as the quiet attribution
   "Powered by", not as a second heading competing with .cpt-rtitle beside
   it, which is also why the size stays well under that title's. */
.cpt-brand-label{font-size:.6rem;font-weight:600;letter-spacing:.06em;color:var(--cpt-muted);line-height:1;white-space:nowrap}
.cpt-brand-logo{display:inline-flex;border-radius:8px;overflow:hidden;box-shadow:inset 0 0 0 1px var(--cpt-gold-line);line-height:0}
.cpt-brand-logo img{height:52px;width:auto;max-width:none;display:block}
/* Phone/narrow admin modal: the three header items wrap onto their own
   lines and centre instead of squeezing the title, and the mark steps
   down one size - still above the ~34px legibility floor noted above. */
@media(max-width:560px){
  .cpt-rhead{flex-wrap:wrap;justify-content:center;gap:10px;text-align:center}
  .cpt-brand-logo img{height:44px}
}
.cpt-pbar{background:var(--cpt-report-bar);color:#fff;border-radius:12px;padding:12px 16px;text-align:center;margin-top:14px;display:flex;align-items:center;justify-content:center;gap:14px}
.cpt-pbar img{width:52px;height:52px;border-radius:50%;object-fit:cover;box-shadow:0 0 0 2px var(--cpt-gold-line)}
.cpt-nm{font-size:1.4rem;font-weight:700;line-height:1.2}
.cpt-meta{font-size:.78rem;opacity:.92}
.cpt-pbar.cpt-slim{padding:7px 16px;font-size:.76rem;margin-top:7px;display:block}
.cpt-rows{margin-top:22px}
.cpt-row{display:grid;grid-template-columns:150px 1fr;align-items:center;gap:12px;padding:10px 0;border-bottom:1px solid var(--cpt-border)}
.cpt-rlabel{font-weight:700;font-size:1.05rem;letter-spacing:.06em;color:var(--cpt-gold-lo);text-transform:uppercase;direction:ltr;text-align:start}
/* (.cpt-code - the gold "4-2"/"3-1" code badge that used to follow the
   BASIC/BELONGING/SELF/CHALLENGES/ASPIRATIONS row labels - was removed
   along with the markup that emitted it in ReportShortcode::ax_row().) */
.cpt-axhead{display:grid;grid-template-columns:150px 1fr;gap:12px;margin:2px 0 8px}
.cpt-axhead-cells{display:flex;gap:7px}
.cpt-axcol{width:56px;text-align:center;font-size:.62rem;font-weight:700;letter-spacing:.03em;color:var(--cpt-muted);line-height:1.3;text-transform:uppercase;direction:ltr}
.cpt-axrow-body{display:flex;align-items:center;gap:24px;flex-wrap:wrap}
.cpt-chips{display:flex;gap:7px;flex-wrap:wrap}
/*
 * FULL EMO TEST (ReportShortcode::sheet_html()): row1 and row3 are bare
 * '.cpt-emo-main' chip groups with nothing reserved before them, so they
 * start at the exact same x as every OTHER row in this report - MODE
 * TEST included. (An earlier version reserved an empty "extra" slot on
 * every row via a shared grid column, which kept all 3 FULL EMO rows
 * internally aligned with each other but pushed the whole block to the
 * right of MODE TEST's own start position - confirmed directly by
 * measuring both rows' real x-coordinates through the browser, not
 * assumed.)
 *
 * Row 2 is the one row with something extra: '.cpt-emo-row2' is a flex
 * row of [extra chip, main group], pulled left by margin-inline-start:
 * -(chip width + gap) - exactly the width the extra chip + its gap would
 * otherwise ADD, so row2's own main group lands back at the same shared
 * x-position as row1/row3/MODE TEST, while the extra chip (dragged left
 * along with the rest of its row) ends up further left than that shared
 * baseline instead of part of it. --cpt-emo-gap drives both the visible
 * gap AND the cancelling margin from one number, so they can't drift out
 * of sync if this is ever tuned again.
 */
.cpt-emo-block{display:flex;flex-direction:column;gap:7px;min-width:0}
.cpt-emo-row2{--cpt-emo-gap:12px;display:flex;align-items:center;gap:var(--cpt-emo-gap);min-width:0}
.cpt-emo-row2.cpt-emo-row2-has-extra{margin-inline-start:calc(-1 * (var(--cpt-chip) + var(--cpt-emo-gap)))}
.cpt-emo-extra{flex:0 0 auto}
/* flex-wrap:nowrap + overflow-x:auto guarantee a chip row can NEVER wrap
   into a vertical stack, even in a narrow admin modal/small phone - it
   scrolls horizontally in place instead. Applied to every FULL EMO row
   (not just row 2) since all three must stay horizontal on any width. */
.cpt-emo-main{min-width:0;flex-wrap:nowrap;overflow-x:auto;-webkit-overflow-scrolling:touch}
.cpt-chip{width:var(--cpt-chip);height:var(--cpt-chip);border-radius:3px;display:grid;place-items:center;font-size:.82rem;font-weight:700;flex:0 0 auto;position:relative}
.cpt-chip img{width:100%;height:100%;border-radius:3px}
.cpt-chip b{position:absolute;inset-inline-start:2px;top:0;font-size:.6rem;color:#fff;text-shadow:0 0 3px #000}
.cpt-cells{display:flex;gap:7px}
/*
 * Each cell shows every colour Scoring::analyze_pair_test() bucketed at
 * that win-count (ReportShortcode::ax_row()) - never forced down to one,
 * since an Irregular result can legitimately group 2-3 colours in a
 * single bucket. min-width/min-height keep a normal (single-colour, or
 * empty "—") cell exactly the size it always was; flex-wrap only kicks in
 * when a bucket actually holds more than fits on one line.
 */
.cpt-cellbox{min-width:56px;min-height:var(--cpt-chip);border-radius:3px;display:flex;flex-wrap:wrap;align-items:center;justify-content:center;gap:3px;padding:3px 4px;font-size:.7rem;color:#4A4855}
.cpt-cellbox .cpt-chip{width:22px;height:22px;font-size:.6rem;border-radius:2px}
.cpt-c1{background:#DCDCDC}.cpt-c2{background:#F6EEDB}.cpt-c3{background:#F3E1D2}.cpt-c4{background:#DEE7EE}
/*
 * Admin-only (see ReportShortcode::sheet_html()'s $is_admin_view) marker
 * next to an irregular test's own label - deliberately small/inline, not
 * a big warning banner, since this is a routine per-test data point for
 * staff reviewing a result, not an alarm.
 */
.cpt-irregular-flag{display:inline-block;margin-inline-start:8px;font-size:.62rem;font-weight:700;color:#9E5B00;background:#FDF0DA;border-radius:99px;padding:2px 9px;direction:rtl;letter-spacing:0;text-transform:none;vertical-align:middle}
.cpt-matrix{width:100%;border-collapse:collapse;margin-top:24px;font-size:.62rem;direction:ltr;table-layout:fixed}
.cpt-matrix th,.cpt-matrix td{border:1px solid #6E6C78;padding:4px 3px;text-align:center;height:30px}
.cpt-matrix th{background:#F1EFEA;font-size:.66rem}
.cpt-matrix td.cpt-k{text-align:start;font-weight:700;font-size:.6rem;line-height:1.25;padding:3px 5px}
.cpt-sep{border:0;width:6px;background:#fff;border-top:1px solid #fff;border-bottom:1px solid #fff}

@media print{
  body{background:#fff}
  .cpt-noprint,.cpt-tabbar{display:none!important}
  .cpt-wrap{padding:0;max-width:none}
  .cpt-sheet{box-shadow:none;padding:0;border-radius:0}
  @page{size:A4 portrait;margin:10mm}
  *{-webkit-print-color-adjust:exact;print-color-adjust:exact}
  /* Same two fixes applied to the mPDF export path (ReportPdf.php /
     cpt-print.css), mirrored here for the other "طباعة / حفظ PDF" button
     (window.print(), rendered by the browser itself using this
     stylesheet - a different engine than mPDF, so needs its own
     hardening rather than assuming it inherits the mPDF fix):
     - .cpt-rtitle is pure Latin content ("SARAYAN colour personality
       test ( C.P.T )") inside an RTL page; isolate it explicitly rather
       than relying on the browser's default bidi handling.
     - Force each row/table-row to stay whole across a page break so a
       chip row is never split with part on each page. */
  .cpt-rtitle{direction:ltr;unicode-bidi:isolate}
  .cpt-row,.cpt-rhead,.cpt-pbar{break-inside:avoid;page-break-inside:avoid}
  /* "Powered by HMS" on A4: one notch smaller than on screen so the header
     band stays as short as it was with the old "C.P.T" text, and never
     wrapped - the header row keeps its single-line [logo | title | brand]
     shape at print width. The dark plate behind the mark relies on the
     print-color-adjust:exact rule above (same as every chip/tint in this
     report) to actually print rather than being dropped as a background. */
  .cpt-rhead{flex-wrap:nowrap}
  .cpt-brand{gap:3px}
  .cpt-brand-label{font-size:6.5pt;color:#6E6C78}
  .cpt-brand-logo{border-radius:7px;break-inside:avoid;page-break-inside:avoid}
  .cpt-brand-logo img{height:46px;max-width:none}
  .cpt-matrix tr{break-inside:avoid;page-break-inside:avoid}
  .cpt-chip{flex-shrink:0;min-width:var(--cpt-chip)}
  /* .cpt-matrix's screen layout uses table-layout:fixed with mostly-equal
     column widths, sized for a ~860px-wide viewport where "ACTIVATION" /
     "EXPRESSION" headers have enough room to fit on one line. At A4 print
     width (~718px content box) those same fixed-percentage columns are too
     narrow for those words, and since fixed-layout cell overflow is
     visible by default, the header text visibly spills into the
     neighboring cell instead of wrapping. Confirmed by rendering an actual
     PDF and inspecting it, not assumed. table-layout:auto lets columns
     size to their real content instead of a rigid equal split, and the
     smaller font gives extra margin. */
  .cpt-matrix{table-layout:auto;font-size:.48rem}
  .cpt-matrix th{font-size:.5rem;padding:3px 2px}
  .cpt-matrix td.cpt-k{font-size:.46rem}
}

/* ---------------- Restart confirmation dialog ----------------
   Sits outside #cpt-root next to the tab bar, so it repeats the few
   tokens it needs rather than inheriting .cpt-wrap's typography. The
   [hidden] attribute does the showing/hiding; .cpt-modal-open only drives
   the transition, which is why the element is un-hidden a frame before
   that class is added (see openRestartModal() in cpt-app.js). */
.cpt-modal{position:fixed;inset:0;z-index:60;display:grid;place-items:center;padding:20px;font-family:inherit}
.cpt-modal[hidden]{display:none}
.cpt-modal-overlay{position:absolute;inset:0;background:rgba(18,19,21,.55);-webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px);opacity:0;transition:opacity .22s ease}
.cpt-modal-dialog{position:relative;width:100%;max-width:430px;background:#fff;border:1px solid var(--cpt-border);border-radius:20px;box-shadow:0 24px 60px rgba(20,22,26,.28);padding:30px 28px 24px;text-align:center;opacity:0;transform:translateY(8px) scale(.96);transition:opacity .22s ease,transform .22s cubic-bezier(.2,.8,.3,1)}
.cpt-modal-open .cpt-modal-overlay{opacity:1}
.cpt-modal-open .cpt-modal-dialog{opacity:1;transform:none}
/* The mark at the top repeats the tab bar's restart glyph, on the same
   soft gold plate the interface uses for its selected state. */
.cpt-modal-icon{display:inline-grid;place-items:center;width:52px;height:52px;border-radius:50%;background:var(--cpt-gold-soft);color:var(--cpt-gold-lo);margin-bottom:16px}
.cpt-modal-icon svg{width:24px;height:24px}
.cpt-modal-title{margin:0 0 10px;font-size:1.22rem;font-weight:700;line-height:1.4;color:var(--cpt-ink)}
.cpt-modal-text{margin:0 0 24px;font-size:.94rem;line-height:1.85;color:var(--cpt-muted)}
/* Two equal columns keep the pair balanced whatever the label lengths -
   'Restart Test' and 'إعادة الاختبار' are very different widths. */
.cpt-modal-actions{display:grid;grid-template-columns:1fr 1fr;gap:10px}
.cpt-modal-btn{font-family:inherit;font-size:.95rem;font-weight:700;cursor:pointer;border-radius:13px;padding:13px 14px;border:1px solid transparent;transition:filter .18s ease,border-color .18s ease,background-color .18s ease}
.cpt-modal-btn-out{background:#fff;color:var(--cpt-ink);border-color:var(--cpt-border)}
.cpt-modal-btn-out:hover{border-color:var(--cpt-gold)}
.cpt-modal-btn-gold{background:linear-gradient(180deg,var(--cpt-gold-hi),var(--cpt-gold-lo));color:#fff;box-shadow:0 6px 16px rgba(158,131,68,.28)}
.cpt-modal-btn-gold:hover{filter:brightness(1.05)}
.cpt-modal-btn:focus-visible{outline:3px solid var(--cpt-gold-soft);outline-offset:2px}
@media(max-width:420px){
  .cpt-modal-dialog{padding:26px 20px 20px;border-radius:18px}
  .cpt-modal-title{font-size:1.12rem}
  .cpt-modal-text{font-size:.88rem;margin-bottom:20px}
  .cpt-modal-actions{grid-template-columns:1fr}
}
@media(prefers-reduced-motion:reduce){
  .cpt-modal-overlay,.cpt-modal-dialog{transition:none}
  .cpt-modal-dialog{transform:none}
}
