/* ============================================================================
   PARTNERS — partners.loyaltycards.click
   ----------------------------------------------------------------------------
   Only what app.css does not already give. The shell, the rail, the tab bar,
   buttons, fields, notes, tiles, stats, badges and table.t all come from
   app/css/app.css, so this app looks like the same product rather than a
   cousin of it.

   Nothing here redefines a token. The brand variables are the app's.
   ========================================================================== */

/* ── Page furniture ─────────────────────────────────────────────────────── */
/* No .pagehead here: app.css already has .phead/.phead-txt, with the right
   type scale and --gap-section beneath it. The first build of this app
   invented a smaller one, which is most of why these screens read as a
   different product.

   The small print under a panel. Used often enough to deserve a name. */
.fine{font-size:13px;line-height:1.55;margin:10px 0 0}
.fine:first-child{margin-top:0}

/* A two-up field row that collapses on a phone. */
.two{display:grid;grid-template-columns:1fr 1fr;gap:0 14px}
@media (max-width:560px){ .two{grid-template-columns:1fr} }

/* A checklist. The tick is the bullet, so the text aligns under itself. */
.ticks{list-style:none;margin:0;padding:0;display:grid;gap:9px}
.ticks li{display:flex;gap:9px;font-size:14.5px;line-height:1.5}
.ticks li i{color:var(--brand);line-height:1.5;flex-shrink:0}

/* A figure that is money. Negative reads as negative without a colour alone
   carrying it — the minus sign is in the text. */
.neg{color:var(--danger)}

/* ── Tables ─────────────────────────────────────────────────────────────── */
/* A second line inside a cell: the detail that would otherwise need its own
   column and make the table scroll on a phone. */
table.t td .sub{display:block;font-size:12.5px;color:var(--muted);margin-top:2px}
table.t td .badge{margin-top:4px}
table.t tr.quiet td{color:var(--faint)}
table.t tr.quiet td .nums{opacity:.55}

/* The state word lives in the Plan column on a wide screen, where there is
   room for it, and moves under the shop name on a narrow one. */
.only-s{display:none}
@media (max-width:620px){
  table.t.bizt td:nth-child(2){display:none}
  table.t.bizt th:nth-child(2){display:none}
  .only-s{display:inline-flex;margin-top:5px}
}

/* ── The link, which is why anybody is here ─────────────────────────────── */
/* A tint and a brand edge — the same emphasis the app gives a panel that
   matters. The first version was a gradient that appears nowhere else in the
   product, which is exactly how a screen starts looking off-brand. */
.linkbox{border-color:var(--brand-line);background:var(--brand-wash)}
.copyrow{display:flex;gap:10px}
.copyrow .input{flex:1;min-width:0;font-family:var(--mono);font-size:13.5px}
.copyrow .btn{flex-shrink:0}
@media (max-width:480px){
  .copyrow{flex-direction:column}
  .copyrow .btn{width:100%;justify-content:center}
}

/* One tagged link per channel. */
.srcgrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,230px),1fr));
  gap:10px;margin-top:4px}
.srcbtn{display:flex;align-items:center;gap:10px;text-align:left;padding:12px 14px;
  border:1px solid var(--line);border-radius:var(--r-sm);background:var(--surface);
  font:inherit;cursor:pointer;min-width:0;
  transition:border-color var(--t-fast),background var(--t-fast)}
.srcbtn:hover{border-color:var(--brand-line);background:var(--brand-wash)}
.srcbtn b{display:block;font-size:14px;font-weight:600;color:var(--ink);
  text-transform:capitalize;letter-spacing:-.015em}
.srcbtn span{display:block;font-size:11.5px;color:var(--faint);font-family:var(--mono);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.srctxt{flex:1;min-width:0;display:block}
.srcbtn i{color:var(--faint);font-size:17px;flex-shrink:0}

/* Ready-made copy, so a partner is not inventing the price. */
.pitchcard{border:1px solid var(--line);border-radius:var(--r-sm);padding:14px 16px;
  margin-bottom:10px;background:var(--surface-2)}
.pitchcard:last-of-type{margin-bottom:0}
.pitchhead{display:flex;align-items:center;justify-content:space-between;gap:12px;
  margin-bottom:8px}
.pitchhead b{font-size:13.5px;font-weight:600;color:var(--ink)}
.pitchcard p{margin:0;font-size:14px;line-height:1.6;color:var(--text)}

/* ── Earnings per month ─────────────────────────────────────────────────── */
/* The same bar chart the console draws on its Overview: a flex row, bars
   whose OPACITY carries the value as well as their height, so a quiet month
   reads as quiet rather than merely short. Twelve values do not justify a
   charting library, and a div has a height on every phone. */
.chart{display:flex;align-items:flex-end;gap:3px;height:150px;margin-top:4px}
.chart .col{flex:1;display:flex;flex-direction:column;justify-content:flex-end;
  align-items:center;height:100%;min-width:0;gap:8px}
.colbar{display:block;width:100%;border-radius:3px 3px 0 0;background:var(--brand);
  transition:opacity var(--t-fast)}
.chart .col:hover .colbar{opacity:1!important}
.collab{font-size:11px;color:var(--faint);white-space:nowrap}
@media (max-width:620px){ .collab{font-size:10px} }

/* ── The course ─────────────────────────────────────────────────────────── */
/* A tile that is a link. .tile is a div component in app.css; this is the
   anchor form, with the hover and the underline suppression it needs. */
a.lesson{text-decoration:none;margin-bottom:8px;
  transition:border-color var(--t-fast),background var(--t-fast)}
a.lesson:last-of-type{margin-bottom:0}
a.lesson:hover{border-color:var(--brand-line);background:var(--brand-wash);
  text-decoration:none}
a.lesson > i{color:var(--faint);font-size:18px;flex-shrink:0}
a.lesson.unread{border-color:var(--brand-line)}
a.lesson.unread .tile-txt > b:after{content:'';display:inline-block;width:7px;height:7px;
  border-radius:50%;background:var(--brand);margin-left:7px;vertical-align:middle}

.backlink{display:inline-flex;align-items:center;gap:6px;font-size:13.5px;font-weight:600;
  color:var(--muted);margin-bottom:14px}
.backlink:hover{color:var(--ink);text-decoration:none}

/* One lesson, set for reading. Measure before decoration: this is the only
   screen in the app somebody reads rather than scans. */
.lessonbody{max-width:66ch}
.lessonbody h1{font-size:clamp(25px,3.6vw,33px);line-height:1.14;text-wrap:balance;
  margin-bottom:10px}
.lessonbody .lead{font-size:17px;line-height:1.55;color:var(--muted);
  margin:0 0 26px;text-wrap:pretty}
.lessonbody h2{font-size:19px;margin:30px 0 10px;letter-spacing:-.02em}
.lessonbody p{margin:0 0 15px;font-size:15.5px;line-height:1.68;color:var(--text)}
.lessonbody ul,.lessonbody ol{margin:0 0 18px;padding-left:22px}
.lessonbody li{font-size:15.5px;line-height:1.66;color:var(--text);margin-bottom:7px}
.lessonbody strong{font-weight:600;color:var(--ink)}
.lessonbody code{font-family:var(--mono);font-size:13.5px;background:var(--surface-2);
  padding:2px 6px;border-radius:6px;color:var(--ink);overflow-wrap:anywhere}
.lessonbody blockquote{margin:0 0 18px;padding:14px 18px;border-left:3px solid var(--brand);
  background:var(--brand-wash);border-radius:0 var(--r-sm) var(--r-sm) 0;
  font-size:15px;line-height:1.62;color:var(--text)}

/* ── Support conversation ───────────────────────────────────────────────── */
.msg{padding:14px 16px;border-radius:var(--r-sm);margin-bottom:10px;font-size:14.5px;
  line-height:1.6;color:var(--text)}
.msg .who{display:block;font-size:11.5px;font-weight:600;letter-spacing:.06em;
  text-transform:uppercase;color:var(--faint);margin-bottom:6px}
.msg.you{background:var(--surface-2)}
.msg.them{background:var(--brand-wash);border:1px solid var(--brand-line)}

/* ── A word about something that worked ─────────────────────────────────── */
.ptoast{position:fixed;left:50%;bottom:calc(var(--tabbar) + 18px);transform:translateX(-50%);
  z-index:90;display:flex;align-items:center;gap:9px;max-width:calc(100vw - 32px);
  padding:12px 18px;border-radius:var(--pill);background:var(--ink);color:#fff;
  font-size:14px;font-weight:500;box-shadow:var(--sh-lg);
  animation:ptoast-in .26s cubic-bezier(.2,.9,.3,1)}
.ptoast i{font-size:18px;color:#9FE3B8;flex-shrink:0}
.ptoast.bad i{color:#FFB4A8}
.ptoast.go{opacity:0;transform:translateX(-50%) translateY(8px);
  transition:opacity .4s,transform .4s}
@keyframes ptoast-in{from{opacity:0;transform:translateX(-50%) translateY(14px)}}
@media (min-width:901px){ .ptoast{bottom:26px} }
@media (prefers-reduced-motion:reduce){
  .ptoast{animation:none}
  .ptoast.go{transition:opacity .2s}
}

/* ============================================================================
   PARTNER OPS — the operator's screens (admin.html)
   ========================================================================== */

/* An application, laid out so the whole of it is read before either button
   is pressed. A name, an email and two buttons gets approved unread. */
.apphead{display:flex;align-items:flex-start;justify-content:space-between;gap:16px;
  margin-bottom:16px}
.apphead h2{font-size:19px;letter-spacing:-.025em}
.apphead .fine{margin-top:3px}

.appmeta{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,150px),1fr));
  gap:14px 20px;padding:14px 0;border-top:1px solid var(--line-soft);
  border-bottom:1px solid var(--line-soft)}
.appmeta .label{display:block;margin-bottom:3px}
.appmeta b{font-size:14.5px;font-weight:600;color:var(--ink);overflow-wrap:anywhere}

.applinks{display:flex;flex-wrap:wrap;gap:8px;margin:14px 0 0}
.applinks .chip{text-decoration:none}
.applinks .chip:hover{text-decoration:none}

/* Their own words, set apart from our summary of them. */
.pitch{margin:16px 0 0;padding:14px 18px;border-left:3px solid var(--brand-line);
  background:var(--surface-2);border-radius:0 var(--r-sm) var(--r-sm) 0;
  font-size:14.5px;line-height:1.62;color:var(--text)}

.appact{display:flex;flex-wrap:wrap;align-items:flex-end;gap:12px;margin-top:18px}
.rejectbox{margin:16px 0 0;padding-top:16px;border-top:1px solid var(--line-soft)}

/* ── A tall step on a short screen ──────────────────────────────────────── */
/* flow.css centres the card with align-items:center. That overflows in BOTH
   directions: when a step is taller than the viewport its top goes ABOVE the
   start edge, where no amount of scrolling reaches it — the application's
   last step did exactly this, putting its heading and its textarea off the
   top of a 900px window.
   Auto margins centre the same way but refuse to overflow the start edge, so
   a tall step begins at the top and the page simply grows. Done here rather
   than in flow.css, which is a policed copy of the app's own. */
.flow-body{align-items:flex-start}
.flow-card{margin-block:auto}

/* ── Getting started ────────────────────────────────────────────────────── */
/* A checklist where only the CURRENT step carries its explanation and its
   button. Five buttons is five things to do at once, which is how somebody
   decides to do none of them. */
.startlist{list-style:none;margin:0;padding:0;display:grid;gap:4px;counter-reset:none}
.startlist li{display:flex;gap:12px;padding:12px 0;border-bottom:1px solid var(--line-soft)}
.startlist li:last-child{border-bottom:0}
.startlist li > i{font-size:20px;line-height:1.3;flex-shrink:0;color:var(--faint)}
.startlist li.done > i{color:var(--ok)}
.startlist li.now > i{color:var(--brand)}
.startlist li > div{min-width:0;flex:1}
.startlist b{display:block;font-size:14.5px;font-weight:600;color:var(--faint);
  letter-spacing:-.015em;line-height:1.35}
.startlist li.done b{color:var(--muted);text-decoration:line-through;
  text-decoration-color:var(--line)}
.startlist li.now b{color:var(--ink);font-size:15.5px}
.startlist span{display:block;font-size:13.5px;color:var(--muted);line-height:1.5;
  margin-top:3px}
.startlist .btn{margin-top:10px}

/* ============================================================================
   THE LOCKUP — the product's wordmark, and what this app is
   ----------------------------------------------------------------------------
   LoyaltyCards is the product. "Partnership programme" is which door of it you
   are standing in. So the wordmark is the real one, unaltered, and the words
   beside it are set small and quiet behind a hairline — a subtitle, not a
   second brand.

   BOTH the square icon and the horizontal wordmark are in the markup, and CSS
   picks. logo.css gives the reason and it holds here: swapping the src from
   JavaScript paints the wrong one first on every single load.
   ========================================================================== */
.lockup{display:flex;align-items:center;gap:10px;min-width:0;flex-shrink:0;
  text-decoration:none!important}
.lockup:hover{text-decoration:none}

/* The wordmark. 22px in the rail: at 5.64:1 that is 124px, which leaves room
   for the subtitle inside the rail's 212px of usable width. */
.lockup .wm{--wm:22px;flex-shrink:0}

/* The subtitle. Behind a hairline rule rather than a slash or a bullet,
   because a rule reads as "this belongs to that" where punctuation reads as
   two things of equal weight. */
.lockup-sub{font-size:10.5px;line-height:1.25;font-weight:600;letter-spacing:.07em;
  text-transform:uppercase;color:var(--faint);padding-left:10px;
  border-left:1px solid var(--line);min-width:0}

/* In the rail and the console header the icon is hidden — until the rail
   collapses to 76px, which is not a measure this wordmark can be set across.
   That is what the square app icon is for, and it is the one already on the
   phone's home screen. */
.rail-top .lockup .applogo,
.topbar  .lockup .applogo{display:none}

@media (max-width:1099px){
  .rail-top .lockup .applogo{display:block}
  .rail-top .lockup .wm,
  .rail-top .lockup-sub{display:none}
}

/* The phone's top bar is full width, so the wordmark fits and the subtitle
   sits beside it on one line. */
@media (max-width:767px){
  .topbar .lockup .wm{--wm:20px}
  .topbar .lockup-sub{font-size:9.5px;letter-spacing:.06em}
  .topbar .lockup-sub br{display:none}
  .topbar .lockup-sub:before{content:' '}
}

/* Sign-in and the application flow sit on a full-width bar: bigger, and the
   subtitle on one line. */
.flow-bar .lockup .applogo{display:none}
.flow-bar .lockup .wm{--wm:26px}
.flow-bar .lockup-sub{font-size:11px}
@media (max-width:520px){
  .flow-bar .lockup .wm{--wm:21px}
  .flow-bar .lockup-sub{display:none}
}

/* ── The knowledge check ────────────────────────────────────────────────── */
/* A fieldset per question, because that is what a group of radios is, and it
   is what a screen reader announces as one. */
.qz{border:1px solid var(--line);border-radius:var(--r);padding:16px 18px;margin:0 0 12px;
  background:var(--surface);transition:border-color var(--t-fast),background var(--t-fast)}
.qz.answered{border-color:var(--brand-line);background:var(--brand-wash)}
.qz legend{display:flex;gap:10px;font-size:15px;font-weight:600;color:var(--ink);
  letter-spacing:-.015em;line-height:1.4;padding:0;margin-bottom:12px}
.qz-n{flex-shrink:0;width:22px;height:22px;border-radius:50%;background:var(--brand-soft);
  color:var(--brand-deep);font-size:12px;font-weight:700;display:grid;place-items:center;
  margin-top:1px}

.qz-opt{display:flex;align-items:flex-start;gap:10px;padding:9px 10px;border-radius:var(--r-xs);
  cursor:pointer;font-size:14.5px;line-height:1.5;color:var(--text)}
.qz-opt:hover{background:var(--surface-2)}
.qz-opt input{margin:3px 0 0;accent-color:var(--brand);flex-shrink:0;width:16px;height:16px}
.qz-opt input:checked + span{color:var(--ink);font-weight:500}

/* ── The terms checkbox ─────────────────────────────────────────────────── */
/* A real label wrapping a real checkbox: the whole sentence is the hit area,
   which on a phone is the difference between accepting the terms and missing
   a 16px box three times. */
.agree{display:flex;align-items:flex-start;gap:12px;padding:16px 18px;cursor:pointer;
  border:1px solid var(--line);border-radius:var(--r);background:var(--surface-2);
  font-size:14.5px;line-height:1.55;color:var(--text)}
.agree:hover{border-color:var(--brand-line)}
.agree input{margin:2px 0 0;accent-color:var(--brand);flex-shrink:0;width:18px;height:18px}
.agree:has(input:checked){border-color:var(--brand-line);background:var(--brand-wash)}

/* ── The social fields ──────────────────────────────────────────────────── */
.field > label > .ti{font-size:15px;color:var(--faint);margin-right:2px;vertical-align:-2px}

/* ── The knowledge check, on the screening card ─────────────────────────── */
/* Open by default for a low score, because that is the one the operator needs
   to read. A good score can stay folded away. */
.quizbox{margin-top:var(--gap-card);border:1px solid var(--line);border-radius:var(--r);
  background:var(--surface-2);overflow:hidden}
.quizbox > summary{cursor:pointer;padding:13px 16px;font-size:14px;color:var(--muted);
  display:flex;align-items:center;gap:8px;list-style:none;user-select:none}
.quizbox > summary::-webkit-details-marker{display:none}
.quizbox > summary b{color:var(--ink);font-weight:600}
.quizbox > summary > i{margin-left:auto;font-size:17px;transition:transform var(--t-fast)}
.quizbox[open] > summary > i{transform:rotate(180deg)}
.quizbox > summary:hover{background:var(--surface)}
.quizbox .fine{padding:0 16px 14px;margin:0}

.qzr{display:flex;gap:11px;padding:12px 16px;border-top:1px solid var(--line-soft);
  background:var(--surface)}
.qzr > .badge{flex-shrink:0;height:24px;align-self:flex-start}
.qzr b{display:block;font-size:13.5px;font-weight:600;color:var(--ink);line-height:1.4}
.qzr .said{display:block;font-size:13px;color:var(--muted);margin-top:4px}
.qzr .real{display:block;font-size:12.5px;color:var(--ok);margin-top:2px}

/* The palette has --ok and --ok-soft but no green hairline, and these
   panels need one. Defined once here rather than repeating a literal. */
:root{--ok-line:#C2DECD}

/* ════════════════════════════════════════════════════════════════════════
   THE COURSE
   ------------------------------------------------------------------------
   Ten lessons over seven days, an exam, a certificate. The DAY is the unit
   an affiliate plans around, so the day is what the screen is built from.
   ══════════════════════════════════════════════════════════════════════ */
.crs-bar{display:flex;align-items:center;gap:14px;margin-bottom:var(--gap-card)}
.crs-prog{flex:1;height:8px;border-radius:var(--pill);background:var(--surface-2);
  overflow:hidden}
.crs-prog i{display:block;height:100%;border-radius:var(--pill);
  background:linear-gradient(90deg,var(--brand),var(--brand-deep));
  transition:width .5s cubic-bezier(.2,.9,.25,1)}
.crs-bar .nums{font-size:13px;font-weight:600;color:var(--muted);flex:none}

/* The banner that changes with where they are: nothing, then "sit the
   exam", then "you passed". */
.crs-done{display:flex;align-items:center;gap:14px;padding:16px 18px;
  border-radius:var(--r);background:var(--ok-soft);border:1px solid var(--ok-line);
  margin-bottom:var(--gap-card)}
.crs-done.crs-ready{background:var(--brand-soft);border-color:var(--brand-line)}
.crs-done > div{flex:1;display:flex;flex-direction:column}
.crs-done b{font-size:15px;color:var(--ink)}
.crs-done span{font-size:13.5px;color:var(--muted)}
.crs-ic{width:42px;height:42px;border-radius:50%;flex:none;display:flex;
  align-items:center;justify-content:center;font-size:21px;
  background:#fff;color:var(--ok)}
.crs-ready .crs-ic{color:var(--brand)}

.crs-day .shead{align-items:flex-start;gap:12px}
.crs-day .shead h2{font-size:17px;margin:0}
.crs-n{width:32px;height:32px;border-radius:50%;flex:none;display:flex;
  align-items:center;justify-content:center;font-size:14px;font-weight:600;
  background:var(--brand-soft);color:var(--brand)}
.crs-day.is-done .crs-n{background:var(--ok-soft);color:var(--ok)}

.tile.lesson{gap:12px}
.crs-tick{flex:none;font-size:20px;color:var(--line);display:flex}
.tile.lesson.is-done .crs-tick{color:var(--ok)}
.tile.lesson.is-done .tile-txt b{color:var(--muted)}
.crs-min{flex:none;font-size:12.5px;color:var(--faint);white-space:nowrap}

.crs-eyebrow{font-size:12px;font-weight:600;letter-spacing:.05em;
  text-transform:uppercase;color:var(--brand);margin:0 0 8px}

/* "Mark as done" — the only thing that completes a lesson. Scroll position
   is not consent. */
.crs-mark{display:flex;align-items:center;gap:14px;margin-top:30px;
  padding:18px 20px;border-radius:var(--r);
  background:var(--brand-soft);border:1px solid var(--brand-line)}
.crs-mark.is-done{background:var(--ok-soft);border-color:var(--ok-line)}
.crs-mark > div{flex:1;display:flex;flex-direction:column}
.crs-mark b{font-size:15px;color:var(--ink)}
.crs-mark span{font-size:13.5px;color:var(--muted)}
.crs-mark .crs-ic{color:var(--brand)}
.crs-mark.is-done .crs-ic{color:var(--ok)}

/* ── The exam ──────────────────────────────────────────────────────────── */
.examhead{margin-bottom:var(--gap-card)}
.examhead h1{font-size:clamp(26px,3vw,34px);letter-spacing:-.025em;margin:0 0 8px}
.exam{display:flex;flex-direction:column;gap:14px}
.exq{border:1px solid var(--line);border-radius:var(--r);background:var(--surface);
  padding:18px 20px;margin:0;display:flex;flex-direction:column;gap:9px;
  transition:border-color .25s ease,background .25s ease}
.exq.is-answered{border-color:var(--brand-line);background:var(--surface)}
/* The one they skipped, so it is findable on a thirty-question page. */
.exq.is-missed{border-color:var(--danger);background:var(--danger-soft)}
.exq legend{display:flex;gap:10px;font-size:15.5px;font-weight:500;color:var(--ink);
  line-height:1.45;padding:0;margin-bottom:4px}
.exq-n{width:24px;height:24px;border-radius:50%;background:var(--brand);color:#fff;
  font-size:12.5px;font-weight:600;display:flex;align-items:center;
  justify-content:center;flex:none;margin-top:1px}
.exq-opt{display:flex;align-items:flex-start;gap:11px;border:1.5px solid var(--line);
  border-radius:var(--r-sm);padding:12px 14px;font-size:14.5px;color:var(--text);
  line-height:1.45;cursor:pointer;transition:border-color .2s ease,background .2s ease}
.exq-opt:hover{border-color:var(--brand-line)}
.exq-opt input{margin:2px 0 0;accent-color:var(--brand);flex:none}
.exq-opt:has(input:checked){border-color:var(--brand);background:var(--brand-soft)}

.exam-foot{display:flex;align-items:center;justify-content:space-between;gap:14px;
  flex-wrap:wrap;position:sticky;bottom:0;padding:16px 0;
  background:linear-gradient(180deg,transparent,var(--paper) 34%)}
.exam-foot p{margin:0}

/* ── The result ────────────────────────────────────────────────────────── */
.exres{text-align:center;padding:34px 20px 30px;border-radius:var(--r-lg);
  margin-bottom:30px;border:1px solid var(--line);background:var(--surface)}
.exres.is-pass{background:var(--ok-soft);border-color:var(--ok-line)}
.exres.is-fail{background:var(--surface-2)}
.exres-ic{width:62px;height:62px;border-radius:50%;background:#fff;
  display:flex;align-items:center;justify-content:center;font-size:31px;
  margin:0 auto 16px;color:var(--muted)}
.exres.is-pass .exres-ic{color:var(--ok)}
.exres h1{font-size:clamp(25px,3vw,33px);letter-spacing:-.025em;margin:0 0 6px}
.exres-score{font-size:clamp(30px,4vw,42px);font-weight:600;color:var(--ink);
  margin:10px 0 6px;letter-spacing:-.03em}
.exres-score span{display:block;font-size:15px;font-weight:500;color:var(--muted);
  letter-spacing:0}
.exres .lead{max-width:48ch;margin:0 auto 20px;color:var(--muted)}
.exres-h{font-size:19px;letter-spacing:-.02em;margin:0 0 14px}

.exrev{border:1px solid var(--line);border-left:3px solid var(--line);
  border-radius:var(--r-sm);padding:14px 16px;background:var(--surface)}
.exrev.is-right{border-left-color:var(--ok)}
.exrev.is-wrong{border-left-color:var(--danger)}
.exrev-top{display:flex;align-items:flex-start;gap:10px}
.exrev-top b{flex:1;font-size:14.5px;font-weight:500;color:var(--ink);line-height:1.45}
.exrev-why{font-size:13.5px;color:var(--muted);line-height:1.6;
  margin:9px 0 0 34px}

/* ── The certificate ───────────────────────────────────────────────────── */
.certwrap{display:flex;justify-content:center;padding:6px 0 22px}
.cert{width:100%;max-width:720px;aspect-ratio:1.414;background:#fff;
  border:1px solid var(--line);border-radius:var(--r);
  box-shadow:0 30px 70px -36px rgba(16,8,34,.4);
  padding:clamp(26px,4.4vw,52px);display:flex;flex-direction:column;
  align-items:center;justify-content:center;text-align:center;gap:4px}
.cert-rule{width:58px;height:3px;border-radius:2px;background:var(--brand);
  margin:0 auto}
.cert-wm{width:clamp(130px,18vw,180px);height:auto;margin:18px 0 10px}
.cert-kicker{font-size:12px;font-weight:600;letter-spacing:.17em;
  text-transform:uppercase;color:var(--muted);margin:0}
.cert-name{font-size:clamp(27px,4.6vw,42px);letter-spacing:-.025em;
  margin:10px 0 12px;color:var(--ink)}
.cert-body{font-size:clamp(13.5px,1.5vw,15.5px);line-height:1.65;color:var(--text);
  max-width:46ch;margin:0 0 22px}
.cert-body b{font-weight:600;color:var(--ink)}
.cert-feet{display:flex;gap:clamp(18px,4vw,44px);margin-bottom:20px;flex-wrap:wrap;
  justify-content:center}
.cert-feet div{display:flex;flex-direction:column;gap:3px}
.cert-feet span{font-size:10.5px;font-weight:600;letter-spacing:.09em;
  text-transform:uppercase;color:var(--faint)}
.cert-feet b{font-size:13.5px;color:var(--ink);font-weight:600}

.cta-row{display:flex;justify-content:center;gap:12px;flex-wrap:wrap}

/* Printing. The browser's own "Save as PDF" makes a better file than
   anything we would generate server-side, and the project carries no PDF
   dependency — poster.html already prints exactly this way. */
.no-print{display:revert}
@media print{
  /* Backgrounds are stripped by default, which would print the certificate
     as grey text on white. */
  html,body,.cert{-webkit-print-color-adjust:exact;print-color-adjust:exact}
  body{background:#fff}
  .no-print,.rail,.topbar,.bell,.appnav,nav,footer,.backlink{display:none!important}
  main,.wrap,#page{margin:0!important;padding:0!important;max-width:none!important}
  .certwrap{padding:0}
  .cert{max-width:none;width:100%;border:0;box-shadow:none;border-radius:0;
    aspect-ratio:auto;min-height:95vh}
  @page{size:A4 landscape;margin:12mm}
}

/* The sign-out panel at the foot of the profile. It is the only way out of
   the app now that the name opens the profile, so it is a labelled section
   rather than a loose button — deliberate to find, hard to hit by accident. */
.signout-panel{display:flex;align-items:center;gap:16px;flex-wrap:wrap}
.signout-panel .btn{flex:none}
