/* =====================================================================
   GlobalSecora — dark security-console theme
   ===================================================================== */

:root{
  --bg:#080b12;
  --bg2:#0d1220;
  --panel:#111828;
  --panel2:#161f33;
  --line:#222d47;
  --line2:#2d3b5c;
  --txt:#e8eefc;
  --txt2:#9fb0cf;
  --txt3:#6d7f9e;
  --acc:#4da3ff;
  --acc2:#7c5cff;
  --ok:#2fd98a;
  --warn:#ffb648;
  --bad:#ff5c7a;
  --easy:#2fd98a;
  --medium:#ffb648;
  --hard:#ff7a45;
  --insane:#ff4d6d;
  --radius:14px;
  --mono:"JetBrains Mono",ui-monospace,SFMono-Regular,"SF Mono",Menlo,Consolas,monospace;
  --sans:"Inter",-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;
}

/* ---------------------------------------------------------------------
   Token aliases.

   The commerce, accounts and academy sheets were authored against a
   second naming vocabulary (--card, --text, --muted, --accent, --c).
   Those five names were never declared, so every rule that used them was
   dropped by the parser and those panels painted no background and no
   secondary text at all.  Aliasing them here fixes all of it in one place
   and keeps the later sheets readable as written.

   Because a custom property resolves at the point of use, these aliases
   follow the light theme automatically: the light block below redeclares
   --panel/--txt/--txt2/--acc on the same element and the aliases re-point
   themselves.

   --c is the per-card brand colour.  Markup sets it inline (see
   pick_color() calls in index.php, course.php, machine.php, ...); the
   default here means a card that forgets to set one still gets the accent
   instead of an invalid declaration.
   --------------------------------------------------------------------- */
:root{
  --text:var(--txt);
  --text2:var(--txt2);
  --muted:var(--txt2);
  --card:var(--panel);
  --card2:var(--panel2);
  --accent:var(--acc);
  --c:var(--acc);
  /* Foreground for text sitting on a solid --acc fill.  The dark theme's
     accent is a pale blue and wants ink on top; the light theme's accent is a
     deep blue and wants white.  Anything that fills with the accent must use
     this rather than guessing, or it fails contrast in one of the two. */
  --on-acc:#07101d;
}

*{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{
  margin:0;background:
    radial-gradient(1100px 620px at 82% -12%,rgba(124,92,255,.16),transparent 62%),
    radial-gradient(900px 520px at 6% 4%,rgba(77,163,255,.12),transparent 58%),
    var(--bg);
  color:var(--txt);font:15px/1.65 var(--sans);
  min-height:100vh;display:flex;flex-direction:column;
}
a{color:var(--acc);text-decoration:none}
a:hover{text-decoration:underline}
code,kbd,pre,.mono{font-family:var(--mono)}
h1,h2,h3,h4{margin:0 0 .4em;line-height:1.22;letter-spacing:-.02em}
h1{font-size:2.1rem}
h2{font-size:1.4rem}
h3{font-size:1.08rem}
p{margin:0 0 1em}
img{max-width:100%}

.wrap{width:min(1240px,100% - 2.5rem);margin-inline:auto}
.main{flex:1;padding:2rem 0 4rem}
.muted{color:var(--txt2)}
.dim{color:var(--txt3)}
.grow{flex:1}
.center{text-align:center}
.right{text-align:right}
.nowrap{white-space:nowrap}

/* ---------------- top bar ---------------- */
.topbar{
  position:sticky;top:0;z-index:50;
  background:rgba(8,11,18,.82);
  backdrop-filter:blur(14px);
  border-bottom:1px solid var(--line);
}
.topbar-in{display:flex;align-items:center;gap:1.5rem;height:60px}
.brand{display:flex;align-items:center;gap:.6rem;color:var(--txt);font-weight:700;letter-spacing:-.02em}
.brand:hover{text-decoration:none}
.brand-mark{
  width:26px;height:26px;display:grid;place-items:center;border-radius:8px;
  background:linear-gradient(135deg,var(--acc),var(--acc2));color:#fff;font-size:11px;
  box-shadow:0 0 22px rgba(77,163,255,.42);
}
.nav{display:flex;gap:.35rem;margin-right:auto}
.nav a{
  color:var(--txt2);padding:.42rem .8rem;border-radius:9px;font-size:.9rem;font-weight:500;
  transition:background .15s,color .15s;
}
.nav a:hover{background:var(--panel);color:var(--txt);text-decoration:none}
.nav a.active{background:var(--panel2);color:var(--txt)}
.topbar-right{display:flex;align-items:center;gap:.6rem}
.who{display:flex;align-items:center;gap:.5rem;color:var(--txt);font-size:.9rem;padding:.25rem .5rem;border-radius:10px}
.who:hover{background:var(--panel);text-decoration:none}
.who-name{font-weight:600}
.pts{color:var(--warn);font-family:var(--mono);font-size:.8rem}
.avatar{
  width:26px;height:26px;border-radius:8px;display:grid;place-items:center;
  background:linear-gradient(135deg,var(--acc2),var(--acc));
  color:#fff;font-weight:700;font-size:.78rem;
}
/* A real picture keeps the same box so it drops in anywhere an initial was. */
.avatar-img{
  object-fit:cover;background:var(--panel2);padding:0;
  border:1px solid var(--line2);
}
.avatar-round{border-radius:50%}

.pill{
  display:inline-flex;align-items:center;gap:.35rem;
  padding:.24rem .6rem;border-radius:999px;font-size:.76rem;font-weight:600;
  border:1px solid var(--line2);background:var(--panel);color:var(--txt2);
}
.pill-quiet{color:var(--ok);border-color:rgba(47,217,138,.28);background:rgba(47,217,138,.08)}
.pill-bad{color:var(--bad);border-color:rgba(255,92,122,.3);background:rgba(255,92,122,.08)}
.pill-warn{color:var(--warn);border-color:rgba(255,182,72,.3);background:rgba(255,182,72,.08)}

/* ---------------- buttons ---------------- */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:.45rem;
  padding:.6rem 1.05rem;border-radius:10px;border:1px solid transparent;
  font:600 .9rem/1 var(--sans);cursor:pointer;text-decoration:none;
  transition:transform .12s,box-shadow .18s,background .18s,border-color .18s;
  white-space:nowrap;
}
.btn:hover{text-decoration:none;transform:translateY(-1px)}
.btn:active{transform:translateY(0)}
.btn:disabled,.btn[aria-disabled=true]{opacity:.5;cursor:not-allowed;transform:none}
.btn-primary{background:linear-gradient(135deg,var(--acc),#3b7fd4);color:#fff;box-shadow:0 6px 20px -6px rgba(77,163,255,.6)}
.btn-accent{background:linear-gradient(135deg,var(--acc2),var(--acc));color:#fff;box-shadow:0 6px 20px -6px rgba(124,92,255,.6)}
.btn-ok{background:linear-gradient(135deg,var(--ok),#1aa869);color:#04140c;box-shadow:0 6px 20px -6px rgba(47,217,138,.5)}
.btn-ghost{background:var(--panel);color:var(--txt);border-color:var(--line2)}
.btn-ghost:hover{background:var(--panel2);border-color:var(--acc)}
.btn-danger{background:rgba(255,92,122,.12);color:var(--bad);border-color:rgba(255,92,122,.35)}
.btn-danger:hover{background:rgba(255,92,122,.2)}
.btn-sm{padding:.4rem .7rem;font-size:.8rem;border-radius:8px}
.btn-lg{padding:.85rem 1.6rem;font-size:1rem;border-radius:12px}
.btn-block{width:100%}
.btn-copy{
  background:var(--panel2);color:var(--txt2);border:1px solid var(--line2);
  padding:.3rem .55rem;font-size:.72rem;border-radius:7px;
  cursor:pointer;font-family:var(--mono);
}
.btn-copy:hover{color:var(--acc);border-color:var(--acc)}
.btn-copy.done{color:var(--ok);border-color:var(--ok)}

/* ---------------- panels / cards ---------------- */
.card{
  background:linear-gradient(180deg,var(--panel),var(--bg2));
  border:1px solid var(--line);border-radius:var(--radius);
  padding:1.35rem;
}
.card h2,.card h3{margin-top:0}
.card-flush{padding:0;overflow:hidden}
.card-accent{border-color:rgba(77,163,255,.35);box-shadow:0 0 40px -18px rgba(77,163,255,.5)}

.alert{
  padding:.8rem 1.05rem;border-radius:11px;margin-bottom:1rem;
  border:1px solid var(--line2);background:var(--panel);font-size:.92rem;
}
.alert-ok{color:var(--ok);border-color:rgba(47,217,138,.35);background:rgba(47,217,138,.09)}
.alert-bad{color:var(--bad);border-color:rgba(255,92,122,.35);background:rgba(255,92,122,.09)}
.alert-warn{color:var(--warn);border-color:rgba(255,182,72,.35);background:rgba(255,182,72,.09)}
.alert-info{color:var(--acc);border-color:rgba(77,163,255,.35);background:rgba(77,163,255,.09)}

.demo-strip{
  margin-top:1rem;padding:.6rem .95rem;border-radius:10px;font-size:.85rem;
  background:rgba(124,92,255,.1);border:1px solid rgba(124,92,255,.3);color:var(--txt2);
}
.demo-strip code{color:var(--warn);background:rgba(0,0,0,.3);padding:.1rem .35rem;border-radius:5px}

pre{
  background:#070a11;border:1px solid var(--line);border-radius:10px;
  padding:.9rem 1rem;overflow-x:auto;font-size:.84rem;line-height:1.6;
  color:#cfe0f7;margin:0 0 1em;
}
pre code{color:inherit}
code:not(pre code){
  background:var(--panel2);border:1px solid var(--line);border-radius:5px;
  padding:.08rem .34rem;font-size:.86em;color:#9fd0ff;
}
kbd{
  background:var(--panel2);border:1px solid var(--line2);border-bottom-width:2px;
  border-radius:5px;padding:.05rem .35rem;font-size:.8em;color:var(--txt);
}

table{width:100%;border-collapse:collapse;font-size:.9rem}
th,td{padding:.6rem .7rem;text-align:left;border-bottom:1px solid var(--line)}
th{color:var(--txt3);font-size:.76rem;text-transform:uppercase;letter-spacing:.07em;font-weight:600}
/* A row header in a key/value table is a sentence, not a column caption, so
   it keeps the weight and case of the label it replaced and gives up only the
   alignment.  The uppercase + letterspaced treatment above is for the header
   row; applying it here turned "Response" into "RESPONSE" beside a value that
   was already sentence case. */
th.dim{
  text-transform:none;letter-spacing:0;font-weight:inherit;font-size:inherit;
  text-align:left;color:var(--txt3);vertical-align:top;
}
tbody tr:hover{background:rgba(77,163,255,.045)}
.table-wrap{overflow-x:auto}

/* ---------------- tags ---------------- */
.tag{
  display:inline-flex;align-items:center;gap:.3rem;padding:.16rem .5rem;
  border-radius:6px;font-size:.7rem;font-weight:700;letter-spacing:.03em;
  text-transform:uppercase;border:1px solid var(--line2);background:var(--panel2);color:var(--txt2);
}
.tag-easy{color:var(--easy);border-color:rgba(47,217,138,.32);background:rgba(47,217,138,.1)}
.tag-medium{color:var(--medium);border-color:rgba(255,182,72,.32);background:rgba(255,182,72,.1)}
.tag-hard{color:var(--hard);border-color:rgba(255,122,69,.32);background:rgba(255,122,69,.1)}
.tag-insane{color:var(--insane);border-color:rgba(255,77,109,.32);background:rgba(255,77,109,.1)}
.tag-os{color:var(--acc);border-color:rgba(77,163,255,.3);background:rgba(77,163,255,.09)}
.tag-done{color:var(--ok);border-color:rgba(47,217,138,.4);background:rgba(47,217,138,.14)}
.tag-queued{color:var(--warn);border-color:rgba(255,182,72,.35);background:rgba(255,182,72,.1)}

/* ---------------- hero ---------------- */
.hero{padding:3.2rem 0 2rem;position:relative}
.hero-grid{display:grid;grid-template-columns:1.15fr .85fr;gap:3rem;align-items:center}
.hero h1{font-size:2.9rem;font-weight:800}
.hero h1 .grad{
  background:linear-gradient(120deg,var(--acc),var(--acc2) 60%,#ff5c7a);
  -webkit-background-clip:text;background-clip:text;color:transparent;
}
.hero-lead{color:var(--txt2);font-size:1.06rem;max-width:34rem}
.hero-cta{display:flex;gap:.7rem;flex-wrap:wrap;margin-top:1.6rem}
.eyebrow{
  display:inline-flex;align-items:center;gap:.45rem;margin-bottom:1rem;
  font-size:.74rem;font-weight:700;letter-spacing:.13em;text-transform:uppercase;color:var(--txt3);
}

.stat-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(120px,1fr));gap:.8rem;margin-top:2.6rem}
.stat{background:var(--panel);border:1px solid var(--line);border-radius:12px;padding:1rem 1.1rem}
.stat b{display:block;font-size:1.7rem;font-weight:800;letter-spacing:-.03em;font-family:var(--mono)}
.stat span{font-size:.76rem;color:var(--txt3);text-transform:uppercase;letter-spacing:.06em}

.terminal{
  background:#060910;border:1px solid var(--line2);border-radius:14px;
  overflow:hidden;box-shadow:0 30px 70px -30px rgba(0,0,0,.9);
}
.terminal-bar{
  display:flex;gap:.4rem;padding:.6rem .9rem;background:var(--panel2);border-bottom:1px solid var(--line);
}
.terminal-bar i{width:11px;height:11px;border-radius:50%;background:#3b4661}
.terminal-bar i:nth-child(1){background:#ff5f57}
.terminal-bar i:nth-child(2){background:#febc2e}
.terminal-bar i:nth-child(3){background:#28c840}
.terminal-body{padding:1rem 1.1rem;font-family:var(--mono);font-size:.82rem;line-height:1.75;overflow-x:auto}
.terminal-body .l{color:#7f8ea8}
.terminal-body .c{color:#2fd98a}
.terminal-body .y{color:#ffb648}
.terminal-body .b{color:#4da3ff}

/* ---------------- machine cards ---------------- */
.section-head{display:flex;align-items:flex-end;justify-content:space-between;gap:1rem;margin:2.6rem 0 1.1rem;flex-wrap:wrap}
.section-head h2{margin:0}
.grid-machines{display:grid;grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:1rem}
.mcard{
  display:flex;flex-direction:column;gap:.55rem;
  background:linear-gradient(180deg,var(--panel),var(--bg2));
  border:1px solid var(--line);border-radius:var(--radius);padding:1.2rem 1.25rem;
  color:var(--txt);transition:border-color .18s,transform .18s,box-shadow .18s;
  position:relative;overflow:hidden;
}
.mcard::after{
  content:"";position:absolute;inset:0;border-radius:var(--radius);pointer-events:none;
  background:linear-gradient(135deg,rgba(77,163,255,.1),transparent 45%);
  opacity:0;transition:opacity .2s;
}
.mcard:hover{
  text-decoration:none;border-color:rgba(77,163,255,.5);transform:translateY(-3px);
  box-shadow:0 20px 44px -22px rgba(77,163,255,.6);
}
.mcard:hover::after{opacity:1}
.mcard-top{display:flex;gap:.4rem;flex-wrap:wrap}
.mcard-name{margin:.15rem 0 0;font-size:1.1rem}
.mcard-sum{color:var(--txt2);font-size:.88rem;margin:0;flex:1}
.mcard-foot{display:flex;align-items:center;gap:.45rem;font-size:.8rem;margin-top:.5rem}
.bar{display:inline-block;width:70px;height:6px;border-radius:99px;background:var(--line);overflow:hidden}
.bar i{display:block;height:100%;background:linear-gradient(90deg,var(--acc),var(--ok));border-radius:99px}

/* ---------------- filters ---------------- */
.filters{
  display:flex;gap:.6rem;flex-wrap:wrap;align-items:center;
  background:var(--panel);border:1px solid var(--line);border-radius:12px;padding:.75rem;
  margin-bottom:1.4rem;
}
.filters input[type=search],.filters input[type=text],.filters select{
  background:var(--bg2);border:1px solid var(--line2);color:var(--txt);
  padding:.5rem .7rem;border-radius:9px;font:400 .88rem var(--sans);
}
.filters input:focus,.filters select:focus{outline:none;border-color:var(--acc);box-shadow:0 0 0 3px rgba(77,163,255,.15)}
.chip{
  padding:.42rem .85rem;border-radius:999px;border:1px solid var(--line2);background:var(--bg2);
  color:var(--txt2);font-size:.83rem;font-weight:500;cursor:pointer;
}
.chip:hover{text-decoration:none;border-color:var(--acc);color:var(--txt)}
.chip.on{background:rgba(77,163,255,.16);border-color:var(--acc);color:var(--acc)}

/* ---------------- machine detail ---------------- */
.mach-head{display:flex;justify-content:space-between;gap:1.6rem;flex-wrap:wrap;align-items:flex-start;margin-bottom:1.4rem}
.mach-head h1{margin:.3rem 0 .35rem}
.mach-meta{display:flex;gap:.45rem;flex-wrap:wrap;align-items:center}
.layout-2col{display:grid;grid-template-columns:1fr 360px;gap:1.4rem;align-items:start}
.layout-2col-r{grid-template-columns:340px 1fr}

/* task list */
.task{
  border:1px solid var(--line);border-radius:12px;background:var(--bg2);
  margin-bottom:.7rem;overflow:hidden;
}
.task.solved{border-color:rgba(47,217,138,.34);background:rgba(47,217,138,.045)}
.task-head{
  display:flex;align-items:center;gap:.8rem;padding:.85rem 1.05rem;cursor:pointer;user-select:none;
}
.task-head:hover{background:rgba(77,163,255,.05)}
.task-no{
  width:26px;height:26px;flex:0 0 26px;border-radius:8px;display:grid;place-items:center;
  background:var(--panel2);border:1px solid var(--line2);font:700 .78rem var(--mono);color:var(--txt2);
}
.task.solved .task-no{background:rgba(47,217,138,.16);border-color:var(--ok);color:var(--ok)}
.task-title{flex:1;font-weight:600;font-size:.96rem}
.task-pts{font-family:var(--mono);font-size:.78rem;color:var(--warn)}
.task-body{padding:0 1.05rem 1.05rem;display:none;border-top:1px solid var(--line)}
.task.open .task-body{display:block}
.task-desc{color:var(--txt2);font-size:.9rem;margin:.9rem 0}
.chev{color:var(--txt3);transition:transform .2s}
.task.open .chev{transform:rotate(90deg)}

/* flag form */
.flag-form{display:flex;gap:.55rem;flex-wrap:wrap;align-items:center;margin-top:.9rem}
.flag-input{
  flex:1;min-width:220px;background:#070a11;border:1px solid var(--line2);color:var(--txt);
  padding:.62rem .8rem;border-radius:10px;font-family:var(--mono);font-size:.86rem;
}
.flag-input:focus{outline:none;border-color:var(--acc);box-shadow:0 0 0 3px rgba(77,163,255,.16)}
.flag-input::placeholder{color:var(--txt3)}
.flag-msg{margin-top:.6rem;font-size:.87rem;font-family:var(--mono);min-height:1.2em}
.flag-msg.ok{color:var(--ok)}
.flag-msg.no{color:var(--bad)}

.hint-box{
  margin-top:.9rem;padding:.8rem .95rem;border-radius:10px;font-size:.88rem;
  background:rgba(255,182,72,.08);border:1px solid rgba(255,182,72,.28);color:#ffd79a;
}
.walk{
  margin-top:1rem;padding:1rem 1.1rem;border-radius:11px;font-size:.9rem;
  background:rgba(47,217,138,.06);border:1px solid rgba(47,217,138,.28);color:#c6f2dd;
}
.walk h4{margin:0 0 .4rem;color:var(--ok);font-size:.9rem;text-transform:uppercase;letter-spacing:.06em}

/* progress ring */
.ring{display:flex;align-items:center;gap:1rem}
.ring svg{transform:rotate(-90deg)}
.ring circle{fill:none;stroke-width:8;stroke-linecap:round}
.ring .bgc{stroke:var(--line)}
.ring .fgc{stroke:url(#ringgrad)}
.ring-num{font:800 1.3rem var(--mono);letter-spacing:-.02em}

/* ---------------- spawn / connection panel ---------------- */
.spawn-panel{border:1px solid var(--line2);border-radius:var(--radius);overflow:hidden;position:sticky;top:76px}
.spawn-head{
  padding:1rem 1.15rem;background:var(--panel2);border-bottom:1px solid var(--line);
  font-weight:700;display:flex;justify-content:space-between;align-items:center;gap:.6rem;
}
.spawn-body{padding:1.15rem}
.conn-row{display:flex;align-items:center;justify-content:space-between;gap:.7rem;padding:.6rem 0;border-bottom:1px dashed var(--line)}
.conn-row:last-of-type{border-bottom:0}
.conn-k{font-size:.78rem;color:var(--txt3);text-transform:uppercase;letter-spacing:.06em;font-weight:600}
.conn-v{font-family:var(--mono);font-size:.88rem;display:flex;align-items:center;gap:.5rem;flex-wrap:wrap;justify-content:flex-end}
.conn-v.pass{color:var(--warn)}

.ttl-bar{height:7px;border-radius:99px;background:var(--line);overflow:hidden;margin:.8rem 0 .4rem}
.ttl-bar i{
  display:block;height:100%;border-radius:99px;transition:width .9s linear;
  background:linear-gradient(90deg,var(--ok),var(--warn),var(--bad));
}
.ttl-text{font-family:var(--mono);font-size:.8rem;color:var(--txt2);text-align:center}

.statusline{display:flex;align-items:center;gap:.5rem;font-size:.84rem;padding:.5rem .7rem;border-radius:9px;margin-bottom:.9rem}
.statusline-ok{background:rgba(47,217,138,.1);border:1px solid rgba(47,217,138,.3);color:var(--ok)}
.statusline-wait{background:rgba(255,182,72,.1);border:1px solid rgba(255,182,72,.3);color:var(--warn)}
.statusline-bad{background:rgba(255,92,122,.1);border:1px solid rgba(255,92,122,.3);color:var(--bad)}
.spin{
  width:13px;height:13px;border:2px solid currentColor;border-right-color:transparent;
  border-radius:50%;display:inline-block;animation:spin .8s linear infinite;flex:0 0 13px;
}
@keyframes spin{to{transform:rotate(360deg)}}

/* A draft to copy rather than a form to submit (admin/reply.php). */
.draft{
  display:grid;grid-template-columns:5.5rem 1fr;gap:.45rem .9rem;
  margin:0 0 1.1rem;align-items:baseline;
}
.draft dt{font-size:.78rem;text-transform:uppercase;letter-spacing:.07em;color:var(--txt3)}
.draft dd{margin:0;word-break:break-word}
.draft .draft-body{
  grid-column:1/-1;background:var(--panel2);border:1px solid var(--line);
  border-radius:10px;padding:.8rem .9rem;font-size:.84rem;line-height:1.6;
  white-space:normal;
}
@media (max-width:34rem){ .draft{grid-template-columns:1fr} }

/* ---------------- forms / auth ---------------- */
.auth-wrap{max-width:430px;margin:2.5rem auto}
.field{margin-bottom:1rem}
.field label{display:block;font-size:.82rem;font-weight:600;color:var(--txt2);margin-bottom:.35rem}
/* A caption over a group of checkboxes is a fieldset with a legend, not a
   label: there is no one control it could name. */
fieldset.field{border:0;padding:0;margin:0 0 1rem;min-width:0}
fieldset.field legend{
  padding:0;font-size:.82rem;font-weight:600;color:var(--txt2);margin-bottom:.35rem;
}
fieldset.field .check{margin-bottom:.3rem}
.field input,.field textarea,.field select{
  width:100%;background:#070a11;border:1px solid var(--line2);color:var(--txt);
  padding:.68rem .85rem;border-radius:10px;font:400 .93rem var(--sans);
}
.field textarea{min-height:130px;resize:vertical;font-family:var(--mono);font-size:.85rem;line-height:1.6}
.field input:focus,.field textarea:focus,.field select:focus{outline:none;border-color:var(--acc);box-shadow:0 0 0 3px rgba(77,163,255,.16)}
.field .help{font-size:.78rem;color:var(--txt3);margin-top:.3rem}
.field-err{font-size:.8rem;color:var(--bad);margin-top:.3rem}

/* Available to every reader, invisible on screen.

   Filter bars and admin grids carry one control per column and a visible
   label on each would either double the row height or push the grid out of
   alignment.  Those controls get a .sr-only label instead: still announced,
   still the label a click targets, still the tooltip, but it takes up no
   space.  Anything that can carry a visible label should. */
.sr-only{
  position:absolute!important;width:1px;height:1px;padding:0;margin:-1px;
  overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;border:0;
}
/* A field that shows its own label must not have the label doubled up when the
   same text is also on the input as a placeholder. */
.field label.sr-only + input,
.field label.sr-only + select,
.field label.sr-only + textarea{margin-top:0}
.form-row{display:grid;grid-template-columns:1fr 1fr;gap:.9rem}
/* A grid of labelled fields that collapses to one column on a phone.

   A long admin form set out as a single stack of full-width inputs reads as
   endless: each field gets the whole screen for one value, and the operator has
   to scroll past nine of them to reach the button.  Two columns up, one down. */
.form-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));gap:.2rem .9rem}
.form-grid .field{margin-bottom:.8rem}
.form-grid .field label .dim{display:block;font-weight:400;margin-top:.1rem}
@media (max-width:560px){ .form-grid{grid-template-columns:1fr} }
.check{display:flex;gap:.5rem;align-items:flex-start;font-size:.87rem;color:var(--txt2)}
.check input{margin-top:.25rem}

/* ---------------- tables / lists ---------------- */
.list{display:flex;flex-direction:column;gap:.55rem}
.list-item{
  display:flex;align-items:center;justify-content:space-between;gap:1rem;
  padding:.8rem 1rem;border:1px solid var(--line);border-radius:11px;background:var(--bg2);
}
.list-item:hover{border-color:var(--line2)}
.rank{
  width:34px;height:34px;flex:0 0 34px;border-radius:10px;display:grid;place-items:center;
  font:800 .9rem var(--mono);background:var(--panel2);border:1px solid var(--line2);color:var(--txt2);
}
.rank-1{background:linear-gradient(135deg,#ffd76e,#ff9f43);color:#2a1a00;border-color:#ffd76e}
.rank-2{background:linear-gradient(135deg,#dfe6ef,#a8b4c4);color:#1a1f28;border-color:#dfe6ef}
.rank-3{background:linear-gradient(135deg,#e0a878,#b9764a);color:#241205;border-color:#e0a878}

/* ---------------- admin ---------------- */
.admin-shell{display:grid;grid-template-columns:210px 1fr;gap:1.5rem;align-items:start}
.admin-nav{display:flex;flex-direction:column;gap:.2rem;position:sticky;top:76px}
.admin-nav a{
  padding:.6rem .85rem;border-radius:9px;color:var(--txt2);font-size:.9rem;font-weight:500;
  border:1px solid transparent;
}
.admin-nav a:hover{background:var(--panel);color:var(--txt);text-decoration:none}
.admin-nav a.active{background:var(--panel2);color:var(--acc);border-color:rgba(77,163,255,.3)}
.admin-nav .lbl{font-size:.7rem;text-transform:uppercase;letter-spacing:.1em;color:var(--txt3);padding:.9rem .85rem .3rem;font-weight:700}
.admin-nav-sep{border:0;border-top:1px solid var(--line);margin:.55rem .85rem}
.adm-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:.9rem;margin-bottom:1.5rem}
.kpi{background:var(--panel);border:1px solid var(--line);border-radius:12px;padding:1.1rem 1.2rem}
.kpi b{display:block;font:800 1.8rem var(--mono);letter-spacing:-.03em;margin-bottom:.15rem}
.kpi span{font-size:.76rem;color:var(--txt3);text-transform:uppercase;letter-spacing:.06em}
.kpi.good b{color:var(--ok)}
.kpi.warn b{color:var(--warn)}
.kpi.bad b{color:var(--bad)}

.tabs{display:flex;gap:.3rem;border-bottom:1px solid var(--line);margin-bottom:1.2rem;flex-wrap:wrap}
.tabs a{padding:.55rem .9rem;color:var(--txt2);font-size:.88rem;font-weight:500;border-bottom:2px solid transparent;margin-bottom:-1px}
.tabs a:hover{color:var(--txt);text-decoration:none}
/* .active is the existing convention on this codebase; .is-on is what the
   certificate editor's tabs carry, because they are links with a role rather
   than the plain anchors the rest of the panel uses.  One rule for both
   beats two rules that can drift apart. */
.tabs a.active,
.tabs a.is-on{color:var(--acc);border-bottom-color:var(--acc)}

.code-box{
  font-family:var(--mono);font-size:.8rem;background:#070a11;border:1px solid var(--line2);
  border-radius:9px;padding:.85rem;word-break:break-all;color:#9fd0ff;line-height:1.7;
}

/* ---------------- leaderboard ---------------- */
.podium{display:grid;grid-template-columns:repeat(3,1fr);gap:1rem;margin-bottom:2rem}
.pod{
  text-align:center;padding:1.5rem 1rem;border-radius:var(--radius);
  background:linear-gradient(180deg,var(--panel),var(--bg2));border:1px solid var(--line);
}
.pod .rank{margin:0 auto .7rem;width:48px;height:48px;font-size:1.15rem;border-radius:14px}
.pod b{display:block;font-size:1.05rem;margin-bottom:.15rem}
.pod .pts{color:var(--warn);font:700 1.1rem var(--mono)}

/* ---------------- footer ---------------- */
.foot{border-top:1px solid var(--line);background:rgba(8,11,18,.7);padding:1.6rem 0;margin-top:auto}
.foot-in{display:flex;justify-content:space-between;gap:1.2rem;flex-wrap:wrap;font-size:.84rem}
.foot-stats{font-family:var(--mono);font-size:.78rem}

/* ---------------- responsive ---------------- */
@media (max-width:1000px){
  .hero-grid{grid-template-columns:1fr;gap:2rem}
  .layout-2col,.layout-2col-r{grid-template-columns:1fr}
  .spawn-panel{position:static}
  .admin-shell{grid-template-columns:1fr}
  .admin-nav{position:static;flex-direction:row;flex-wrap:wrap;gap:.3rem}
  .admin-nav .lbl{width:100%;padding:.3rem}
}
@media (max-width:720px){
  .wrap{width:min(1240px,100% - 1.6rem)}
  .nav a:not(.active){display:none}
  .hero h1{font-size:2.1rem}
  .form-row{grid-template-columns:1fr}
  .podium{grid-template-columns:1fr}
  .who-name,.pts{display:none}
  .main{padding:1.2rem 0 3rem}
}

/* =====================================================================
   Extensions
   ===================================================================== */

/* ---- accessibility / utilities ---- */
.skip{position:absolute;left:-9999px;top:0;z-index:200;background:var(--acc);color:#fff;padding:.6rem 1rem;border-radius:0 0 9px 0}
.skip:focus{left:0}
.icon-btn{
  width:32px;height:32px;display:grid;place-items:center;border-radius:9px;cursor:pointer;
  background:var(--panel);border:1px solid var(--line2);color:var(--txt2);font-size:.95rem;
}
.icon-btn:hover{color:var(--acc);border-color:var(--acc)}
.theme-ico{display:none}
[data-theme="dark"] .theme-ico.theme-dark{display:inline}
[data-theme="light"] .theme-ico.theme-light{display:inline}

.live-dot{
  width:7px;height:7px;border-radius:50%;background:var(--ok);display:inline-block;
  box-shadow:0 0 0 0 rgba(47,217,138,.6);animation:pulse 2s infinite;
}
@keyframes pulse{
  0%{box-shadow:0 0 0 0 rgba(47,217,138,.55)}
  70%{box-shadow:0 0 0 7px rgba(47,217,138,0)}
  100%{box-shadow:0 0 0 0 rgba(47,217,138,0)}
}
.dot{color:var(--txt3)}

/* Utilities that were being used from the markup but never written down.
   Three of them, each with a page that had reached for it by name and got
   nothing back: a monospaced run for serials and amounts, an element removed
   from the layout rather than merely faded, and a block-level muted aside. */
.mono{font-family:var(--mono);font-variant-numeric:tabular-nums}
/* .hidden has to win over .row-actions and the form defaults, hence the
   specificity, and it is display:none rather than visibility:hidden because a
   visibility:hidden control is still focusable and still submitted. */
.hidden{display:none !important}
.block{display:block}
.muted.block{margin-top:.4rem}

/* A log of who did what.  Deliberately not a table: it is a list of events,
   and the useful reading of one is "who, when, and what did they say". */
.audit-list{list-style:none;margin:0;padding:0}
.audit-list li{
  padding:.5rem 0;border-top:1px solid var(--line);font-size:.86rem;line-height:1.5;
}
.audit-list li:first-child{border-top:0;padding-top:0}
.audit-list .dim{margin-top:.1rem}

/* ---- difficulty pips ---- */
.pips{display:inline-flex;gap:2px;vertical-align:-1px}
.pips i{width:5px;height:13px;border-radius:2px;background:var(--line);display:block}
.pips i.on.beginner{background:var(--easy)}
.pips i.on.intermediate{background:var(--medium)}
.pips i.on.advanced{background:var(--hard)}
.pips i.on.expert{background:var(--insane)}

/* ---- stars ---- */
.stars{color:var(--warn);letter-spacing:1px;font-size:.95rem}

/* ---- tags ---- */
.cat-chip{color:var(--c);border-color:color-mix(in srgb,var(--c) 42%,transparent);background:color-mix(in srgb,var(--c) 12%,transparent)}
.tag-premium{color:var(--warn);border-color:rgba(255,182,72,.4);background:rgba(255,182,72,.12)}
.tag-featured{color:var(--acc2);border-color:rgba(124,92,255,.4);background:rgba(124,92,255,.14)}
.tag-locked{color:var(--txt3)}
.tag-os img{border-radius:2px}

/* ---- grids ---- */
.grid-2{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:1rem}
.grid-3{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:1rem}
.grid-4{display:grid;grid-template-columns:repeat(auto-fit,minmax(215px,1fr));gap:1rem}

/* buttons / forms laid out in a row, wrapping on narrow screens */
.row-actions{display:flex;gap:.5rem;align-items:center;flex-wrap:wrap}
.row-actions form{margin:0}

.hero-tight{padding:2.6rem 0 1.2rem}

/* ---- step cards ---- */
.step{position:relative;padding-top:2.6rem}
.step-n{
  position:absolute;top:1rem;left:1.2rem;width:30px;height:30px;border-radius:9px;
  display:grid;place-items:center;font:800 .9rem var(--mono);
  background:linear-gradient(135deg,var(--acc),var(--acc2));color:#fff;
}
.feat-ico{font-size:1.7rem;display:block;margin-bottom:.5rem}

/* ---- track chips ---- */
.trackbar{display:flex;gap:.5rem;flex-wrap:wrap;margin-bottom:1.4rem}

/* ---- track cards ---- */
.grid-tracks{display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));gap:1rem}
.track-card{
  background:linear-gradient(180deg,var(--panel),var(--bg2));
  border:1px solid var(--line);border-radius:var(--radius);padding:1.3rem 1.4rem;
  display:flex;flex-direction:column;gap:.7rem;
}
.track-card:hover{border-color:rgba(77,163,255,.4)}
.track-head{display:flex;align-items:flex-start;justify-content:space-between;gap:.7rem}
.track-head h3{margin:0}
.track-head a{color:var(--txt)}
.track-blurb{margin:0;font-size:.9rem}
.track-meta{display:flex;gap:.35rem;flex-wrap:wrap;align-items:center;margin-top:auto}

/* ---- category grid ---- */
.grid-cats{display:grid;grid-template-columns:repeat(auto-fill,minmax(190px,1fr));gap:.8rem}
.cat-card{
  display:flex;flex-direction:column;gap:.35rem;color:var(--txt);
  background:linear-gradient(180deg,var(--panel),var(--bg2));
  border:1px solid var(--line);border-left:3px solid var(--c);
  border-radius:12px;padding:1rem 1.1rem;transition:transform .15s,border-color .15s;
}
.cat-card:hover{text-decoration:none;transform:translateY(-2px);border-color:var(--c);border-left-color:var(--c)}
.cat-ico{font-size:1.35rem;color:var(--c);line-height:1}
.cat-name{font-weight:600;font-size:.96rem}
.cat-desc{font-size:.8rem;line-height:1.5}
.cat-count{font-size:.76rem;color:var(--c);font-weight:600;margin-top:.2rem}

/* ---- machine card extras ---- */
.mcard.is-featured{border-color:rgba(124,92,255,.45)}
.mcard.is-soon{opacity:.92;border-style:dashed}
.mcard-thumb{margin:-1.2rem -1.25rem .6rem;border-radius:var(--radius) var(--radius) 0 0;overflow:hidden;max-height:120px}
.mcard-thumb img{width:100%;height:120px;object-fit:cover;display:block}
.mcard-tags{margin-top:.2rem}

.notify{display:flex;gap:.4rem;margin-top:auto}
.notify input[type=email]{
  flex:1;min-width:0;background:#070a11;border:1px solid var(--line2);color:var(--txt);
  padding:.45rem .6rem;border-radius:9px;font:400 .84rem var(--sans);
}
.notify input[type=email]:focus{outline:none;border-color:var(--acc)}

.lab-banner{width:100%;border-radius:var(--radius);margin-bottom:1rem;border:1px solid var(--line);display:block}

/* ---- lab detail extras ---- */
.mach-head-main{flex:1;min-width:260px}
.ring-card{min-width:190px;padding:1rem 1.2rem}

/* ---- rating & reviews ---- */
.rating-sum{display:flex;align-items:center;gap:1rem;margin-bottom:1.2rem;padding-bottom:1.2rem;border-bottom:1px solid var(--line)}
.rating-sum>b{font:800 2.4rem var(--mono);letter-spacing:-.04em;line-height:1}
.review{padding:.9rem 0;border-bottom:1px solid var(--line)}
.review:last-of-type{border-bottom:0}
.review-head{display:flex;align-items:center;gap:.6rem;font-size:.9rem}
.review-body{margin:.5rem 0 0;color:var(--txt2);font-size:.9rem;white-space:pre-line}
.review-form{margin-top:1.4rem;padding-top:1.4rem;border-top:1px solid var(--line)}

.starpick{display:inline-flex;flex-direction:row-reverse;gap:.15rem}
.starpick input{position:absolute;opacity:0;width:0;height:0}
.starpick label{font-size:1.7rem;color:var(--line2);cursor:pointer;transition:color .12s;line-height:1}
.starpick label:hover,.starpick label:hover ~ label,
.starpick input:checked ~ label{color:var(--warn)}

/* ---- solver list ---- */
.solver{display:flex;align-items:center;gap:.55rem;padding:.35rem 0;font-size:.88rem}

/* ---- prose / markdown ---- */
.prose{line-height:1.75}
.prose h1{font-size:1.6rem;margin:1.6em 0 .5em}
.prose h2{font-size:1.28rem;margin:1.5em 0 .45em;padding-bottom:.3em;border-bottom:1px solid var(--line)}
.prose h3{font-size:1.08rem;margin:1.3em 0 .4em}
.prose h4{font-size:.98rem;margin:1.1em 0 .35em;color:var(--txt2)}
.prose h1:first-child,.prose h2:first-child{margin-top:0}
.prose ul,.prose ol{padding-left:1.4rem;margin:0 0 1em}
.prose li{margin:.25em 0}
.prose blockquote{
  margin:1em 0;padding:.7rem 1rem;border-left:3px solid var(--acc);
  background:rgba(77,163,255,.06);color:var(--txt2);border-radius:0 9px 9px 0;
}
.prose hr{border:0;border-top:1px solid var(--line);margin:2em 0}
.prose table{margin:0 0 1.2em}
.prose th{text-align:left}
.prose code:not(pre code){font-size:.85em}

/* ---- numbered steps ---- */
.steps{margin:0 0 1.2rem;padding-left:1.2rem;color:var(--txt2);font-size:.92rem;line-height:1.9}
.steps strong{color:var(--txt)}

/* ---- pricing ---- */
.plan-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(255px,1fr));gap:1.2rem;max-width:1000px;margin:0 auto}
.plan{
  position:relative;background:linear-gradient(180deg,var(--panel),var(--bg2));
  border:1px solid var(--line);border-radius:var(--radius);padding:1.6rem 1.5rem;
  display:flex;flex-direction:column;
}
.plan-hot{border-color:rgba(77,163,255,.5);box-shadow:0 24px 60px -30px rgba(77,163,255,.7)}
.plan-ribbon{
  position:absolute;top:-11px;left:50%;transform:translateX(-50%);
  background:linear-gradient(135deg,var(--acc),var(--acc2));color:#fff;
  font-size:.68rem;font-weight:700;text-transform:uppercase;letter-spacing:.09em;
  padding:.22rem .7rem;border-radius:99px;white-space:nowrap;
}
.plan-name{margin:0;font-size:1.2rem}
.plan-tag{margin:.2rem 0 1rem;font-size:.86rem;min-height:2.6em}
.plan-price{display:flex;align-items:baseline;gap:.35rem;margin-bottom:.3rem}
.plan-price b{font:800 2.2rem var(--mono);letter-spacing:-.04em}
.plan-price span{font-size:.85rem}
.plan-credits{
  font-size:.78rem;color:var(--warn);font-weight:600;margin-bottom:.6rem;
  font-family:var(--mono);
}
.plan-feats{list-style:none;padding:0;margin:1rem 0 1.4rem;flex:1;font-size:.9rem}
.plan-feats li{display:flex;gap:.55rem;padding:.32rem 0;color:var(--txt2);align-items:flex-start}
.tick{color:var(--ok);font-weight:700;flex:0 0 auto}

/* ---- cta band ---- */
.cta-band{
  display:flex;align-items:center;justify-content:space-between;gap:1.6rem;flex-wrap:wrap;
  margin-top:3.4rem;padding:2rem 2.2rem;border-radius:var(--radius);
  background:linear-gradient(120deg,rgba(77,163,255,.14),rgba(124,92,255,.14));
  border:1px solid var(--line2);
}
.cta-band h2{margin:0 0 .2rem}
.cta-band p{margin:0}

/* ---- footer grid ---- */
.foot-grid{
  display:grid;grid-template-columns:1.7fr repeat(3,1fr);gap:2rem;
  padding:2.2rem 0 1.6rem;
}
.foot-grid>div{display:flex;flex-direction:column;gap:.35rem;font-size:.88rem}
.foot-h{
  font-size:.72rem;text-transform:uppercase;letter-spacing:.11em;font-weight:700;
  color:var(--txt3);margin-bottom:.4rem;
}
.foot-grid a{color:var(--txt2)}
.foot-grid a:hover{color:var(--acc)}
.foot-legal{
  display:flex;justify-content:space-between;gap:1rem;flex-wrap:wrap;
  padding:1rem 0 1.6rem;border-top:1px solid var(--line);font-size:.82rem;
}

/* ---- terminal green ---- */
.terminal-body .g{color:#7ee787}

/* ---- legal page ---- */
.legal-wrap{max-width:820px;margin-inline:auto}
.legal-nav{display:flex;gap:.4rem;flex-wrap:wrap;margin-top:1.2rem;justify-content:center}

/* =====================================================================
   LIGHT THEME
   ===================================================================== */
[data-theme="light"]{
  --bg:#f4f6fb;
  --bg2:#ffffff;
  --panel:#ffffff;
  --panel2:#eef1f8;
  --line:#dde3ee;
  --line2:#c6d0e2;
  --txt:#16203a;
  --txt2:#4a5878;
  --txt3:#7b88a6;
  --acc:#1667d6;
  --acc2:#6d3ff2;
  --ok:#0f9f5f;
  --warn:#b8730b;
  --bad:#d92b4f;
  --easy:#0f9f5f; --medium:#b8730b; --hard:#d1601f; --insane:#d92b4f;

  --radius:14px;
  --on-acc:#ffffff;
}
[data-theme="light"] body{
  background:
    radial-gradient(1100px 620px at 82% -12%,rgba(124,92,255,.10),transparent 62%),
    radial-gradient(900px 520px at 6% 4%,rgba(22,103,214,.09),transparent 58%),
    var(--bg);
}
[data-theme="light"] .topbar{background:rgba(244,246,251,.88)}
[data-theme="light"] .foot{background:rgba(255,255,255,.72)}
[data-theme="light"] pre,
[data-theme="light"] .code-box,
[data-theme="light"] .flag-input,
[data-theme="light"] .field input,
[data-theme="light"] .field textarea,
[data-theme="light"] .field select,
[data-theme="light"] .filters input,
[data-theme="light"] .filters select,
[data-theme="light"] .notify input[type=email],
[data-theme="light"] .review-form select{background:#fbfcfe}
[data-theme="light"] .terminal{background:#0b1020;border-color:#c6d0e2}
[data-theme="light"] .card,
[data-theme="light"] .mcard,
[data-theme="light"] .cat-card,
[data-theme="light"] .track-card,
[data-theme="light"] .plan,
[data-theme="light"] .stat,
[data-theme="light"] .kpi,
[data-theme="light"] .task,
[data-theme="light"] .list-item{box-shadow:0 1px 2px rgba(20,30,60,.05)}
[data-theme="light"] .mcard:hover{box-shadow:0 18px 38px -22px rgba(22,103,214,.45)}
[data-theme="light"] .btn-primary{color:#fff}
[data-theme="light"] .btn-ok{color:#fff}
[data-theme="light"] .mcard-thumb img{filter:none}

/* =====================================================================
   RESPONSIVE (extensions)
   ===================================================================== */
@media (max-width:1000px){
  .foot-grid{grid-template-columns:1fr 1fr}
}
@media (max-width:720px){
  .hide-sm{display:none}
  .foot-grid{grid-template-columns:1fr;gap:1.4rem}
  .cta-band{padding:1.5rem;text-align:center;justify-content:center}
  .trackbar{gap:.35rem}
  .chip{padding:.34rem .68rem;font-size:.78rem}
  .grid-4{grid-template-columns:1fr 1fr}
}

/* =====================================================================
   PRINT
   ===================================================================== */
@media print{
  .topbar,.foot,.btn,.flag-form,.tabs,.spawn-panel,.notify{display:none}
  body{background:#fff;color:#000}
  .card{border:1px solid #ccc;box-shadow:none}
}

/* ---------------------------------------------------------------
   Flag editor — the shared / per-player flag block on the lab form
   --------------------------------------------------------------- */
.flag-editor{
  padding:.95rem;margin:0 0 1rem;border:1px dashed var(--line2);
  border-radius:12px;background:rgba(127,127,127,.04);
}
.flag-editor .field:last-child{margin-bottom:0}
.input-row{display:flex;gap:.5rem}
.input-row input{flex:1 1 auto;width:auto;min-width:0}
.input-row button{flex:0 0 auto;align-self:stretch;padding-top:0;padding-bottom:0}
/* Whichever half is not in play is removed rather than merely dimmed, so it
   cannot be read as the field the operator is meant to fill in. */
[data-flag-editor] .flag-mode-static,
[data-flag-editor] .flag-mode-dynamic{display:none}
[data-flag-editor].mode-static  .flag-mode-static,
[data-flag-editor].mode-dynamic .flag-mode-dynamic{display:block}
.flag-preview{word-break:break-all}
.tag-per{color:var(--warn);border-color:rgba(255,182,72,.32);background:rgba(255,182,72,.09)}

/* A player's own flag on the lab page. */
.flag-mine{
  display:flex;align-items:center;gap:.6rem;flex-wrap:wrap;
  padding:.55rem 0;border-top:1px solid var(--line);
}
.flag-mine:first-of-type{border-top:0}
.flag-val{
  font-family:var(--mono);font-size:.86rem;color:var(--ok);
  word-break:break-all;flex:1 1 14rem;
}

/* ---------------------------------------------------------------
   Operator-granted exam access
   ---------------------------------------------------------------
   A separate panel from the rest of the account page, because it is the
   one control there that hands out an achievement on the operator's word
   alone.  The reason field sits in the row rather than behind a dialog so
   the grant and its justification are visible together, and so there is
   no path that grants without saying why. */
.exam-access{margin-top:1rem}
.exam-access .table-wrap{margin:-.2rem 0 0}
.exam-access .exam-access-act{min-width:16rem}
.exam-access .exam-access-act form{margin:0}
.exam-access .exam-grant-form{
  display:flex;gap:.4rem;align-items:center;flex-wrap:wrap;margin:0;
}
.exam-access .exam-grant-form .input{
  flex:1 1 9rem;min-width:7rem;margin:0;
}
/* An open gate should be findable when scanning the table, not only when
   reading each row. */
.exam-access tr.row-open{background:rgba(255,182,72,.05)}
.exam-access .cert-field-default{font-size:.72rem}

.exam-granted{margin-bottom:1rem}
.exam-card .alert{margin-bottom:.9rem}

/* ---------------------------------------------------------------
   Certificate design editor
   ---------------------------------------------------------------
   Two columns: the fields, and a preview that stays put while they are
   edited.  Below 1100px the preview moves above the fields, because a
   preview you have to scroll past to see is not a preview. */
.cert-design{display:block}
.cert-design-grid{
  display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.05fr);
  gap:1.2rem;align-items:start;
}
.cert-design-fields > .card{padding:1.2rem 1.3rem}
.cert-design-group{
  border:0;padding:0;margin:0 0 1.5rem;min-width:0;
}
.cert-design-group legend{
  padding:0;margin:0 0 .7rem;font-size:.78rem;font-weight:700;
  letter-spacing:.11em;text-transform:uppercase;color:var(--acc);
  border-bottom:1px solid var(--line);width:100%;padding-bottom:.35rem;
}
.cert-field{margin:0 0 .75rem}
.cert-field:last-child{margin-bottom:0}
.cert-field > label,
.cert-colour-label{
  display:block;margin:0 0 .25rem;font-size:.8rem;font-weight:600;color:var(--txt2);
}
.cert-field .field-hint,
.cert-field .muted.small{display:block;margin:.2rem 0 0;font-weight:400}
.cert-field textarea{
  font-family:var(--mono);font-size:.78rem;line-height:1.5;resize:vertical;
  min-height:3rem;
}
.cert-field .input{margin:0}
.cert-field-default{
  margin:.22rem 0 0;font-size:.7rem;color:var(--txt3);
}
.cert-field-default code{
  background:var(--bg2);padding:.05rem .25rem;border-radius:4px;
  word-break:break-all;
}

/* Swatch plus text box: the box is the field, the swatch is a control for it,
   so the swatch is out of the tab order and never carries a name. */
.cert-colour{display:flex;gap:.45rem;align-items:center}
.cert-colour input[type="color"]{
  flex:0 0 auto;width:34px;height:34px;padding:2px;cursor:pointer;
  background:var(--panel);border:1px solid var(--line2);border-radius:8px;
}
.cert-colour .input{flex:1 1 auto;min-width:0}

/* ---- the preview ---- */
.cert-design-side{position:sticky;top:1rem}
.cert-preview-card{padding:1.1rem 1.2rem}
.cert-preview-head{
  display:flex;align-items:baseline;justify-content:space-between;
  gap:.8rem;margin-bottom:.5rem;
}
.cert-preview-state{
  font-size:.7rem;letter-spacing:.05em;text-transform:uppercase;
  color:var(--txt3);white-space:nowrap;
}
.cert-preview-state.is-busy{color:var(--warn)}
.cert-preview-state.is-dirty{color:var(--acc)}
.cert-preview-state.is-bad{color:var(--bad)}

.cert-preview-frame{
  margin:.8rem 0;border:1px solid var(--line2);border-radius:10px;
  overflow:hidden;background:var(--bg2);
}
/* Tall enough to show the whole sheet without a scrollbar in the common
   case, short enough that the fields below stay reachable. */
.cert-preview-frame iframe{display:block;width:100%;height:30rem;border:0}

.cert-preview-names{margin:.6rem 0}
.cert-preview-names summary{
  cursor:pointer;font-size:.82rem;color:var(--txt2);font-weight:600;
}
.cert-preview-names .field{margin:.6rem 0 0}
.cert-preview-actions{
  display:flex;gap:.5rem;flex-wrap:wrap;margin-top:1rem;
  padding-top:.9rem;border-top:1px solid var(--line);
}
.cert-preview-actions .btn{flex:1 1 auto}
.cert-preview-reset{
  margin-top:.8rem;padding-top:.8rem;border-top:1px solid var(--line);
}
.cert-preview-reset p{margin:0 0 .5rem}

/* A dot on a tab whose design has been edited, so it is visible without
   opening the tab. */
.tab-dot{
  display:inline-block;width:6px;height:6px;border-radius:50%;
  background:var(--warn);vertical-align:middle;margin-left:.35rem;
}

/* ---------------------------------------------------------------
   Hackathon events
   --------------------------------------------------------------- */
.hack-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:1rem}
.hack-card{
  background:linear-gradient(180deg,var(--panel),var(--bg2));
  border:1px solid var(--line);border-radius:12px;padding:1.1rem 1.2rem;
  display:flex;flex-direction:column;gap:.55rem;
}
.hack-card.upcoming{border-color:rgba(77,163,255,.36)}
.hack-card.past{opacity:.82}
.hack-card h3{margin:0;font-size:1rem;line-height:1.3}
.hack-card .hack-when{
  font-size:.74rem;letter-spacing:.06em;text-transform:uppercase;color:var(--acc);
}
.hack-card .hack-when.past{color:var(--txt3)}
.hack-card .hack-where{font-size:.8rem;color:var(--txt2)}
.hack-card .hack-tally{
  display:flex;gap:1rem;flex-wrap:wrap;font-size:.76rem;color:var(--txt3);
  padding-top:.5rem;border-top:1px solid var(--line);margin-top:auto;
}
.hack-card .hack-tally b{color:var(--txt2)}
.hack-card .hack-act{display:flex;gap:.4rem;flex-wrap:wrap;padding-top:.6rem}
.hack-card .hack-act form{margin:0}
.hack-card .hack-act .input{flex:1 1 8rem;min-width:6rem;margin:0}

@media (max-width:1100px){
  /* One column, preview first.  A preview below the fold is a screenshot. */
  .cert-design-grid{grid-template-columns:minmax(0,1fr)}
  .cert-design-side{position:static;order:-1}
  .cert-preview-frame iframe{height:26rem}
}
@media (max-width:560px){
  .cert-preview-actions{flex-direction:column}
  .exam-access .exam-access-act{min-width:0}
  .exam-access .exam-grant-form{flex-direction:column;align-items:stretch}
}

/* ---------------- certificate approval queue ---------------- */

/* The line under the page heading when something is waiting.

Deliberately an alert rather than a quiet link: the reason an operator opens
this page is almost always a notification they have just been sent, and the
answer to that is one click away. A subdued grey link in the filter bar would be
read past. */
.queue-prompt{
  display:flex;gap:.6rem;flex-wrap:wrap;align-items:center;
  margin-bottom:1.1rem;
}
.queue-prompt a{font-weight:600}

/* One row of the queue: who asked, for what, how far along they are, and the
decision. The verdict is two buttons rather than a select plus a submit, because
approving a queue of requests should be clicking rather than configuring, and a
mistaken click on Decline is recoverable while a forgotten dropdown is not. */
.decide-form{display:flex;flex-direction:column;gap:.45rem;min-width:15rem}
.decide-form input{
  width:100%;background:#070a11;border:1px solid var(--line2);color:var(--txt);
  padding:.42rem .6rem;border-radius:9px;font:400 .82rem var(--sans);
}
.decide-form input:focus{
  outline:none;border-color:var(--acc);box-shadow:0 0 0 3px rgba(77,163,255,.16);
}
.decide-buttons{display:flex;gap:.4rem}
.decide-buttons .btn{flex:1 1 0}

/* The second look before a batch award.

Coloured as a warning rather than as information on purpose - the whole reason
this step exists is that the number in it is bigger than an operator expected. */
.bulk-confirm{margin:0 0 1.1rem}
.bulk-confirm .row-actions{gap:.5rem}
