:root{
  --bg:#EEF2F1; --surface:#FFFFFF; --surface-2:#F6F9F8; --surface-3:#E8EEEC;
  --ink:#0F1817; --ink-2:#3A4643; --muted:#6A7673;
  --line:#D9E1DE; --line-strong:#C0CCC8;
  --accent:#0E4A52; --accent-ink:#FFFFFF; --accent-soft:#DCEAEA; --accent-hover:#0A363C;
  --ok:#2C7551; --ok-soft:#DEF0E5; --ok-line:#A9D3BC;
  --warn:#8E6410; --warn-soft:#F7ECD3; --warn-line:#E0C88C;
  --risk:#A63A2D; --risk-soft:#F8E3DF; --risk-line:#E6B4AA;
  --radius:10px; --radius-sm:6px;
  --shadow:0 1px 2px rgba(15,24,23,.05), 0 14px 30px -22px rgba(15,24,23,.45);
  --sans:"IBM Plex Sans","Noto Sans Georgian", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  --serif:"IBM Plex Serif","Noto Serif Georgian", Georgia, "Times New Roman", serif;
  --mono:"IBM Plex Mono","Noto Sans Georgian", ui-monospace, SFMono-Regular, Menlo, monospace;
}
@media (prefers-color-scheme: dark){
  :root:not([data-theme="light"]){
    --bg:#0A1110; --surface:#111A19; --surface-2:#16211F; --surface-3:#1D2A28;
    --ink:#E8EFED; --ink-2:#C0CCC9; --muted:#8B9895;
    --line:#22302E; --line-strong:#33443F;
    --accent:#63B8AE; --accent-ink:#04201F; --accent-soft:#11302E; --accent-hover:#81CBC2;
    --ok:#63B78C; --ok-soft:#102E22; --ok-line:#1F513A;
    --warn:#D6A754; --warn-soft:#2E2410; --warn-line:#5A4518;
    --risk:#E2887B; --risk-soft:#331A16; --risk-line:#5C2C25;
    --shadow:0 1px 2px rgba(0,0,0,.4), 0 14px 30px -22px rgba(0,0,0,.9);
  }
}
:root[data-theme="dark"]{
  --bg:#0A1110; --surface:#111A19; --surface-2:#16211F; --surface-3:#1D2A28;
  --ink:#E8EFED; --ink-2:#C0CCC9; --muted:#8B9895;
  --line:#22302E; --line-strong:#33443F;
  --accent:#63B8AE; --accent-ink:#04201F; --accent-soft:#11302E; --accent-hover:#81CBC2;
  --ok:#63B78C; --ok-soft:#102E22; --ok-line:#1F513A;
  --warn:#D6A754; --warn-soft:#2E2410; --warn-line:#5A4518;
  --risk:#E2887B; --risk-soft:#331A16; --risk-line:#5C2C25;
  --shadow:0 1px 2px rgba(0,0,0,.4), 0 14px 30px -22px rgba(0,0,0,.9);
}

*{box-sizing:border-box}
body{
  margin:0; background:var(--bg); color:var(--ink);
  font-family:var(--sans); font-size:14px; line-height:1.5;
  -webkit-font-smoothing:antialiased;
}
h1,h2,h3,h4{margin:0; text-wrap:balance; letter-spacing:-.015em; font-weight:600}
p{margin:0}
button,input,select,textarea{font:inherit; color:inherit}
a{color:var(--accent)}
:focus-visible{outline:2px solid var(--accent); outline-offset:2px; border-radius:4px}
@media (prefers-reduced-motion: reduce){*{animation-duration:.001ms !important; transition-duration:.001ms !important}}

/* ---------- shell ---------- */
.app{display:grid; grid-template-columns:236px 1fr; min-height:100vh}
.rail{
  background:var(--surface); border-right:1px solid var(--line);
  display:flex; flex-direction:column; gap:22px; padding:20px 14px; position:sticky; top:0; height:100vh;
}
.brand{display:flex; gap:10px; align-items:center; padding:0 6px}
.brand .mark{
  width:30px; height:30px; border-radius:8px; background:var(--accent); color:var(--accent-ink);
  display:grid; place-items:center; flex:none;
}
.brand .mark svg{width:17px; height:17px}
.brand b{display:block; font-size:13.5px; letter-spacing:-.01em; line-height:1.2}
.brand span{display:block; font-size:11px; color:var(--muted); font-family:var(--mono); letter-spacing:.02em}
.nav{display:flex; flex-direction:column; gap:2px}
.nav-label{font-size:10.5px; text-transform:uppercase; letter-spacing:.09em; color:var(--muted); padding:0 8px 6px; font-weight:600}
.nav button{
  display:flex; align-items:center; gap:9px; width:100%; text-align:left;
  background:none; border:0; padding:8px 9px; border-radius:var(--radius-sm); cursor:pointer;
  color:var(--ink-2); font-weight:450; font-size:13.5px;
}
.nav button:hover{background:var(--surface-2); color:var(--ink)}
.nav button[aria-current="true"]{background:var(--accent-soft); color:var(--accent); font-weight:600}
.nav button .ico{width:15px; height:15px; flex:none; opacity:.85}
.nav button .cnt{margin-left:auto; font-family:var(--mono); font-size:11px; color:var(--muted)}
.rail-foot{margin-top:auto; display:flex; flex-direction:column; gap:8px}
.storeline{
  font-size:10.5px; color:var(--muted); font-family:var(--mono); line-height:1.4;
  padding:8px 9px; border:1px dashed var(--line-strong); border-radius:var(--radius-sm);
}
.storeline b{color:var(--ink-2); font-weight:600}

.main{min-width:0; display:flex; flex-direction:column}
.topbar{
  display:flex; align-items:center; gap:14px; padding:16px 26px; border-bottom:1px solid var(--line);
  background:var(--surface); position:sticky; top:0; z-index:20; flex-wrap:wrap;
}
.topbar h1{font-size:18px}
.topbar .sub{font-size:12.5px; color:var(--muted)}
.topbar .spacer{flex:1}
.page{padding:24px 26px 60px; display:flex; flex-direction:column; gap:22px; max-width:1180px; width:100%}

/* ---------- primitives ---------- */
.btn{
  display:inline-flex; align-items:center; gap:7px; border:1px solid var(--line-strong);
  background:var(--surface); border-radius:var(--radius-sm); padding:7px 13px; cursor:pointer;
  font-size:13px; font-weight:500; color:var(--ink); white-space:nowrap;
}
.btn:hover{border-color:var(--muted); background:var(--surface-2)}
.btn.primary{background:var(--accent); border-color:var(--accent); color:var(--accent-ink)}
.btn.primary:hover{background:var(--accent-hover); border-color:var(--accent-hover)}
.btn.ghost{border-color:transparent; background:transparent; color:var(--ink-2)}
.btn.ghost:hover{background:var(--surface-2); color:var(--ink)}
.btn.sm{padding:4px 9px; font-size:12px}
.btn.danger{color:var(--risk); border-color:var(--risk-line)}
.btn:disabled{opacity:.45; cursor:not-allowed}
.btn svg{width:14px; height:14px}

.card{background:var(--surface); border:1px solid var(--line); border-radius:var(--radius)}
.card > header{
  padding:14px 18px; border-bottom:1px solid var(--line); display:flex; align-items:center; gap:12px; flex-wrap:wrap;
}
.card > header h2{font-size:14.5px}
.card > header .hint{font-size:12px; color:var(--muted)}
.card .body{padding:18px}
.card .body.tight{padding:0}

.field{display:flex; flex-direction:column; gap:5px}
.field label{font-size:11.5px; font-weight:600; letter-spacing:.03em; text-transform:uppercase; color:var(--muted)}
input[type=text],input[type=email],input[type=date],input[type=number],select,textarea{
  width:100%; background:var(--surface-2); border:1px solid var(--line-strong); color:var(--ink);
  border-radius:var(--radius-sm); padding:8px 10px; font-size:13.5px;
}
textarea{resize:vertical; min-height:90px; line-height:1.55}
input:focus,select:focus,textarea:focus{outline:2px solid var(--accent); outline-offset:-1px; border-color:var(--accent)}
.grid2{display:grid; grid-template-columns:repeat(auto-fit,minmax(min(230px,100%),1fr)); gap:14px}
.row{display:flex; gap:10px; align-items:center; flex-wrap:wrap}
/* A tick box and its wording are one line that wraps inside itself. .row
   wraps whole items, so in a narrow column a long Georgian label dropped
   below its own box and read as an orphaned sentence. */
label.row{align-items:flex-start; flex-wrap:nowrap; line-height:1.4}
label.row > input{margin-top:2px; flex:none}
label.row > span{min-width:0}

.pill{
  display:inline-flex; align-items:center; gap:5px; font-size:11px; font-weight:600; letter-spacing:.02em;
  padding:2.5px 8px; border-radius:99px; border:1px solid transparent; white-space:nowrap;
}
.pill .dot{width:6px; height:6px; border-radius:99px; background:currentColor}
.pill.ok{background:var(--ok-soft); color:var(--ok); border-color:var(--ok-line)}
.pill.warn{background:var(--warn-soft); color:var(--warn); border-color:var(--warn-line)}
.pill.risk{background:var(--risk-soft); color:var(--risk); border-color:var(--risk-line)}
.pill.mute{background:var(--surface-3); color:var(--muted); border-color:var(--line)}
.pill.info{background:var(--accent-soft); color:var(--accent); border-color:transparent}

.mono{font-family:var(--mono); font-size:12px}
.tnum{font-variant-numeric:tabular-nums}
.muted{color:var(--muted)}

/* ---------- stat strip ---------- */
.stats{display:grid; grid-template-columns:repeat(auto-fit,minmax(min(160px,100%),1fr)); gap:0; border:1px solid var(--line); border-radius:var(--radius); background:var(--surface); overflow:hidden}
.stat{padding:16px 18px; border-right:1px solid var(--line)}
.stat:last-child{border-right:0}
.stat .k{font-size:11px; text-transform:uppercase; letter-spacing:.07em; color:var(--muted); font-weight:600}
.stat .v{font-size:27px; font-weight:600; letter-spacing:-.03em; font-variant-numeric:tabular-nums; margin-top:4px; line-height:1.1}
.stat .n{font-size:12px; color:var(--muted); margin-top:2px}
.stat .v.ok{color:var(--ok)} .stat .v.risk{color:var(--risk)}

/* ---------- bars ---------- */
.bars{display:flex; flex-direction:column; gap:11px}
.bar-row{display:grid; grid-template-columns:minmax(110px,150px) 1fr 54px; gap:12px; align-items:center}
.bar-row .nm{font-size:12.5px; color:var(--ink-2); overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
.bar-track{height:8px; border-radius:99px; background:var(--surface-3); overflow:hidden}
.bar-fill{height:100%; border-radius:99px; background:var(--accent)}
.bar-row .pc{font-size:12px; text-align:right; font-variant-numeric:tabular-nums; color:var(--ink-2)}
.axis{display:grid; grid-template-columns:minmax(110px,150px) 1fr 54px; gap:12px; font-size:10.5px; color:var(--muted); font-family:var(--mono); margin-top:10px}
.axis .ax{display:flex; justify-content:space-between}

/* ---------- table ---------- */
.tablewrap{overflow-x:auto}
table{width:100%; border-collapse:collapse; font-size:13px}
th{
  text-align:left; font-size:10.5px; text-transform:uppercase; letter-spacing:.07em; color:var(--muted);
  font-weight:600; padding:9px 14px; border-bottom:1px solid var(--line); white-space:nowrap; background:var(--surface-2);
}
td{padding:10px 14px; border-bottom:1px solid var(--line); vertical-align:middle}
tr:last-child td{border-bottom:0}
tbody tr:hover{background:var(--surface-2)}
td .who{display:flex; flex-direction:column; gap:1px}
td .who b{font-weight:600; font-size:13px}
td .who span{font-size:11.5px; color:var(--muted); font-family:var(--mono)}

/* ---------- campaign cards ---------- */
.camp-list{display:flex; flex-direction:column; gap:0}
.camp{
  display:grid; grid-template-columns:1fr auto; gap:14px; align-items:center;
  padding:16px 18px; border-bottom:1px solid var(--line); cursor:pointer; background:none; border-left:0; border-right:0; border-top:0; width:100%; text-align:left;
}
.camp:last-child{border-bottom:0}
.camp:hover{background:var(--surface-2)}
.camp h3{font-size:15px; margin-bottom:3px}
.camp .meta{display:flex; gap:10px; flex-wrap:wrap; font-size:12px; color:var(--muted)}
.camp .prog{display:flex; align-items:center; gap:10px; min-width:170px}
.camp .prog .bar-track{width:110px; flex:none}

/* ---------- tabs ---------- */
.tabs{display:flex; gap:2px; border-bottom:1px solid var(--line); overflow-x:auto; padding:0 6px}
.tabs button{
  background:none; border:0; border-bottom:2px solid transparent; padding:11px 13px; cursor:pointer;
  font-size:13px; font-weight:500; color:var(--muted); white-space:nowrap; margin-bottom:-1px;
}
.tabs button:hover{color:var(--ink)}
.tabs button[aria-selected="true"]{color:var(--accent); border-bottom-color:var(--accent); font-weight:600}

/* ---------- dropzone ---------- */
.drop{
  border:1.5px dashed var(--line-strong); border-radius:var(--radius); padding:26px 18px; text-align:center;
  background:var(--surface-2); cursor:pointer; display:flex; flex-direction:column; align-items:center; gap:8px;
}
.drop:hover,.drop.over{border-color:var(--accent); background:var(--accent-soft)}
.drop svg{width:24px; height:24px; color:var(--accent)}
.drop b{font-size:13.5px}
.drop span{font-size:12px; color:var(--muted)}

.filecard{display:flex; align-items:center; gap:13px; padding:13px 15px; border:1px solid var(--line); border-radius:var(--radius); background:var(--surface-2)}
.filecard .ficon{width:36px; height:44px; border-radius:4px; background:var(--risk-soft); color:var(--risk); display:grid; place-items:center; font-family:var(--mono); font-size:9.5px; font-weight:600; border:1px solid var(--risk-line); flex:none}
.filecard .fmeta{min-width:0; flex:1}
.filecard .fmeta b{display:block; font-size:13.5px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
.filecard .fmeta span{font-size:11.5px; color:var(--muted); font-family:var(--mono)}

/* ---------- quiz builder ---------- */
.q-item{border:1px solid var(--line); border-radius:var(--radius); padding:14px; display:flex; flex-direction:column; gap:10px; background:var(--surface-2)}
.q-item .qhead{display:flex; gap:10px; align-items:center}
.q-item .qnum{font-family:var(--mono); font-size:11px; color:var(--muted); font-weight:600; flex:none}
.opts{display:flex; flex-direction:column; gap:7px}
.opt{display:flex; gap:9px; align-items:center}
.opt input[type=radio]{accent-color:var(--accent); width:15px; height:15px; flex:none}
.opt input[type=text]{flex:1}

/* ---------- outbox ---------- */
.mail{border:1px solid var(--line); border-radius:var(--radius); overflow:hidden; background:var(--surface)}
.mail .mh{padding:12px 15px; background:var(--surface-2); border-bottom:1px solid var(--line); display:flex; gap:12px; align-items:center; flex-wrap:wrap}
.mail .mh .to{font-size:13px; font-weight:600}
.mail .mh .tm{font-size:11.5px; color:var(--muted); font-family:var(--mono); margin-left:auto}
.mail .mb{padding:16px 18px; font-size:13.5px; color:var(--ink-2); white-space:pre-wrap; line-height:1.6}
.mail .subj{font-weight:600; color:var(--ink); font-size:14px; margin-bottom:10px}
.linkbox{
  display:flex; gap:8px; align-items:center; margin-top:14px; padding:10px 12px; background:var(--accent-soft);
  border-radius:var(--radius-sm); flex-wrap:wrap;
}
.linkbox code{font-family:var(--mono); font-size:11.5px; color:var(--accent); word-break:break-all; flex:1; min-width:180px}

/* ---------- language switch ---------- */
.lang{display:inline-flex; border:1px solid var(--line-strong); border-radius:99px; overflow:hidden; background:var(--surface); flex:none}
.lang button{background:none; border:0; padding:5px 12px; cursor:pointer; font-size:12px; font-weight:600; color:var(--muted); letter-spacing:.02em}
.lang button+button{border-left:1px solid var(--line-strong)}
.lang button[aria-pressed="true"]{background:var(--accent); color:var(--accent-ink)}
.alt{display:block; font-size:.82em; color:var(--muted); font-weight:400; letter-spacing:0; margin-top:2px}
.docsplit{display:flex; align-items:center; gap:14px; margin:40px 0 10px; color:var(--muted); font-family:var(--mono); font-size:10.5px; letter-spacing:.09em; text-transform:uppercase}
.docsplit::before,.docsplit::after{content:""; flex:1; height:1px; background:var(--line-strong)}

.empty{padding:40px 20px; text-align:center; color:var(--muted); display:flex; flex-direction:column; align-items:center; gap:8px}
.empty b{color:var(--ink-2); font-size:14px; font-weight:600}
.empty p{font-size:13px; max-width:44ch}

.banner{
  display:flex; gap:11px; align-items:flex-start; padding:12px 15px; border-radius:var(--radius);
  background:var(--warn-soft); border:1px solid var(--warn-line); color:var(--warn); font-size:12.5px; line-height:1.5;
}
.banner svg{width:16px; height:16px; flex:none; margin-top:1px}
.banner b{color:inherit; font-weight:700}

.toast{
  position:fixed; left:50%; bottom:24px; transform:translateX(-50%); z-index:100;
  background:var(--ink); color:var(--bg); padding:10px 18px; border-radius:99px; font-size:13px; font-weight:500;
  box-shadow:var(--shadow); opacity:0; pointer-events:none; transition:opacity .18s, transform .18s;
}
.toast.show{opacity:1; transform:translateX(-50%) translateY(-4px)}

/* ---------- participant view ---------- */
.pv{max-width:820px; margin:0 auto; padding:28px 20px 80px; display:flex; flex-direction:column; gap:20px}
/* A campaign logo, a long name and an email address all want this row. The
   middle column must be allowed to shrink — flex items floor at min-content
   unless told otherwise, and an email address has no break points, so
   without this the language switch is pushed off a narrow screen. */
.pv-head{display:flex; gap:14px; align-items:center; padding-bottom:18px;
  border-bottom:1px solid var(--line); flex-wrap:wrap}
.pv-head > span{min-width:0}
.pv-head span{overflow-wrap:anywhere}
.pv-head .mark{width:34px; height:34px; border-radius:9px; background:var(--accent); color:var(--accent-ink); display:grid; place-items:center; flex:none}
.pv-head .mark svg{width:19px; height:19px}
.pv-head b{display:block; font-size:14px}
.pv-head span{display:block; font-size:11.5px; color:var(--muted); font-family:var(--mono)}
.pv h1{font-family:var(--serif); font-size:29px; font-weight:600; letter-spacing:-.02em; line-height:1.2}
.pv .lede{font-family:var(--serif); font-size:16px; color:var(--ink-2); line-height:1.65; max-width:64ch}
.steps{display:flex; gap:0; border:1px solid var(--line); border-radius:var(--radius); overflow:hidden; background:var(--surface)}
.step{flex:1; padding:11px 13px; border-right:1px solid var(--line); display:flex; gap:9px; align-items:center; min-width:0}
.step:last-child{border-right:0}
.step .n{width:20px; height:20px; border-radius:99px; border:1.5px solid var(--line-strong); color:var(--muted); display:grid; place-items:center; font-size:11px; font-weight:600; flex:none; font-family:var(--mono)}
.step .t{font-size:12.5px; color:var(--muted); overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
.step.active{background:var(--accent-soft)}
.step.active .n{border-color:var(--accent); color:var(--accent)}
.step.active .t{color:var(--accent); font-weight:600}
.step.done .n{background:var(--ok); border-color:var(--ok); color:#fff}
.step.done .t{color:var(--ink-2)}
.reader{border:1px solid var(--line); border-radius:var(--radius); overflow:hidden; background:var(--surface-3)}
.reader iframe,.reader embed{width:100%; height:min(72vh,640px); border:0; display:block; background:var(--surface)}
.readbar{display:flex; gap:12px; align-items:center; padding:12px 15px; background:var(--surface); border-top:1px solid var(--line); flex-wrap:wrap}
.q-view{border:1px solid var(--line); border-radius:var(--radius); background:var(--surface); padding:16px 18px; display:flex; flex-direction:column; gap:11px}
.q-view .qt{font-size:14.5px; font-weight:600; line-height:1.45}
.q-choice{display:flex; gap:10px; align-items:flex-start; padding:9px 12px; border:1px solid var(--line); border-radius:var(--radius-sm); cursor:pointer; background:var(--surface-2); font-size:13.5px; line-height:1.45}
.q-choice:hover{border-color:var(--accent)}
.q-choice input{accent-color:var(--accent); margin-top:2px; flex:none}
.q-choice.correct{background:var(--ok-soft); border-color:var(--ok-line); color:var(--ok)}
.q-choice.wrong{background:var(--risk-soft); border-color:var(--risk-line); color:var(--risk)}
.ackbox{display:flex; gap:11px; align-items:flex-start; padding:14px 16px; border:1px solid var(--line-strong); border-radius:var(--radius); background:var(--surface-2); font-size:13.5px; line-height:1.55; cursor:pointer}
.ackbox input{accent-color:var(--accent); margin-top:2px; width:16px; height:16px; flex:none}
.cert{border:1px solid var(--ok-line); background:var(--ok-soft); border-radius:var(--radius); padding:22px; display:flex; flex-direction:column; gap:10px; align-items:flex-start}
.cert h2{font-family:var(--serif); font-size:21px; color:var(--ok)}
.cert dl{display:grid; grid-template-columns:auto 1fr; gap:5px 18px; font-size:13px; margin:6px 0 0}
.cert dt{color:var(--muted); font-size:11.5px; text-transform:uppercase; letter-spacing:.05em; font-weight:600; align-self:center}
.cert dd{margin:0; font-family:var(--mono); font-size:12.5px; color:var(--ink)}

/* A control the campaign has switched off stays on the page, greyed, with
   the reason underneath. A button that silently disappears reads as a bug,
   and the person asks support instead of reading the rule. */
.reviewoff{display:inline-flex; flex-direction:column; gap:4px;
  align-items:flex-start; align-self:flex-start}
/* the switched-off button keeps a border and a ground: at .45 opacity and
   no outline a ghost button stops looking like a control at all */
.reviewoff .btn[disabled]{opacity:1; border:1px solid var(--line);
  background:var(--surface-2); color:var(--muted); cursor:not-allowed}
.reviewoff > span{font-size:11.5px; color:var(--muted); line-height:1.35; max-width:36ch}
/* the reason line makes this control two lines taller than its neighbours,
   so the row tops-aligns rather than centring the buttons at three heights.
   Browsers without :has() simply keep the centred row — no worse than before */
.row:has(> .reviewoff){align-items:flex-start}

/* ---------- the finish line ----------
   The one screen in the programme that is allowed to celebrate. Everything
   on it is still a fact the platform can stand behind — it is just said
   with a seal rather than a table row. */
.finale{
  position:relative; isolation:isolate; overflow:hidden;
  border:1px solid var(--ok-line); border-radius:var(--radius);
  background:radial-gradient(130% 85% at 50% -18%, var(--ok-soft), transparent 60%), var(--surface);
  box-shadow:var(--shadow);
  padding:34px 26px 26px;
  display:flex; flex-direction:column; align-items:center; gap:12px; text-align:center;
}
.finale h2{font-family:var(--serif); font-size:26px; color:var(--ok); line-height:1.2}
.finale .lede{font-size:13.5px; color:var(--ink-2); max-width:58ch; margin:0}

.finale .medal{width:96px; height:96px}
.finale .medal svg{width:100%; height:100%; overflow:visible;
  transform-box:view-box; transform-origin:60px 60px;
  animation:sealpop .55s cubic-bezier(.2,.9,.3,1.45) backwards}
.finale .medal circle{fill:none}
.finale .medal .r1{stroke:var(--ok); stroke-width:2.5; opacity:.3}
.finale .medal .r2{stroke:var(--ok-line); stroke-width:2}
.finale .medal .disc{fill:var(--ok)}
.finale .medal .tick{
  fill:none; stroke:var(--accent-ink); stroke-width:8; stroke-linecap:round; stroke-linejoin:round;
  stroke-dasharray:62; stroke-dashoffset:62; animation:tickdraw .5s .3s ease-out forwards;
}
@keyframes sealpop{from{opacity:0; transform:scale(.72)}}
@keyframes tickdraw{to{stroke-dashoffset:0}}

/* Confetti. Behind the content, and ending at opacity 0, so that a reader
   who asked for reduced motion — where every duration collapses to almost
   nothing — lands straight on the invisible final frame. */
.finale .fx{position:absolute; inset:0; z-index:-1; pointer-events:none}
.finale .fx i{
  position:absolute; top:-16px; left:calc(3% + var(--i) * 7%);
  width:7px; height:11px; border-radius:2px; opacity:0; background:var(--ok);
  animation:confetti 2.7s cubic-bezier(.25,.55,.4,1) forwards;
  animation-delay:calc(.1s + var(--i) * .085s);
}
.finale .fx i:nth-child(3n){background:var(--accent); width:8px; height:8px; border-radius:50%}
.finale .fx i:nth-child(3n+1){background:var(--warn)}
@keyframes confetti{
  0%{opacity:0; transform:translate3d(0,0,0) rotate(0)}
  10%{opacity:.8}
  100%{opacity:0; transform:translate3d(calc((var(--i) - 6.5) * 7px), 320px, 0) rotate(560deg)}
}

.finale .stamp{
  position:relative; overflow:hidden; width:min(470px,100%); margin-top:4px;
  border:1px solid var(--ok-line); border-radius:var(--radius); background:var(--surface-2);
  padding:13px 16px 14px 20px; display:flex; flex-direction:column; gap:2px; text-align:left;
}
.finale .stamp::before{content:""; position:absolute; inset:0 auto 0 0; width:4px; background:var(--ok)}
.finale .stamp span{font-size:10.5px; font-weight:600; letter-spacing:.09em;
  text-transform:uppercase; color:var(--muted)}
.finale .stamp b{font-family:var(--mono); font-size:19px; color:var(--ink); overflow-wrap:anywhere}
.finale .stamp small{font-size:12px; color:var(--ink-2)}

.finale .factrow{
  display:grid; grid-template-columns:repeat(auto-fit,minmax(min(158px,100%),1fr));
  gap:10px 18px; width:100%; margin:6px 0 0; text-align:left;
}
.finale .factrow div{border-top:1px solid var(--line); padding-top:8px; min-width:0}
.finale .factrow dt{font-size:10.5px; font-weight:600; letter-spacing:.06em;
  text-transform:uppercase; color:var(--muted)}
.finale .factrow dd{margin:2px 0 0; font-family:var(--mono); font-size:12.5px; overflow-wrap:anywhere}

.finaleacts{justify-content:center; margin-top:4px}
.finaleacts .btn svg{width:15px; height:15px}
.finaleacts .reviewoff{align-items:center; text-align:center}
.finale .keepit{font-size:11.5px; max-width:52ch}

/* ---------- responsive ---------- */
/* The hamburger and its drawer. Both are inert on wide screens, where the
   rail is simply a column of the page. */
.navtoggle{position:absolute; width:1px; height:1px; opacity:0; pointer-events:none}
.navscrim{display:none}
.navbtn{display:none; align-items:center; justify-content:center; width:40px; height:40px;
  margin-left:-6px; border-radius:var(--radius-sm); color:var(--ink-2); cursor:pointer; flex:none}
.navbtn svg{width:22px; height:22px}
.navbtn:hover{background:var(--surface-2); color:var(--ink)}
.topbar .ttl{min-width:0}
.topbar .ttl h1{overflow-wrap:anywhere}
.topacts{display:contents}

@media (max-width:880px){
  .app{grid-template-columns:1fr}
  .navbtn{display:inline-flex}
  /* Off-canvas: the rail slides over the page. The old behaviour squeezed it
     into a horizontal strip where most destinations were off-screen with no
     hint that they existed. */
  .rail{position:fixed; top:0; bottom:0; left:0; z-index:70; width:min(84vw,300px);
    height:100%; border-right:1px solid var(--line); border-bottom:0;
    transform:translateX(-101%); transition:transform .22s cubic-bezier(.22,.9,.3,1);
    overflow-y:auto; overscroll-behavior:contain;
    padding-bottom:calc(20px + env(safe-area-inset-bottom))}
  .navtoggle:checked ~ .rail{transform:none; box-shadow:0 0 44px rgba(0,0,0,.34)}
  .navscrim{display:block; position:fixed; inset:0; z-index:65; background:rgba(6,12,11,.5);
    opacity:0; pointer-events:none; transition:opacity .22s}
  .navtoggle:checked ~ .navscrim{opacity:1; pointer-events:auto}
  /* the page behind the drawer must not scroll under the finger */
  body.navopen{overflow:hidden}
  .topbar{padding:10px 14px; gap:10px}
  .topbar h1{font-size:16px}
  .page{padding:16px 14px calc(60px + env(safe-area-inset-bottom))}
  .stat{border-right:0; border-bottom:1px solid var(--line)}
  .camp{grid-template-columns:1fr}
  .steps{flex-wrap:wrap}
  .step{min-width:50%; border-bottom:1px solid var(--line)}
}
@media (prefers-reduced-motion:reduce){ .rail,.navscrim{transition:none} }

/* ---------- server-rendered additions ---------- */
.nav a{display:flex; align-items:center; gap:9px; width:100%; text-decoration:none;
  padding:8px 9px; border-radius:var(--radius-sm); color:var(--ink-2); font-weight:450; font-size:13.5px}
.nav a:hover{background:var(--surface-2); color:var(--ink)}
.nav a[aria-current="page"]{background:var(--accent-soft); color:var(--accent); font-weight:600}
.nav a .ico{width:15px; height:15px; flex:none; opacity:.85}
.nav a .cnt{margin-left:auto; font-family:var(--mono); font-size:11px; color:var(--muted)}
a.camp{text-decoration:none; color:inherit}
.tabs a{display:inline-block; text-decoration:none; border-bottom:2px solid transparent; padding:11px 13px;
  font-size:13px; font-weight:500; color:var(--muted); white-space:nowrap; margin-bottom:-1px}
.tabs a:hover{color:var(--ink)}
.tabs a[aria-selected="true"]{color:var(--accent); border-bottom-color:var(--accent); font-weight:600}
.lang a{text-decoration:none}
.mailstat{margin-left:auto; display:flex; gap:8px; align-items:center}
@media (max-width:880px){
  .rail-foot{display:flex; margin-left:auto; flex-direction:row; align-items:center}
  .rail-foot .storeline{display:none}
}

/* ---------- paged reader ---------- */
.pages{max-height:min(74vh,720px); overflow-y:auto; overflow-x:hidden; background:var(--surface-3);
  padding:14px; display:flex; flex-direction:column; gap:14px; scroll-behavior:smooth}
/* flex:0 0 auto is not decoration. The container is a flex column with a
   max-height, so shrinkable children are squeezed to share it — and an image
   that has not loaded yet has no intrinsic height to defend itself with. That
   collapsed every page to a ~54px strip showing only its heading. Pages must
   keep their full height and let the container scroll, which is its purpose. */
.pages figure{flex:0 0 auto; margin:0; position:relative; background:var(--surface);
  border:1px solid var(--line); border-radius:6px; overflow:hidden;
  box-shadow:0 1px 3px rgba(0,0,0,.08)}
/* --pr is the real page ratio, measured from the rendered image, so a lazy
   page reserves the right space instead of jumping when it arrives. */
.pages img{display:block; width:100%; height:auto; background:#fff;
  aspect-ratio:var(--pr, 16 / 9)}
.pages figcaption{position:absolute; top:8px; right:8px; font-family:var(--mono); font-size:10.5px;
  padding:2px 7px; border-radius:99px; background:rgba(15,24,23,.62); color:#fff; letter-spacing:.03em}
.pages figure[data-seen="1"] figcaption{background:var(--ok); color:#fff}

/* An unread page says so on the page itself. A count of what is left is no
   help if you cannot see which one it means. */
.pages figure[data-seen="0"]{border-color:var(--risk-line, #e6bcbc)}
.pages figure[data-seen="0"]::before{content:""; position:absolute; left:0; top:0; bottom:0;
  width:4px; background:var(--risk); z-index:1}
.pages figure[data-seen="0"] figcaption{background:var(--risk); color:#fff}
.pages figure.flash{animation:pageflash 1.5s ease-out 1}
@keyframes pageflash{
  0%{box-shadow:0 0 0 3px var(--risk)}
  60%{box-shadow:0 0 0 3px var(--risk)}
  100%{box-shadow:0 1px 3px rgba(0,0,0,.08)}
}
@media (prefers-reduced-motion:reduce){ .pages figure.flash{animation:none} }

/* the hint that takes you there */
/* an explicit display: overrides the UA's [hidden]{display:none}, so say it again */
.jumpbtn[hidden]{display:none}
.jumpbtn{display:inline-flex; align-items:center; gap:6px; font:inherit; font-size:12.5px;
  font-weight:600; cursor:pointer; border:1px solid var(--risk); color:var(--risk);
  background:var(--risk-soft, rgba(180,62,62,.08)); padding:4px 11px; border-radius:99px}
.jumpbtn::before{content:""; width:7px; height:7px; border-radius:50%; background:var(--risk)}
.jumpbtn::after{content:"→"; font-weight:700}
.jumpbtn:hover{background:var(--risk); color:#fff}
.jumpbtn:hover::before{background:#fff}
.jumpbtn.soft{border-color:var(--line-strong); color:var(--ink-2); background:var(--surface-2)}
.jumpbtn.soft::before{background:var(--warn)}
.readprog{display:flex; align-items:center; gap:8px; min-width:150px}
.readprog .bar-track{flex:1; min-width:70px}
.readbar .warnnote{font-size:12.5px; color:var(--warn)}
@media (max-width:880px){ .pages{max-height:70vh; padding:10px; gap:10px} }

/* ---------- book view: one page at a time ----------
   A deck read as an endless ribbon is read badly: people scroll past half a
   page and never see the other half. Book view shows exactly one page, turned
   with the buttons, the arrow keys, the wheel or a swipe. The scrolling list
   is still there behind the toggle for anyone who prefers it. */
.pagenav{display:flex; align-items:center; gap:10px; flex-wrap:wrap;
  padding:9px 12px; background:var(--surface); border-bottom:1px solid var(--line)}
.pagenav[hidden]{display:none}
.pgbtn{display:inline-flex; align-items:center; gap:5px; font:inherit; font-size:12.5px;
  font-weight:600; cursor:pointer; border:1px solid var(--line-strong); color:var(--ink);
  background:var(--surface-2); padding:6px 12px; border-radius:99px; min-height:34px}
.pgbtn:hover:not(:disabled){background:var(--accent-soft); border-color:var(--accent)}
.pgbtn:disabled{opacity:.42; cursor:default}
.pgpos{display:inline-flex; align-items:center; gap:5px; font-family:var(--mono); font-size:12.5px}
.pgpos input{width:3.8em; text-align:center; font:inherit; padding:4px 6px; -moz-appearance:textfield;
  border:1px solid var(--line); border-radius:7px; background:var(--surface); color:var(--ink)}
.pgpos input::-webkit-outer-spin-button,
.pgpos input::-webkit-inner-spin-button{-webkit-appearance:none; margin:0}
.pghint{font-size:12px; flex:1 1 120px; min-width:0; overflow:hidden;
  text-overflow:ellipsis; white-space:nowrap}
.pgmode{font:inherit; font-size:12px; font-weight:600; cursor:pointer; border:1px solid var(--line);
  background:none; color:var(--ink-2); padding:5px 11px; border-radius:99px; min-height:32px}
.pgmode:hover{border-color:var(--accent); color:var(--accent)}

/* The strip: one page wide, snapped, so a turn always lands on a whole page. */
/* The frame takes the shape of the document's own pages (--pr, measured when
   the material was prepared), so a 16:9 deck is not floated in a tall grey
   well and an A4 portrait page is not squeezed into a letterbox. */
/* The side gutters belong to the sheet, not to the strip: padding on the
   strip is inside the scrollport, so the next page peeks through it — which,
   with an unread page's red frame, reads as a rendering fault. */
.pages.book{flex-direction:row; overflow-x:auto; overflow-y:hidden; gap:0; padding:12px 0;
  scroll-snap-type:x mandatory; max-height:min(78vh,760px); min-height:240px;
  height:auto; aspect-ratio:var(--pr, 16 / 9);
  /* the inline size must stay the parent's: with only a ratio and a
     min-height to go on, the box takes its WIDTH from the height instead
     and pushes a narrow screen sideways */
  width:100%; max-width:100%;
  scrollbar-width:none; -ms-overflow-style:none; overscroll-behavior-x:contain}
.pages.book::-webkit-scrollbar{display:none}
.pages.book figure{flex:0 0 100%; width:100%; height:100%; border:0; background:none;
  box-shadow:none; overflow:visible; scroll-snap-align:center; scroll-snap-stop:always;
  display:flex; align-items:center; justify-content:center; padding:0 14px}
/* auto in both axes with both maxima: the sheet keeps its own proportions
   whatever shape the frame is, so the border hugs the picture instead of
   boxing in a band of empty space above and below it. */
.pages.book img{width:auto; height:auto; max-width:100%; max-height:100%;
  object-fit:contain; border:1px solid var(--line); border-radius:6px;
  box-shadow:0 2px 12px -5px rgba(0,0,0,.42)}
/* the page number sits under the sheet, where a book keeps it */
.pages.book figcaption{top:auto; bottom:6px; right:auto; left:50%; transform:translateX(-50%)}
/* the unread mark rides the sheet, not the empty strip around it */
.pages.book figure[data-seen="0"]::before{display:none}
.pages.book figure[data-seen="0"] img{border-color:var(--risk); box-shadow:0 0 0 2px var(--risk)}
.pages.book figure.flash{animation:none}
.pages.book figure.flash img{animation:pageflash 1.5s ease-out 1}
@media (prefers-reduced-motion:reduce){ .pages.book figure.flash img{animation:none} }

/* ---------- phishing lure picker ---------- */
.tmplgrid{display:grid; grid-template-columns:repeat(auto-fit,minmax(min(210px,100%),1fr)); gap:10px}
.tmplgrid .tcard{border:1px solid var(--line); border-radius:var(--radius-sm); background:var(--surface-2);
  padding:12px; cursor:pointer; display:flex; flex-direction:column; gap:6px; position:relative}
.tmplgrid .tcard:hover{border-color:var(--accent)}
.tmplgrid .tcard:has(input:checked){border-color:var(--accent); background:var(--accent-soft)}
.tmplgrid .tcard input{accent-color:var(--accent); position:absolute; top:12px; right:12px}
.tmplgrid .tcard b{font-size:13px; padding-right:22px}
.tmplgrid .tcard span{font-size:11.5px; color:var(--muted); line-height:1.45}
.tmplgrid .tcard .meta{font-family:var(--mono); font-size:10.5px; letter-spacing:.03em}
/* the per-card "preview" link. A plain link, not a button, so it never looks
   like it competes with the radio that actually picks the lure. */
.tmplgrid .tcard .tprev{font-size:11px; font-weight:600; color:var(--accent);
  text-decoration:none; margin-top:2px}
.tmplgrid .tcard .tprev:hover{text-decoration:underline}
/* the picker is grouped by category; each group carries a quiet heading */
.tmplcat{font-size:11px; font-weight:600; letter-spacing:.05em; text-transform:uppercase;
  color:var(--muted); margin:14px 0 6px}
.tmplcat:first-child{margin-top:0}

/* ---------- the lure preview, as a mail client would frame it ---------- */
.mailview{overflow:hidden}
.mailhead{display:flex; gap:13px; align-items:flex-start; padding:16px 18px;
  border-bottom:1px solid var(--line); background:var(--surface-2)}
.mailhead .avatar{width:40px; height:40px; border-radius:50%; flex:none;
  background:var(--accent); color:var(--accent-ink); display:grid; place-items:center;
  font-weight:600; font-size:17px}
.mailhead .mailmeta{flex:1; min-width:0; display:flex; flex-direction:column; gap:3px}
.mailhead .msubject{font-size:15.5px; font-weight:600; line-height:1.3; overflow-wrap:anywhere}
.mailhead .mrow{font-size:12.5px; color:var(--ink-2); display:flex; gap:8px; overflow-wrap:anywhere}
.mailhead .mrow .k{color:var(--muted); min-width:44px; flex:none}
.mailhead .mdate{font-size:11px; color:var(--muted); flex:none; padding-top:2px}
.mailbody{padding:20px 20px; font-size:14px; line-height:1.7; color:var(--ink);
  white-space:normal; overflow-wrap:anywhere}
.mailfoot{padding:11px 18px; border-top:1px solid var(--line); background:var(--surface-2);
  font-size:11px; color:var(--muted); overflow-wrap:anywhere}
@media (max-width:620px){
  .mailhead{flex-wrap:wrap}
  .mailhead .mdate{width:100%; padding-top:0}
}

/* ---------- funnel ---------- */
.funnel{display:flex; flex-direction:column; gap:9px}
.frow{display:grid; grid-template-columns:minmax(96px,150px) 1fr 62px; gap:12px; align-items:center}
.frow .fl{font-size:12.5px; color:var(--ink-2)}
.ftrack{height:20px; border-radius:5px; background:var(--surface-3); overflow:hidden}
.ffill{height:100%; border-radius:5px; transition:width .7s cubic-bezier(.22,.9,.3,1)}
.frow .fv{font-family:var(--mono); font-size:12px; text-align:right; color:var(--ink-2)}
.funnel + .axis, .funnel .axis{grid-template-columns:minmax(96px,150px) 1fr 62px}

/* ---------- certificate sheet ---------- */
.certsheet{border:1px solid var(--line-strong); border-radius:10px; background:var(--surface);
  padding:38px 34px; font-family:var(--serif); display:flex; flex-direction:column; gap:14px; position:relative}
.certsheet::after{content:""; position:absolute; inset:10px; border:1px solid var(--line); border-radius:6px; pointer-events:none}
.certmark{display:flex; gap:10px; align-items:center; font-family:var(--sans)}
.certmark .mark{width:30px; height:30px; border-radius:8px; background:var(--accent); color:var(--accent-ink);
  display:grid; place-items:center; flex:none}
.certmark .mark svg{width:17px; height:17px}
.certmark b{display:block; font-size:13.5px; line-height:1.2}
.certmark span span{display:block; font-size:11px; color:var(--muted); font-family:var(--mono)}
.certsheet .cap{font-family:var(--mono); font-size:9.5px; letter-spacing:.14em; text-transform:uppercase;
  color:var(--accent); font-weight:600; margin-top:6px}
.certsheet h1{font-family:var(--serif); font-size:25px; font-weight:600; letter-spacing:-.01em; line-height:1.2}
.certsheet .awarded{font-family:var(--sans); font-size:11px; letter-spacing:.07em;
  text-transform:uppercase; color:var(--muted); font-weight:600; margin-bottom:-8px}
.certsheet .who{font-size:29px; font-weight:600; border-bottom:1px solid var(--line-strong); padding-bottom:8px}
.certsheet p{font-size:14px; color:var(--ink-2); line-height:1.65; max-width:54ch}
.certsheet dl{display:grid; grid-template-columns:auto 1fr; gap:5px 18px; font-family:var(--sans); margin:8px 0 0}
.certsheet dt{font-size:10.5px; text-transform:uppercase; letter-spacing:.06em; color:var(--muted); font-weight:600; align-self:center}
.certsheet dd{margin:0; font-family:var(--mono); font-size:12.5px}
.certsheet .certfoot{font-family:var(--sans); font-size:11px; color:var(--muted); margin-top:4px}
/* the seal, small, in the corner of the head — the PDF carries the big one */
.certseal{flex:none; width:46px; height:46px}
.certseal svg{width:100%; height:100%}
.certseal .ring{fill:none; stroke:var(--ok); stroke-width:1.6; opacity:.45}
.certseal .disc{fill:var(--ok)}
.certseal .tick{fill:none; stroke:var(--accent-ink); stroke-width:3.4;
  stroke-linecap:round; stroke-linejoin:round}
/* the exact moment, in its own band, as on the PDF */
.certwhen{position:relative; overflow:hidden; font-family:var(--sans);
  border:1px solid var(--accent-soft); border-left:4px solid var(--accent); border-radius:8px;
  background:var(--accent-soft); padding:11px 15px; display:flex; flex-direction:column; gap:2px;
  align-self:flex-start; max-width:100%}
.certwhen span{font-size:10px; font-weight:600; letter-spacing:.09em;
  text-transform:uppercase; color:var(--accent)}
.certwhen b{font-family:var(--mono); font-size:17px; color:var(--ink); overflow-wrap:anywhere}

@media print{
  .noprint{display:none !important}
  body{background:#fff}
  .certsheet{border-color:#999; box-shadow:none; page-break-inside:avoid}
}

/* ---------- risk rows ---------- */
.rrow{display:grid; grid-template-columns:1fr 34px; gap:10px; align-items:center}
.rtrack{height:8px; border-radius:99px; background:var(--surface-3); overflow:hidden}
.rfill{height:100%; border-radius:99px}
.rrow .rv{font-family:var(--mono); font-size:12px; text-align:right; font-variant-numeric:tabular-nums}

/* ---------- participant edit popover ---------- */
.editpop{position:absolute; z-index:40; margin-top:6px; right:0; min-width:320px;
  box-shadow:var(--shadow); text-align:left}
details[open] > summary.btn{background:var(--surface-2); border-color:var(--muted)}

/* ---------- dashboards ---------- */
.wgrid{display:grid; grid-template-columns:repeat(auto-fill,minmax(min(240px,100%),1fr)); gap:14px; align-items:start}
.widget{border:1px solid var(--line); border-radius:var(--radius); background:var(--surface); padding:15px;
  display:flex; flex-direction:column; gap:12px; min-height:120px}
.widget.wide{grid-column:span 2}
@media (max-width:640px){ .widget.wide{grid-column:span 1} }
.whead{display:flex; align-items:baseline; gap:10px}
.whead h3{font-size:12.5px; text-transform:uppercase; letter-spacing:.06em; color:var(--muted); font-weight:600; flex:1}
.wkpi{font-size:40px; font-weight:600; letter-spacing:-.03em; line-height:1; font-variant-numeric:tabular-nums}
.wkpi.ok{color:var(--ok)} .wkpi.warn{color:var(--warn)} .wkpi.risk{color:var(--risk)}
.wnote{font-size:12.5px; color:var(--muted); font-family:var(--mono)}
.donutwrap{display:flex; gap:16px; align-items:center; flex-wrap:wrap}
.donut{width:118px; height:118px; flex:none; transform:rotate(0deg)}
.donut .dcenter{font-family:var(--mono); font-size:8px; fill:var(--ink); text-anchor:middle; font-weight:600}
.dlegend{display:flex; flex-direction:column; gap:5px; font-size:12.5px; color:var(--ink-2)}
.dlegend > div{display:flex; align-items:center; gap:7px}
.dlegend .dot{width:9px; height:9px; border-radius:3px; flex:none}
.dlegend b{margin-left:auto; padding-left:12px}

/* ---------- widget catalogue (Dashboards page) ---------- */
.catgrid{display:grid; grid-template-columns:repeat(auto-fill,minmax(min(268px,100%),1fr)); gap:10px}
.catcard{display:flex; gap:11px; align-items:flex-start; padding:12px;
  border:1px solid var(--line); border-radius:var(--radius-sm); background:var(--surface)}
.catcard b{display:block; font-size:12.8px; margin-bottom:3px}
.catcard span{display:block; font-size:11.8px; color:var(--muted); line-height:1.5}
.catcard .kindtag{display:inline-block; margin-top:7px; font-size:10px; letter-spacing:.04em;
  text-transform:uppercase; color:var(--ink-2); background:var(--surface-3);
  border-radius:99px; padding:2px 8px}
.kindmark{flex:none; width:30px; height:30px; border-radius:8px; display:grid; place-items:center;
  background:var(--accent-soft); color:var(--accent)}
.kindmark svg{width:16px; height:16px}
.kindmark.bars{background:var(--warn-soft); color:var(--warn)}
.kindmark.donut{background:var(--ok-soft, var(--accent-soft)); color:var(--ok)}
.kindmark.funnel{background:var(--risk-soft); color:var(--risk)}

/* ---------- campaign list: bulk selection ---------- */
.camppick{display:grid; grid-template-columns:26px 1fr; align-items:center; gap:2px;
  border-bottom:1px solid var(--line)}
.camppick:last-child{border-bottom:0}
.camppick > input{margin-left:10px}
.camppick .camp{border-bottom:0}

/* ---------- campaign logo ---------- */
.logobox{width:172px; height:74px; border:1px dashed var(--line-strong); border-radius:8px;
  display:grid; place-items:center; background:var(--surface); padding:8px; flex:none}
.logobox img{max-width:100%; max-height:58px; object-fit:contain}
.pv-logo{max-height:38px; max-width:190px; object-fit:contain}

/* ---------- Microsoft sign-in ---------- */
.msbtn{display:flex; align-items:center; justify-content:center; gap:10px; width:100%;
  padding:10px 14px; font-weight:600; font-size:13.5px; text-decoration:none;
  border:1px solid var(--line-strong); background:var(--surface); color:var(--ink)}
.msbtn:hover{border-color:var(--muted); background:var(--surface-2)}
.orline{display:flex; align-items:center; gap:12px; color:var(--muted); font-size:11.5px;
  text-transform:uppercase; letter-spacing:.08em}
.orline::before,.orline::after{content:""; flex:1; height:1px; background:var(--line)}

/* ---------- participant: the finish sheet ---------- */
.donerows{display:flex; flex-direction:column; gap:10px}
.donerows > div{display:flex; align-items:center; gap:10px; flex-wrap:wrap; font-size:12.5px}

/* a step you have already passed is a link back to it */
a.step{text-decoration:none; color:inherit}
a.step:hover{border-color:var(--accent)}

/* ---------- tables become cards on a phone ----------
   A seven-column roster cannot be read on a 390px screen, and a sideways
   scrollbar hides half of it. Each row becomes a labelled card instead; the
   labels are copied from the header by app.js, so no template repeats them.
   Without JavaScript the table simply scrolls sideways, which still works. */
@media (max-width:620px){
  .tablewrap{overflow-x:auto; -webkit-overflow-scrolling:touch}
  .tablewrap table{min-width:560px}

  .tablewrap table.cards{min-width:0; display:block}
  .cards thead{display:none}
  .cards tbody,.cards tr,.cards td{display:block}
  .cards tr{padding:12px 14px; border-bottom:1px solid var(--line); position:relative}
  .cards tr:last-child{border-bottom:0}
  .cards tbody tr:hover{background:none}
  .cards td{border-bottom:0; padding:3px 0; display:grid;
    grid-template-columns:minmax(88px,36%) 1fr; gap:12px; align-items:baseline}
  .cards td::before{content:attr(data-label); font-size:10.5px; text-transform:uppercase;
    letter-spacing:.06em; color:var(--muted); font-weight:600; line-height:1.5}
  /* the tick box and the row's buttons have no heading to borrow */
  .cards td.nolabel{display:block; padding:0}
  .cards td.nolabel:last-child{padding-top:10px; text-align:left !important}
  .cards td.nolabel:last-child .btn{margin-right:6px; margin-bottom:6px}
  .cards td.pick{position:absolute; top:12px; right:12px; padding:0; width:auto}
  .cards .who b{font-size:14px}
  .cards td:empty{display:none}
}

/* ---------- the reader on a phone ----------
   One scrolling surface, not a small scrolling window inside a scrolling page,
   with the finish bar pinned so it is reachable without scrolling to page 40. */
@media (max-width:620px){
  .reader{overflow:visible; border:0; background:none; border-radius:0}
  /* both axes, or CSS turns a lone overflow-y:visible back into auto
     and the list keeps its own scrollbar */
  .pages{max-height:none; overflow:visible; padding:0; gap:12px; background:none}
  .reader iframe,.reader embed{height:min(78vh,560px); border-radius:var(--radius);
    border:1px solid var(--line)}
  .readbar{position:sticky; bottom:0; z-index:12; border:1px solid var(--line);
    border-radius:var(--radius); margin-top:12px; gap:10px;
    box-shadow:0 -10px 26px -18px rgba(0,0,0,.7);
    padding-bottom:calc(12px + env(safe-area-inset-bottom))}
  .readbar form{flex:1 1 auto}
  .readbar #readbtn,.readbar .btn.primary{width:100%; justify-content:center}
  .readprog{min-width:120px; flex:1}
  /* Book view keeps its own frame on a phone — that is the whole point of it,
     and a swipe across one sheet is the most natural page turn there is. */
  .pagenav{border:1px solid var(--line); border-radius:var(--radius);
    margin-bottom:10px; padding:8px 10px; gap:8px}
  .pages.book{max-height:min(66vh,520px); min-height:200px; padding:8px 0;
    background:var(--surface-3); border:1px solid var(--line); border-radius:var(--radius)}
  .pages.book figure{padding:0 8px}
  .pghint{display:none}
  .pglabel{position:absolute; width:1px; height:1px; overflow:hidden; clip:rect(0 0 0 0)}
  .pgbtn{padding:7px 14px; font-size:15px}
  .pgmode{margin-inline-start:auto}
}

/* ---------- odds and ends that overflow on small screens ---------- */
.tabs{scrollbar-width:thin}
@media (max-width:620px){
  .tabs{padding:0 4px; scroll-snap-type:x proximity}
  .tabs a,.tabs button{scroll-snap-align:start}
  .mail .mh .tm{margin-left:0}
  .linkbox code{min-width:0}
  .donutwrap{gap:12px}
  .dlegend{font-size:12px; width:100%}
  .filecard{flex-wrap:wrap}
  .filecard .fmeta{flex:1 1 140px}
  .q-item .qhead{flex-wrap:wrap}
  .q-item .qhead .q-text{flex:1 1 100%; order:2}
  .catgrid{gap:8px}
  .camppick{grid-template-columns:30px 1fr}
  .msbtn{min-height:44px}
}
/* long unbroken strings — tokens, addresses, URLs — must not widen the page */
.mono,code,.who span,.storeline{overflow-wrap:anywhere}

/* The language switch is a permanent fixture of the top bar; on a phone it
   must not take a third of the row. Higher specificity than the touch rule. */
@media (max-width:620px){
  .topbar .lang a{padding:7px 11px; font-size:11.5px}
  .pv-head .lang a{padding:7px 11px; font-size:11.5px}
  .topbar{padding:8px 12px; gap:8px}
  .topbar h1{font-size:15.5px; line-height:1.25}
}

/* The pinned finish bar covers the foot of the screen, so a page jumped to
   must stop above it rather than under it. */
.pages figure{scroll-margin-top:12px; scroll-margin-bottom:120px}
@media (max-width:620px){
  .readbar{padding:10px 12px calc(10px + env(safe-area-inset-bottom)); gap:8px; row-gap:8px}
  .readbar .mono{font-size:11.5px}
  .readbar > .btn.ghost.sm{order:5}
  .pages figure{scroll-margin-top:64px}
}


/* ---------- the quiz is not open yet ---------- */
.waitcard{border-color:var(--accent-soft); background:var(--surface)}
.waitcard .body{display:flex; flex-direction:column; gap:12px; align-items:flex-start;
  padding:26px 24px}
.waitcard h2{font-size:18px}
.waitcard p{font-size:13.5px; color:var(--ink-2); line-height:1.65; max-width:62ch}
.waitmark{width:46px; height:46px; border-radius:14px; background:var(--accent-soft);
  color:var(--accent); display:grid; place-items:center}
.waitmark svg{width:24px; height:24px}
.waitwhen{display:flex; flex-direction:column; gap:3px; padding:12px 16px; width:100%;
  background:var(--surface-2); border:1px solid var(--line); border-radius:var(--radius)}
.waitwhen .k{font-size:10.5px; text-transform:uppercase; letter-spacing:.07em; color:var(--muted);
  font-weight:600}
.waitwhen b{font-family:var(--mono); font-size:15px}
.waitwhen .muted{font-size:12.5px}

/* ---------- send a nudge by hand ---------- */
.notifygrid{display:grid; grid-template-columns:repeat(auto-fit,minmax(min(235px,100%),1fr)); gap:10px}
.notifycard{display:flex; flex-direction:column; gap:8px; padding:13px;
  border:1px solid var(--line); border-radius:var(--radius-sm); background:var(--surface)}
.notifycard b{display:block; font-size:13px; margin-bottom:3px}
.notifycard span{display:block; font-size:11.8px; color:var(--muted); line-height:1.5}

/* ---------- two-step sign-in ---------- */
.codebox{font-family:var(--mono); font-size:22px !important; letter-spacing:.32em;
  text-align:center; padding:12px 10px !important}
.twosetup{display:grid; grid-template-columns:auto 1fr; gap:26px; align-items:start}
.twoqr{display:flex; flex-direction:column; gap:8px; align-items:center; flex:none}
.twoqr svg{border:1px solid var(--line); border-radius:8px; display:block; background:#fff}
.twoqr .muted{font-size:11.5px; text-align:center; max-width:190px}
.twosteps{display:flex; flex-direction:column; gap:16px; min-width:0}
.twosteps ol{margin:0; padding-left:20px; display:flex; flex-direction:column; gap:10px}
.twosteps li b{display:block; font-size:13.5px}
.twosteps li span{display:block; font-size:12.5px; color:var(--muted); line-height:1.55; margin-top:2px}
.twomanual summary{cursor:pointer; font-size:12.5px; font-weight:600; color:var(--accent)}
.twomanual > div{padding-top:10px; display:flex; flex-direction:column; gap:9px}
.twomanual p{font-size:12px}
.secretbox{display:block; font-family:var(--mono); font-size:14px; letter-spacing:.08em;
  padding:11px 13px; background:var(--surface-3); border-radius:var(--radius-sm);
  word-break:break-all; user-select:all}
.twoparams{display:grid; grid-template-columns:auto 1fr; gap:4px 14px; margin:0; font-size:12px}
.twoparams dt{color:var(--muted); text-transform:uppercase; font-size:10.5px; letter-spacing:.05em;
  font-weight:600; align-self:center}
.twoparams dd{margin:0; font-family:var(--mono); overflow-wrap:anywhere}
.reccodes{display:grid; grid-template-columns:repeat(auto-fit,minmax(min(150px,100%),1fr));
  gap:8px; margin:0; padding-left:22px}
.reccodes li{font-family:var(--mono); font-size:14px; letter-spacing:.06em}

/* =========================================================================
   Small-screen overrides live at the very END of this stylesheet on purpose:
   a media query adds no specificity, so anything declared after it would win
   and the phone layout would silently lose to a later desktop rule.
   ========================================================================= */

/* ---------- phones ---------- */
@media (max-width:620px){
  /* 16px is the threshold below which iOS Safari zooms the page on focus, and
     then leaves the whole layout scrolled sideways. */
  input[type=text],input[type=email],input[type=date],input[type=number],
  input[type=password],input[type=search],input[type=tel],input[type=url],
  select,textarea{font-size:16px}

  .topbar{position:sticky; top:0}
  .topbar .sub{display:none}
  /* a page's own actions take their own row rather than crushing the title */
  .topacts{display:flex; order:3; width:100%; gap:8px; flex-wrap:wrap}
  .topacts > *{flex:1 1 auto; min-width:0}
  .topacts form{display:flex}
  .topacts .btn{flex:1 1 auto; min-width:0; justify-content:center}
  .topacts .row{gap:8px}
  .topbar .spacer{display:none}

  .card > header{padding:12px 14px; gap:8px}
  .card .body{padding:14px}
  .grid2{gap:12px}
  .bar-row,.axis{grid-template-columns:minmax(76px,1fr) 1.4fr 42px; gap:8px}
  .frow,.funnel + .axis,.funnel .axis{grid-template-columns:minmax(70px,1fr) 1.3fr 42px; gap:8px}
  .camp{padding:14px}
  .camp .prog{min-width:0; width:100%}
  .camp .prog .bar-track{flex:1; width:auto}
  .stat{padding:13px 14px}
  .stat .v{font-size:23px}
  .wkpi{font-size:32px}
  .pv{padding:18px 14px calc(70px + env(safe-area-inset-bottom))}
  .pv h1{font-size:23px}
  .pv .lede{font-size:15px}
  .pv-head{gap:10px}
  .certsheet{padding:22px 18px}
  .certsheet h1{font-size:21px}
  .certsheet .who{font-size:23px}
  .cert{padding:16px}
  .cert dl,.certsheet dl{grid-template-columns:1fr; gap:2px}
  .cert dd,.certsheet dd{margin-bottom:8px; overflow-wrap:anywhere}
  .toast{left:12px; right:12px; transform:none; text-align:center;
    bottom:calc(16px + env(safe-area-inset-bottom))}
  .toast.show{transform:translateY(-4px)}
  .drop{padding:20px 14px}
  .logobox{width:100%; max-width:220px}
  /* a popover anchored to a table cell is unreachable on a phone; make it a
     sheet at the bottom of the screen instead */
  .editpop{position:fixed; inset:auto 8px calc(8px + env(safe-area-inset-bottom)) 8px;
    min-width:0; max-height:76vh; overflow-y:auto; z-index:80}
  .steps .step .t{white-space:normal; line-height:1.25}
  .q-view{padding:14px}
  .q-view .qt{font-size:14px}
}

/* Touch pointers need a target, not a 22px pill. Keyed on the pointer rather
   than the width, so a narrow laptop window is left alone. */
@media (pointer:coarse){
  .btn{min-height:40px}
  .btn.sm{min-height:36px; padding:7px 11px; font-size:12.5px}
  .tabs a,.tabs button{padding:13px 14px}
  .nav a{padding:11px 10px}
  .q-choice{padding:12px 13px}
  .jumpbtn{min-height:36px; padding:7px 13px}
  input[type=checkbox],input[type=radio]{width:19px; height:19px}
  .lang a{padding:9px 14px}
  summary.btn{min-height:36px}
}

/* a compact select that still reaches 16px on a phone, where anything
   smaller makes iOS Safari zoom the page */
.mini{padding:4px 8px; font-size:12.5px}
@media (max-width:620px){
  .mini{font-size:16px; padding:8px 10px}
  /* a bare tick box in the corner of a card needs a finger-sized area
     around it, not a bigger box */
  .cards td.pick{padding:6px; margin:-6px}
}

/* ---------- the new screens, on a phone ---------- */
@media (max-width:620px){
  .twosetup{grid-template-columns:1fr; gap:18px}
  .twoqr{align-items:flex-start}
  .twoqr svg{width:min(220px,60vw); height:auto}
  .waitcard .body{padding:20px 16px}
  .waitcard h2{font-size:16.5px}
  .codebox{font-size:20px !important; letter-spacing:.24em}
  .reccodes{grid-template-columns:1fr 1fr; padding-left:18px; gap:6px}
  .reccodes li{font-size:13px}
  .notifycard .btn{width:100%; justify-content:center}
  /* the finish screen: the seal shrinks, the actions become full-width rows,
     and the exact moment steps down a size rather than wrapping mid-stamp */
  .finale{padding:26px 16px 20px}
  .finale h2{font-size:21px}
  .finale .medal{width:76px; height:76px}
  .finale .stamp b{font-size:16px}
  .finale .factrow{gap:8px 14px}
  .finaleacts{width:100%; flex-direction:column; align-items:stretch}
  .finaleacts .btn{width:100%; justify-content:center}
  .finaleacts .reviewoff{align-items:stretch}
  .certwhen{align-self:stretch}
  .certwhen b{font-size:15px}
  .certseal{width:38px; height:38px}
  /* Georgian status labels run long. A pill that cannot wrap pushes the
     whole page sideways, which is far worse than a pill on two lines; the
     dot then lines up with the first line rather than the block's middle. */
  .pill{max-width:100%; white-space:normal; align-items:flex-start}
  .pill .dot{margin-top:5px}
  .camp .prog{flex-wrap:wrap}
}
@media print{
  /* recovery codes are meant to be printed and put somewhere safe */
  .rail,.topbar,.navscrim,.btn{display:none !important}
  .app{grid-template-columns:1fr}
  .reccodes li{font-size:15px}
}

/* ================= training areas, and the person signed in ==============
   An area is a department's own training programme. It gets a colour, and
   that colour is the thread that ties its card, its filter chip and its
   campaigns together — with the name always spelled out beside it, because
   colour alone is not a label anyone can read. */
.areagrid{display:grid; grid-template-columns:repeat(auto-fit,minmax(min(340px,100%),1fr)); gap:16px}
.areacard{display:flex; flex-direction:column; gap:12px; padding:16px;
  border-top:3px solid var(--ac, var(--accent))}
.areacard.off{opacity:.72}
.areahead{display:flex; gap:12px; align-items:flex-start}
.areahead h2{font-size:16px; line-height:1.25; margin:0}
.areahead .meta{display:flex; gap:6px; flex-wrap:wrap; align-items:center;
  font-size:12.5px; color:var(--muted); margin-top:3px}
.arealogo{width:44px; height:44px; object-fit:contain; border-radius:8px; flex:none;
  background:var(--surface-2); border:1px solid var(--line); padding:4px}
.areadot{width:44px; height:44px; flex:none; border-radius:10px; display:grid; place-items:center;
  background:var(--ac, var(--accent)); color:#fff; font-weight:700; font-size:18px}
.areastats{display:grid; grid-template-columns:repeat(auto-fit,minmax(76px,1fr)); gap:10px}
.areastats span{display:flex; flex-direction:column; gap:1px; font-size:11.5px; color:var(--muted)}
.areastats b{font-size:19px; color:var(--ink); line-height:1.1}
.arealinks{display:flex; gap:8px; flex-wrap:wrap; align-items:center}
.areapeople{display:flex; gap:6px; flex-wrap:wrap; align-items:center}
.lbl{font-size:11.5px; font-weight:600; letter-spacing:.03em; text-transform:uppercase;
  color:var(--muted)}
.areaedit{border-top:1px solid var(--line); padding-top:10px}
.areaedit summary{cursor:pointer; font-size:12.5px; font-weight:600; color:var(--accent)}
.areaedit > *:not(summary){margin-top:12px}
.grid2 .wide{grid-column:1/-1}
.tickrow{display:flex; gap:8px; flex-wrap:wrap}
.tick{display:inline-flex; gap:6px; align-items:center; cursor:pointer; font-size:12.5px;
  border:1px solid var(--line); border-radius:99px; padding:5px 11px; background:var(--surface-2)}
.tick input{accent-color:var(--accent)}
.warn-card{border-color:var(--warn-line, var(--line)); background:var(--warn-soft, var(--surface))}

/* the area filter above the campaign list */
.areafilter{display:flex; gap:8px; flex-wrap:wrap; border-bottom:1px solid var(--line)}
.chip{display:inline-flex; gap:7px; align-items:center; text-decoration:none; font-size:12.5px;
  font-weight:600; color:var(--ink-2); border:1px solid var(--line); background:var(--surface-2);
  padding:6px 12px; border-radius:99px; min-height:34px}
.chip i{width:8px; height:8px; border-radius:50%; background:var(--ac, var(--accent)); flex:none}
.chip:hover{border-color:var(--accent); color:var(--accent)}
.chip.on{background:var(--accent); border-color:var(--accent); color:var(--accent-ink)}
.chip.on i{background:currentColor}

/* the signed-in person, in the rail and on their own page */
.whoami{display:flex; gap:9px; align-items:center; text-decoration:none; color:inherit;
  padding:7px 8px; border-radius:10px; margin-bottom:8px}
.whoami:hover{background:var(--surface-2)}
.whoami .who{display:flex; flex-direction:column; min-width:0; line-height:1.25}
.whoami .who b{font-size:12.5px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
.whoami .who span{font-size:11px; color:var(--muted); overflow:hidden;
  text-overflow:ellipsis; white-space:nowrap}
.avatar{width:30px; height:30px; border-radius:50%; flex:none; object-fit:cover;
  background:var(--surface-3); border:1px solid var(--line)}
.avatar.ini{display:grid; place-items:center; font-weight:700; font-size:13px;
  background:var(--accent); color:var(--accent-ink); border-color:transparent}
.profilehead{display:flex; gap:22px; align-items:flex-start; flex-wrap:wrap}
.photoblock{display:flex; flex-direction:column; gap:8px; align-items:flex-start; width:180px}
.photoform{display:flex; gap:8px; align-items:center; flex-wrap:wrap}
.photoform input[type=file]{max-width:100%; font-size:11.5px}
.photohint{font-size:11.5px; line-height:1.5}
.bigavatar{width:112px; height:112px; border-radius:16px; object-fit:cover;
  background:var(--surface-3); border:1px solid var(--line)}
.bigavatar.ini{display:grid; place-items:center; font-size:44px; font-weight:700;
  background:var(--accent); color:var(--accent-ink); border-color:transparent}
.whocard{flex:1; min-width:220px}
.whocard h2{font-size:20px; margin:0}
.whocard .meta{display:flex; gap:8px; flex-wrap:wrap; align-items:center;
  font-size:12.5px; color:var(--muted); margin-top:6px}
td.agent{font-size:11.5px; max-width:280px; overflow:hidden; text-overflow:ellipsis;
  white-space:nowrap}

@media (max-width:620px){
  .areacard{padding:14px}
  .areastats b{font-size:17px}
  .profilehead{gap:16px}
  .photoblock{width:100%; align-items:center; text-align:center}
  .photoform{justify-content:center}
  .bigavatar{width:96px; height:96px}
  .whocard{text-align:center}
  .whocard .meta{justify-content:center}
  .areafilter{overflow-x:auto; flex-wrap:nowrap; padding-bottom:10px;
    scrollbar-width:none; -webkit-overflow-scrolling:touch}
  .areafilter::-webkit-scrollbar{display:none}
  .chip{white-space:nowrap; flex:none}
  td.agent{max-width:140px}
}
/* the area a campaign belongs to, on its row in the list */
.areatag{display:inline-flex; gap:5px; align-items:center; font-weight:600; color:var(--ink-2)}
.areatag i{width:7px; height:7px; border-radius:50%; background:var(--ac, var(--accent)); flex:none}

/* ---------- the read-only administrator ----------
   A viewer sees every screen and changes nothing. The badge says so once, in
   the title bar, and each form that would write is visibly switched off —
   a control that looks live and then fails is worse than one plainly off. */
.ropill{display:inline-flex; align-items:center; gap:6px; flex:none; font-size:11.5px;
  font-weight:700; letter-spacing:.04em; text-transform:uppercase; cursor:default;
  color:var(--warn); background:var(--warn-soft, rgba(150,110,20,.10));
  border:1px solid var(--warn-line, rgba(150,110,20,.30));
  padding:4px 10px; border-radius:99px}
.ropill::before{content:""; width:7px; height:7px; border-radius:50%; background:var(--warn)}
form.ro{opacity:.72}
form.ro input:read-only, form.ro textarea:read-only{background:var(--surface-2); cursor:default}
form.ro button:disabled, form.ro .btn:disabled{cursor:not-allowed}
@media (max-width:620px){
  .ropill{font-size:10.5px; padding:3px 8px}
}
.drop.ro{opacity:.55; cursor:not-allowed; border-style:solid}

/* ---------- reports ----------
   The catalogue is a grid of cards, because a report is chosen by reading
   what it answers, not by scanning a list of names. */
.repgrid{display:grid; grid-template-columns:repeat(auto-fill,minmax(min(290px,100%),1fr)); gap:12px}
.repcard{display:flex; flex-direction:column; gap:6px; text-decoration:none; color:inherit;
  border:1px solid var(--line); border-radius:var(--radius); padding:13px 14px;
  background:var(--surface); transition:border-color .12s, transform .12s}
a.repcard:hover{border-color:var(--accent); transform:translateY(-1px)}
.repcard b{font-size:13.5px; line-height:1.3}
.repcard > span{font-size:12px; color:var(--muted); line-height:1.5}
.repfoot{display:flex; gap:6px; align-items:center; flex-wrap:wrap; margin-top:4px}
.repfoot .tag{font-size:10.5px; font-weight:600; letter-spacing:.02em; text-transform:uppercase;
  color:var(--ink-2); background:var(--surface-2); border:1px solid var(--line);
  padding:2px 8px; border-radius:99px}
.repfoot .go{margin-inline-start:auto; font-size:12px; font-weight:600; color:var(--accent)}
.repcard.static{background:var(--surface-2)}
.colpick{max-height:190px; overflow-y:auto; padding:2px}
.reptable td{white-space:nowrap; max-width:320px; overflow:hidden; text-overflow:ellipsis}
.reptable tbody tr:last-child td{font-weight:600}
tr.off{opacity:.6}
@media (max-width:620px){
  .repgrid{grid-template-columns:1fr}
  .colpick{max-height:150px}
}

/* ---------- the permission matrix ----------
   A wide grid read across rather than down: the permission on the left, one
   narrow column per role. The help line under each name is what stops the
   table becoming a wall of jargon. */
.permtable{min-width:640px}
.permtable td:first-child, .permtable th:first-child{text-align:start; min-width:230px}
.permtable .permrole{text-align:center; font-size:11.5px; line-height:1.3;
  white-space:normal; min-width:88px; max-width:120px; vertical-align:bottom}
.permhelp{display:block; font-size:11.5px; color:var(--muted); line-height:1.45; margin-top:2px}
.permgroup td{background:var(--surface-2); font-weight:700; font-size:11.5px;
  letter-spacing:.04em; text-transform:uppercase; color:var(--ink-2)}
.permcell{text-align:center; vertical-align:middle}
.permbox{display:inline-flex; padding:6px; cursor:pointer}
.permbox input{width:17px; height:17px; accent-color:var(--accent); cursor:pointer}
.permlock{display:inline-block; font-weight:700; color:var(--ok); cursor:default}
.sr{position:absolute; width:1px; height:1px; overflow:hidden; clip:rect(0 0 0 0);
  white-space:nowrap}
@media (max-width:620px){
  .permtable td:first-child, .permtable th:first-child{min-width:180px}
  .permtable .permrole{min-width:64px; font-size:10.5px}
  .permhelp{display:none}
}

/* ---------------------------------------------------------------------
   the HTTPS certificate card

   Certificate facts read best as short labelled pairs rather than a table:
   a fingerprint is 64 characters and a host list can be long, so the grid
   collapses to one column early and every value is allowed to wrap. */
.banner.risk{background:var(--risk-soft); border-color:var(--risk-line); color:var(--risk)}
.banner.ok{background:var(--ok-soft); border-color:var(--ok-line); color:var(--ok)}
.certfacts{display:grid; gap:13px 20px; margin:0;
  grid-template-columns:repeat(auto-fit,minmax(min(215px,100%),1fr))}
.certfacts > div{min-width:0}
.certfacts dt{font-size:11.5px; font-weight:600; letter-spacing:.03em;
  text-transform:uppercase; color:var(--muted)}
.certfacts dd{margin:4px 0 0; font-size:13px; line-height:1.55; overflow-wrap:anywhere}
.certfacts dd .pill{display:inline-flex}
.tlsnotes{margin:0; padding:0; list-style:none; display:flex; flex-direction:column; gap:6px}
.tlsnotes li{font-size:12.5px; line-height:1.5; padding-inline-start:14px; position:relative}
.tlsnotes li::before{content:""; position:absolute; inset-inline-start:0; top:7px;
  width:6px; height:6px; border-radius:99px; background:currentColor}
.tlsnotes li.warn{color:var(--warn)}
.tlsnotes li.risk{color:var(--risk)}
.cmdline{font-family:var(--mono); font-size:12px; background:var(--surface-3);
  border:1px solid var(--line); border-radius:10px; padding:9px 12px;
  overflow-x:auto; white-space:pre; -webkit-overflow-scrolling:touch}
.tlsmore summary{font-size:11.5px; font-weight:600; letter-spacing:.03em;
  text-transform:uppercase; color:var(--muted); cursor:pointer}
.tlsmore[open] summary{margin-bottom:2px}
input[type=file]{font-size:12.5px; max-width:100%}

/* ---------------------------------------------------------------------
   the certificate guide

   A document rather than a screen: one readable column, generous line
   height, and code blocks that scroll sideways on a phone instead of
   forcing the whole page to. */
.guide{display:flex; flex-direction:column; gap:16px}
.prose{max-width:78ch; font-size:13.5px; line-height:1.75; color:var(--ink-2)}
.prose h2{font-size:17px; color:var(--ink); margin:0 0 10px; line-height:1.35}
.prose h3{font-size:13.5px; color:var(--ink); margin:20px 0 6px; letter-spacing:.01em}
.prose p{margin:0 0 11px}
.prose ul, .prose ol{margin:0 0 12px; padding-inline-start:20px}
.prose li{margin-bottom:7px}
.prose code{font-family:var(--mono); font-size:.88em; background:var(--surface-3);
  border:1px solid var(--line); border-radius:5px; padding:1px 5px; overflow-wrap:anywhere}
.prose a{color:var(--accent)}
.prose .note{border-inline-start:3px solid var(--accent); background:var(--accent-soft);
  border-radius:0 10px 10px 0; padding:10px 14px; margin:14px 0}
.prose ol.pick{counter-reset:none}
.prose ol.pick li{margin-bottom:10px}
.guidecode{font-family:var(--mono); font-size:11.8px; line-height:1.62;
  background:var(--surface-3); border:1px solid var(--line); border-radius:10px;
  padding:12px 14px; margin:0 0 13px; overflow-x:auto; white-space:pre;
  -webkit-overflow-scrolling:touch; color:var(--ink)}
.guidetable{width:100%; border-collapse:collapse; margin:0 0 13px; font-size:12.5px}
.guidetable td{border-top:1px solid var(--line); padding:9px 10px 9px 0;
  vertical-align:top; line-height:1.6}
.guidetable tr:first-child td{border-top:0}
.guidetable td:first-child{white-space:normal; padding-inline-end:16px; width:34%}
@media (max-width:560px){
  .guidetable td{display:block; padding:4px 0}
  .guidetable td:first-child{width:auto; border-top:1px solid var(--line); padding-top:10px}
  .guidetable tr:first-child td:first-child{border-top:0}
  .guidecode{font-size:11px}
}
@media print{
  .app > aside, .topbar, .guide .btn, .flash{display:none !important}
  .guide .card{break-inside:avoid; border:0; box-shadow:none}
}

/* The certificate warning bar. It sits above the page rather than inside a
   card because it is not about the page you are on. */
.certbar{display:flex; gap:10px; align-items:center; text-decoration:none;
  padding:11px 15px; border-radius:var(--radius); margin-bottom:16px;
  font-size:13px; line-height:1.45; font-weight:500;
  background:var(--warn-soft); border:1px solid var(--warn-line); color:var(--warn)}
.certbar.risk{background:var(--risk-soft); border-color:var(--risk-line); color:var(--risk)}
.certbar svg{width:17px; height:17px; flex:none}
.certbar span{flex:1; min-width:0}
.certbar b{font-weight:700; white-space:nowrap}
@media (max-width:520px){
  .certbar{flex-wrap:wrap}
  .certbar b{width:100%; padding-inline-start:27px}
}
