/* ==========================================================================
   TechBiz Academy — UI layer

   Loaded AFTER academy.css and deliberately additive: it restyles what is
   already on the page and adds new primitives, so no existing template had to
   be rewritten.

   The look follows the InfoSecLabs dashboard the owner chose: a deep base
   under a violet/magenta wash, a node-graph texture behind everything, rounded
   panels with terminal chrome, and uppercase severity pills.

   BOTH THEMES ARE STYLED. The first pass scoped everything to dark and left
   the light theme with no backdrop and invisible panels — the --ui-panel token
   was rgba(255,255,255,.035), which on a white page is nothing at all. Panels
   and lines now come from tokens that are redefined per theme, and only the
   deep atmospheric base is dark-only.
   ========================================================================== */

:root,
:root[data-theme="dark"] {
    --ui-violet:   #7c3aed;
    --ui-magenta:  #e829c8;
    --ui-mint:     #2ee6a8;
    --ui-cyan:     #22d3ff;

    --ui-panel:    rgba(255, 255, 255, 0.035);
    --ui-panel-2:  rgba(255, 255, 255, 0.055);
    --ui-line:     rgba(255, 255, 255, 0.09);
    --ui-radius:   16px;

    --sev-high:    #ff4d6a;
    --sev-med:     #ffa32f;
    --sev-low:     #3b9dff;
}

/* Light theme: same hues, but darkened enough to hold their own on white, and
   panels become real surfaces with a visible hairline instead of a translucent
   white film that disappears. */
:root[data-theme="light"] {
    --ui-violet:   #6d28d9;
    --ui-magenta:  #c026a6;
    --ui-mint:     #0d9488;
    --ui-cyan:     #0284c7;

    --ui-panel:    #ffffff;
    --ui-panel-2:  #f6f8fc;
    --ui-line:     #dfe6ef;
    --ui-radius:   16px;

    --sev-high:    #dc2626;
    --sev-med:     #b45309;
    --sev-low:     #1d4ed8;
}

/* --------------------------------------------------------------- backdrop */
/* z-index 0, NOT -1: body's own background-color propagates to the canvas and
   paints over anything behind it, so a -1 pseudo-element is invisible. Sitting
   at 0 with the real content lifted to 1 is what works. The sticky header is
   already at 100 and is left alone — giving it position:relative via body > *
   would silently kill the sticky. */
body.academy { position: relative; }

body.academy::before,
body.academy::after {
    content: "";
    pointer-events: none;
    z-index: 0;
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 100%;
}

body.academy > main,
body.academy > footer,
body.academy > .ac-footer {
    position: relative;
    z-index: 1;
}

/* BOTH layers are absolute over the whole document, not fixed.
 *
 * Fixed, nothing appeared to move while scrolling — and a seamlessly repeating
 * tile that scrolls still looks identical at every offset, which is why the
 * first attempt at "make it move" changed nothing visible. The wash is what
 * gives perceptible motion, so it is spread DOWN the document at four
 * different heights: scrolling now carries you through violet, then magenta,
 * then cyan, and the page visibly changes under the content.
 */
:root:not([data-theme="light"]) body.academy { background: #05040a; }

:root:not([data-theme="light"]) body.academy::before {
    background:
        radial-gradient(ellipse 1000px 700px at 50% 0%,    rgba(124, 58, 237, .40), transparent 62%),
        radial-gradient(ellipse 760px  560px at 96% 18%,   rgba(232, 41, 200, .22), transparent 60%),
        radial-gradient(ellipse 820px  620px at 2%  42%,   rgba(34, 211, 255, .16), transparent 60%),
        radial-gradient(ellipse 900px  640px at 88% 66%,   rgba(124, 58, 237, .26), transparent 60%),
        radial-gradient(ellipse 820px  600px at 10% 90%,   rgba(232, 41, 200, .18), transparent 60%),
        linear-gradient(180deg, #0b0718 0%, #07060f 38%, #090616 70%, #05040a 100%);
}

/* Light theme gets the same structure at a fraction of the strength — enough
   that the page is not a blank white sheet, nowhere near enough to fight the
   text. Without this the academy in light mode had no backdrop at all. */
:root[data-theme="light"] body.academy { background: #f4f7fb; }

:root[data-theme="light"] body.academy::before {
    background:
        radial-gradient(ellipse 1000px 700px at 50% 0%,  rgba(109, 40, 217, .10), transparent 62%),
        radial-gradient(ellipse 760px  560px at 96% 18%, rgba(192, 38, 166, .07), transparent 60%),
        radial-gradient(ellipse 820px  620px at 2%  42%, rgba(2, 132, 199, .08),  transparent 60%),
        radial-gradient(ellipse 900px  640px at 88% 66%, rgba(109, 40, 217, .07), transparent 60%),
        radial-gradient(ellipse 820px  600px at 10% 90%, rgba(13, 148, 136, .07), transparent 60%),
        linear-gradient(180deg, #eef2f9 0%, #f6f8fc 45%, #f1f5fb 100%);
}

/* The node graph, in white on dark and in ink on light. */
body.academy::after {
    background-size: 220px 220px;
    /* Fades over a fixed distance, not a percentage: a percentage mask on a
       3,000px course page would thin the texture out to nothing by halfway. */
    -webkit-mask-image: linear-gradient(180deg, #000 0px, rgba(0, 0, 0, .5) 900px, rgba(0, 0, 0, .35) 100%);
            mask-image: linear-gradient(180deg, #000 0px, rgba(0, 0, 0, .5) 900px, rgba(0, 0, 0, .35) 100%);
}
:root:not([data-theme="light"]) body.academy::after {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220' viewBox='0 0 220 220'%3E%3Cg fill='none' stroke='%23ffffff' stroke-width='.6' opacity='.16'%3E%3Cpath d='M18 42 L96 18 L174 56 L206 132 L132 196 L46 168 Z'/%3E%3Cpath d='M96 18 L132 196'/%3E%3Cpath d='M18 42 L206 132'/%3E%3Cpath d='M46 168 L174 56'/%3E%3C/g%3E%3Cg fill='%23ffffff' opacity='.30'%3E%3Ccircle cx='18' cy='42' r='1.9'/%3E%3Ccircle cx='96' cy='18' r='1.9'/%3E%3Ccircle cx='174' cy='56' r='1.9'/%3E%3Ccircle cx='206' cy='132' r='1.9'/%3E%3Ccircle cx='132' cy='196' r='1.9'/%3E%3Ccircle cx='46' cy='168' r='1.9'/%3E%3C/g%3E%3C/svg%3E");
    opacity: .55;
}
:root[data-theme="light"] body.academy::after {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220' viewBox='0 0 220 220'%3E%3Cg fill='none' stroke='%231a2b4a' stroke-width='.7' opacity='.22'%3E%3Cpath d='M18 42 L96 18 L174 56 L206 132 L132 196 L46 168 Z'/%3E%3Cpath d='M96 18 L132 196'/%3E%3Cpath d='M18 42 L206 132'/%3E%3Cpath d='M46 168 L174 56'/%3E%3C/g%3E%3Cg fill='%231a2b4a' opacity='.34'%3E%3Ccircle cx='18' cy='42' r='1.9'/%3E%3Ccircle cx='96' cy='18' r='1.9'/%3E%3Ccircle cx='174' cy='56' r='1.9'/%3E%3Ccircle cx='206' cy='132' r='1.9'/%3E%3Ccircle cx='132' cy='196' r='1.9'/%3E%3Ccircle cx='46' cy='168' r='1.9'/%3E%3C/g%3E%3C/svg%3E");
    opacity: .5;
}

/* main.css gives .hero an OPAQUE linear-gradient as its last background layer,
   which painted straight over the page wash and left the academy looking like
   two unrelated pages stacked. Keep the hero's accent radials, drop its base,
   and let the backdrop show through so the whole page is one scene. */
body.academy .hero {
    background:
        radial-gradient(circle at 18% 24%, color-mix(in srgb, var(--ui-mint) 14%, transparent), transparent 46%),
        radial-gradient(circle at 82% 28%, color-mix(in srgb, var(--ui-magenta) 14%, transparent), transparent 46%);
}
body.academy .section,
body.academy .ac-main { background: transparent; }

/* ------------------------------------------------------------- theme toggle */
/* It was a 42px near-black disc with a thin border and a small grey glyph, and
   it read as an empty circle — the owner could not find it. Accent-coloured
   icon, a surface that separates from the header, and a hover state. */
body.academy .theme-toggle {
    width: 40px; height: 40px;
    display: inline-grid; place-items: center;
    border-radius: 50%;
    color: var(--ui-mint);
    background: color-mix(in srgb, var(--ui-mint) 12%, transparent);
    border: 1px solid color-mix(in srgb, var(--ui-mint) 42%, transparent);
    font-size: 1rem;
    transition: background .18s, color .18s, transform .18s;
}
body.academy .theme-toggle:hover {
    background: color-mix(in srgb, var(--ui-mint) 22%, transparent);
    transform: rotate(-12deg);
}
body.academy .theme-toggle i { color: inherit; }
/* ------------------------------------------------------------------ header */
:root:not([data-theme="light"]) body.academy .ac-header {
    background: rgba(8, 6, 18, .72);
    border-bottom: 1px solid var(--ui-line);
}
body.academy .ac-nav a {
    position: relative;
    padding: .34rem .1rem;
    transition: color .18s;
}
/* Underline grows from the centre on hover and on the current page, so the nav
   has a state at all — previously only the text colour changed. */
body.academy .ac-nav a:not(.btn)::after {
    content: "";
    position: absolute;
    left: 50%; right: 50%; bottom: -2px; height: 2px;
    border-radius: 2px;
    background: linear-gradient(90deg, var(--ui-magenta), var(--ui-mint));
    transition: left .2s, right .2s;
}
body.academy .ac-nav a:not(.btn):hover::after,
body.academy .ac-nav a[aria-current="page"]::after { left: 0; right: 0; }
body.academy .ac-nav a[aria-current="page"] { color: var(--text); }

/* ------------------------------------------------------------------ panels */
:root:not([data-theme="light"]) body.academy .card {
    background: var(--ui-panel);
    border: 1px solid var(--ui-line);
    border-radius: var(--ui-radius);
    backdrop-filter: blur(6px);
    transition: border-color .2s, transform .2s, background .2s;
}
:root:not([data-theme="light"]) body.academy .card:hover {
    background: var(--ui-panel-2);
    border-color: rgba(232, 41, 200, .35);
}

/* A panel with the terminal chrome header from the reference. Use as
   <div class="tbz-panel"><div class="tbz-panel__bar">…</div><div class="tbz-panel__body">…</div></div> */
.tbz-panel {
    border-radius: var(--ui-radius);
    border: 1px solid var(--ui-line);
    background: var(--ui-panel);
    overflow: hidden;
}
.tbz-panel__bar {
    display: flex; align-items: center; gap: .7rem;
    padding: .85rem 1.1rem;
    border-bottom: 1px solid var(--ui-line);
    background: rgba(255, 255, 255, .025);
    font-family: "Orbitron", "Segoe UI", sans-serif;
    font-size: .82rem; font-weight: 700; letter-spacing: .16em; text-transform: uppercase;
    color: var(--text);
}
.tbz-panel__bar i { color: var(--ui-magenta); }
.tbz-panel__dots { margin-left: auto; display: flex; gap: .4rem; }
.tbz-panel__dots span { width: 10px; height: 10px; border-radius: 50%; background: var(--ui-line); }
.tbz-panel__dots span:nth-child(1) { background: #ff5f57; }
.tbz-panel__dots span:nth-child(2) { background: #febc2e; }
.tbz-panel__dots span:nth-child(3) { background: #28c840; }
.tbz-panel__body { padding: 1.1rem; display: flex; flex-direction: column; gap: .85rem; }

/* ------------------------------------------------------------- queue rows */
.tbz-row {
    display: flex; align-items: center; gap: 1rem;
    padding: 1rem 1.1rem;
    border-radius: 14px;
    border: 1px solid var(--ui-line);
    background: rgba(255, 255, 255, .025);
    transition: border-color .2s, background .2s;
}
.tbz-row:hover { border-color: rgba(124, 58, 237, .45); background: rgba(255, 255, 255, .045); }
.tbz-row__ic {
    flex: 0 0 auto; width: 46px; height: 46px; border-radius: 12px;
    display: grid; place-items: center; font-size: 1.05rem;
    color: var(--ui-mint); background: rgba(46, 230, 168, .1);
    border: 1px solid rgba(46, 230, 168, .22);
}
.tbz-row__body { flex: 1 1 200px; min-width: 0; }
.tbz-row__meta { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; margin-bottom: .3rem; }
.tbz-row__src { font-size: .78rem; color: var(--text-secondary); }
.tbz-row__title { font-weight: 700; color: var(--text); line-height: 1.3; }
.tbz-row__cta { flex: 0 0 auto; }

/* Severity + technique chips */
.sev {
    display: inline-block; padding: .18rem .5rem; border-radius: 5px;
    font-size: .66rem; font-weight: 800; letter-spacing: .09em; text-transform: uppercase;
    color: #0b0718;
}
.sev--high { background: var(--sev-high); }
.sev--med  { background: var(--sev-med); }
.sev--low  { background: var(--sev-low); color: #fff; }
.sev--done { background: var(--ui-mint); }
.chip {
    display: inline-block; padding: .16rem .46rem; border-radius: 5px;
    font-family: ui-monospace, "Cascadia Code", Consolas, monospace;
    font-size: .68rem; color: var(--text-secondary);
    background: rgba(255, 255, 255, .05); border: 1px solid var(--ui-line);
}

/* -------------------------------------------------------------- stat tiles */
.tbz-stats { display: grid; gap: 1rem; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); }
.tbz-stat {
    border-radius: var(--ui-radius); border: 1px solid var(--ui-line);
    background: var(--ui-panel); padding: 1.15rem 1.2rem;
}
.tbz-stat__lbl {
    display: block; font-size: .7rem; font-weight: 800; letter-spacing: .15em;
    text-transform: uppercase; color: var(--text-secondary);
}
.tbz-stat__val {
    display: block; margin-top: .5rem; font-family: "Orbitron", sans-serif;
    font-size: 1.85rem; font-weight: 900; line-height: 1; color: var(--text);
}
.tbz-stat__val small { font-size: .9rem; font-weight: 700; color: var(--text-secondary); }
.tbz-stat__sub { display: block; margin-top: .45rem; font-size: .78rem; color: var(--text-secondary); }
.tbz-stat--accent .tbz-stat__val { color: var(--ui-mint); }
.tbz-stat--magenta .tbz-stat__val { color: var(--ui-magenta); }

/* XP / progress bar */
.tbz-bar { height: 9px; border-radius: 999px; background: rgba(255, 255, 255, .08); overflow: hidden; margin-top: .7rem; }
.tbz-bar__fill {
    height: 100%; border-radius: 999px;
    background: linear-gradient(90deg, var(--ui-magenta), var(--ui-mint));
}

/* ----------------------------------------------------------------- motion */
/* Everything above that moves is a transition on hover, so honouring this is
   one rule rather than a sweep. */
@media (prefers-reduced-motion: reduce) {
    body.academy *,
    body.academy *::before,
    body.academy *::after { transition: none !important; animation: none !important; }
}

/* ------------------------------------------------------------------ phone */
@media (max-width: 600px) {
    .tbz-row { flex-wrap: wrap; }
    .tbz-row__cta { flex: 1 1 100%; }
    .tbz-row__cta .btn { width: 100%; }
    .tbz-panel__body { padding: .85rem; }
    .tbz-stat__val { font-size: 1.55rem; }
}

/* ---------------------------------------------------------------------------
   Profile — identity banner, stat cards, coverage radar, progression panel.
   Laid out against the reference at infoseclabs.io/dashboard?view=profile.
   Markup: academy/includes/profile-hero.php
   --------------------------------------------------------------------------- */
.pf{margin-bottom:2.2rem}

.pf-id{display:flex;align-items:center;justify-content:space-between;gap:1.6rem;flex-wrap:wrap;
  border-radius:var(--ui-radius);border:1px solid var(--ui-line);padding:1.7rem 1.8rem;
  background:linear-gradient(110deg,rgba(124,58,237,.26),rgba(232,41,200,.12) 48%,transparent 80%)}
.pf-id__left{display:flex;align-items:center;gap:1.5rem;flex:1 1 420px;min-width:0}
.pf-avatar{position:relative;flex:0 0 auto;width:112px;height:112px;border-radius:50%;
  display:grid;place-items:center;
  font-family:"Orbitron",sans-serif;font-size:2.1rem;font-weight:900;color:#fff;
  background:linear-gradient(145deg,var(--ui-violet),var(--ui-magenta));
  box-shadow:0 0 0 3px rgba(232,41,200,.5),0 0 38px rgba(232,41,200,.32)}
.pf-avatar img{width:100%;height:100%;border-radius:50%;object-fit:cover}
.pf-avatar--empty{background:linear-gradient(145deg,#2a2440,#3b2550)}
.pf-avatar__badge{position:absolute;right:2px;bottom:2px;width:30px;height:30px;border-radius:50%;
  display:grid;place-items:center;font-size:.76rem;color:#fff;text-decoration:none;
  background:var(--ui-magenta);border:3px solid #0b0718;transition:transform .18s}
.pf-avatar__badge:hover{transform:scale(1.12)}
.pf-id__who{min-width:0}
.pf-id__nameline{display:flex;align-items:center;gap:.6rem;flex-wrap:wrap}
.pf-id__nameline h1{margin:0;font-size:clamp(1.7rem,4vw,2.5rem);line-height:1.05;letter-spacing:-1.2px}
.pf-id__nameline h1 span{color:var(--text-secondary)}
.pf-chip{font-size:.68rem;font-weight:800;letter-spacing:.09em;text-transform:uppercase;
  padding:.3rem .7rem;border-radius:999px;border:1px solid var(--ui-line);
  color:var(--text-secondary);background:rgba(255,255,255,.06);white-space:nowrap}
.pf-chip--live{color:var(--ui-mint);border-color:rgba(46,230,168,.42);display:inline-flex;align-items:center;gap:.4rem}
.pf-dot{width:7px;height:7px;border-radius:50%;background:currentColor}
.pf-id__bio{margin:.8rem 0 .4rem;max-width:62ch;color:var(--text-secondary);font-size:.92rem;line-height:1.6}
.pf-id__meta{margin:0;font-size:.8rem;color:var(--text-secondary)}
.pf-id__meta strong{color:var(--ui-mint)}
.pf-id__actions{display:flex;flex-direction:column;gap:.6rem;flex:0 0 auto}
.pf-btn{display:inline-flex;align-items:center;justify-content:center;gap:.5rem;white-space:nowrap;
  padding:.72rem 1.3rem;border-radius:999px;font-size:.82rem;font-weight:700;text-decoration:none;
  border:1px solid var(--ui-line);color:var(--text);background:rgba(255,255,255,.05);transition:all .18s}
.pf-btn:hover{border-color:rgba(232,41,200,.5);background:rgba(255,255,255,.09)}
.pf-btn--mag{border:0;color:#fff;background:linear-gradient(95deg,var(--ui-violet),var(--ui-magenta));
  box-shadow:0 6px 22px rgba(232,41,200,.3)}
.pf-btn--mag:hover{filter:brightness(1.08)}

/* Only 389 of 2,935 students have uploaded a photo, and the points table and
   certificates both carry a name. This is the one gap a student can close in
   ten seconds, so it is asked for inline rather than buried in settings. */
.pf-nag{display:flex;align-items:center;gap:.9rem;flex-wrap:wrap;margin-top:1rem;padding:.95rem 1.2rem;
  border-radius:14px;text-decoration:none;border:1px dashed rgba(232,41,200,.5);
  background:rgba(232,41,200,.07);color:var(--text-secondary);font-size:.86rem;line-height:1.5}
.pf-nag i{color:var(--ui-magenta);font-size:1.1rem}
.pf-nag strong{color:var(--text)}
.pf-nag span{flex:1 1 280px;min-width:0}
.pf-nag em{font-style:normal;font-weight:800;color:var(--ui-magenta);white-space:nowrap}

.pf-tabs{display:flex;gap:.3rem;flex-wrap:wrap;margin:1.4rem 0 1rem;border-bottom:1px solid var(--ui-line)}
.pf-tabs a{padding:.7rem 1.05rem;font-size:.78rem;font-weight:800;letter-spacing:.09em;text-transform:uppercase;
  color:var(--text-secondary);text-decoration:none;border-bottom:2px solid transparent;white-space:nowrap}
.pf-tabs a:hover{color:var(--text)}
.pf-tabs a.is-active{color:var(--ui-cyan);border-bottom-color:var(--ui-cyan)}

.pf-stats{display:grid;gap:1rem;grid-template-columns:repeat(auto-fit,minmax(252px,1fr))}
.pf-card{border-radius:var(--ui-radius);border:1px solid var(--ui-line);background:var(--ui-panel);
  padding:1.25rem 1.35rem;color:var(--text-secondary)}
.pf-card__top{display:flex;align-items:flex-start;justify-content:space-between;gap:1rem;margin-bottom:.2rem}
.pf-lbl{display:block;font-size:.68rem;font-weight:800;letter-spacing:.16em;text-transform:uppercase;color:var(--text-secondary)}
.pf-sub{display:block;margin-top:.25rem;font-style:normal;font-size:.68rem;letter-spacing:.1em;
  text-transform:uppercase;color:var(--text-secondary);opacity:.65}
.pf-glyph{flex:0 0 auto;width:34px;height:34px;border-radius:50%;display:grid;place-items:center;
  font-size:.8rem;color:var(--ui-magenta);background:rgba(232,41,200,.12);border:1px solid rgba(232,41,200,.3)}
.pf-sync{display:inline-flex;align-items:center;gap:.4rem;font-size:.66rem;font-weight:800;
  letter-spacing:.14em;text-transform:uppercase;color:var(--ui-magenta);white-space:nowrap}
.pf-big{margin:.6rem 0 0;font-family:"Orbitron",sans-serif;font-size:1.35rem;font-weight:900;
  line-height:1.15;color:var(--text)}
.pf-big--mint{color:var(--ui-mint);font-size:2.3rem}
.pf-big small{font-size:.95rem}
.pf-xprow{display:flex;justify-content:space-between;align-items:baseline;margin-top:1rem;font-size:.76rem}
.pf-xprow strong{color:var(--ui-magenta);font-size:.84rem}
.pf-bar{height:8px;border-radius:999px;background:rgba(127,127,127,.22);overflow:hidden;margin-top:.5rem}
.pf-bar span{display:block;height:100%;border-radius:999px;
  background:linear-gradient(90deg,var(--ui-magenta),var(--ui-mint))}
.pf-hint{margin:.7rem 0 0;font-size:.78rem;font-style:italic;line-height:1.55}
.pf-hint--caps{font-style:normal;font-weight:700;letter-spacing:.08em;text-transform:uppercase;font-size:.68rem}
.pf-hint a{color:var(--ui-mint)}
.pf-tier{display:flex;align-items:center;gap:.8rem;margin:.9rem 0 .2rem}
.pf-tier__ico{flex:0 0 auto;width:42px;height:42px;border-radius:12px;display:grid;place-items:center;
  font-size:1.05rem;color:var(--ui-magenta);background:rgba(232,41,200,.12);border:1px solid rgba(232,41,200,.3)}
.pf-tier strong{display:block;font-size:1.2rem;color:var(--text);line-height:1.2}
.pf-tier em{display:block;margin-top:.15rem;font-style:normal;font-size:.64rem;font-weight:800;
  letter-spacing:.14em;text-transform:uppercase;opacity:.75}
.pf-foot{display:flex;justify-content:space-between;align-items:center;margin-top:1.1rem;padding-top:.85rem;
  border-top:1px solid var(--ui-line);font-size:.68rem;font-weight:800;letter-spacing:.12em;text-transform:uppercase}
.pf-foot strong{color:var(--ui-mint);font-size:.95rem;letter-spacing:0}

.pf-lower{display:grid;gap:1rem;grid-template-columns:minmax(0,.9fr) minmax(0,1.5fr);margin-top:1rem}
.pf-radar svg{width:100%;max-width:260px;height:auto;display:block;margin:.4rem auto 0}
.pf-strip{display:grid;grid-template-columns:repeat(3,1fr);margin:1rem 0;border-radius:13px;
  border:1px solid var(--ui-line);background:rgba(255,255,255,.02);overflow:hidden}
.pf-strip div{padding:1rem .6rem;text-align:center;border-right:1px solid var(--ui-line)}
.pf-strip div:last-child{border-right:0}
.pf-strip strong{display:block;font-family:"Orbitron",sans-serif;font-size:1.6rem;color:var(--text);line-height:1}
.pf-strip strong.mag{color:var(--ui-magenta)}
.pf-strip strong.mint{color:var(--ui-mint)}
.pf-strip span{display:block;margin-top:.4rem;font-size:.64rem;font-weight:800;letter-spacing:.12em;text-transform:uppercase}
.mint{color:var(--ui-mint)}

.pf-track{position:relative;display:flex;align-items:center;gap:.9rem;flex-wrap:wrap;
  padding:.95rem 1.05rem 1.15rem;border-radius:13px;border:1px solid var(--ui-line);
  background:rgba(255,255,255,.02);margin-bottom:.7rem}
.pf-track:last-child{margin-bottom:0}
.pf-track__ico{flex:0 0 auto;width:42px;height:42px;border-radius:11px;display:grid;place-items:center;
  color:var(--ui-cyan);background:rgba(34,211,255,.1);border:1px solid rgba(34,211,255,.25)}
.pf-track__body{flex:1 1 200px;min-width:0}
.pf-track__body strong{display:block;color:var(--text);font-size:.98rem;line-height:1.3}
.pf-track__meta{display:block;margin-top:.3rem;font-size:.74rem}
.pf-pill{font-style:normal;font-size:.62rem;font-weight:800;letter-spacing:.1em;text-transform:uppercase;
  padding:.16rem .5rem;border-radius:5px;color:#04130c;background:var(--ui-mint);margin-right:.35rem}
.pf-track__pct{flex:0 0 auto;text-align:right}
.pf-track__pct strong{display:block;font-family:"Orbitron",sans-serif;font-size:1.25rem;color:var(--text);line-height:1}
.pf-track__pct span{display:block;margin-top:.2rem;font-size:.62rem;font-weight:800;letter-spacing:.12em;text-transform:uppercase}
.pf-bar--row{position:absolute;left:1.05rem;right:1.05rem;bottom:.6rem;height:4px;margin:0}

@media(max-width:900px){.pf-lower{grid-template-columns:1fr}}
@media(max-width:620px){
  .pf-id{padding:1.3rem}
  /* Chips were inline with the name, so on a phone each one took its own line
     beside the avatar and the block read as a ragged column. Name on its own
     line, chips flowing under it, avatar aligned to the top. */
  .pf-id__left{gap:1rem;align-items:flex-start}
  .pf-id__nameline{display:block}
  .pf-id__nameline h1{margin-bottom:.55rem}
  .pf-id__nameline .pf-chip{display:inline-flex;margin:0 .35rem .35rem 0}
  .pf-avatar{width:84px;height:84px;font-size:1.5rem}
  .pf-id__actions{flex-direction:row;width:100%}
  .pf-btn{flex:1 1 0}
  .pf-strip{grid-template-columns:1fr}
  .pf-strip div{border-right:0;border-bottom:1px solid var(--ui-line)}
  .pf-strip div:last-child{border-bottom:0}
}

/* ---------------------------------------------------------------------------
   Dashboard — welcome banner, onboarding checklist, priority queue.
   Markup: academy/includes/dashboard-hero.php
   --------------------------------------------------------------------------- */
.db{margin-bottom:2rem}

.db-welcome{display:flex;align-items:center;justify-content:space-between;gap:1.4rem;flex-wrap:wrap;
  border-radius:var(--ui-radius);border:1px solid var(--ui-line);padding:1.5rem 1.7rem;
  background:linear-gradient(110deg,rgba(124,58,237,.26),rgba(232,41,200,.12) 50%,transparent 82%)}
.db-welcome__who{display:flex;align-items:center;gap:1.1rem;flex:1 1 300px;min-width:0}
.db-ava{flex:0 0 auto;width:62px;height:62px;border-radius:50%;display:grid;place-items:center;
  font-family:"Orbitron",sans-serif;font-size:1.15rem;font-weight:900;color:#fff;overflow:hidden;
  box-shadow:0 0 0 2px rgba(232,41,200,.45)}
.db-ava img{width:100%;height:100%;object-fit:cover}
.db-welcome h1{margin:0;font-size:clamp(1.3rem,3.2vw,1.85rem);line-height:1.15;letter-spacing:-.8px}
.db-welcome h1 span{color:var(--ui-magenta)}
.db-welcome p{margin:.4rem 0 0;font-size:.82rem;color:var(--text-secondary)}
.db-welcome p strong{color:var(--ui-mint)}
.db-live{display:inline-flex;align-items:center;gap:.4rem;color:var(--ui-mint);font-weight:700}

.db-metrics{display:flex;gap:.7rem;flex:0 0 auto;flex-wrap:wrap}
.db-metric{min-width:92px;text-align:center;padding:.7rem .9rem;border-radius:13px;
  border:1px solid var(--ui-line);background:rgba(0,0,0,.25)}
.db-metric__lbl{display:block;font-size:.6rem;font-weight:800;letter-spacing:.14em;
  text-transform:uppercase;color:var(--text-secondary)}
.db-metric strong{display:block;margin-top:.3rem;font-family:"Orbitron",sans-serif;
  font-size:1.5rem;line-height:1;color:var(--text)}
.db-metric strong.mag{color:var(--ui-magenta)}
.db-metric__sub{display:block;margin-top:.25rem;font-size:.66rem;color:var(--text-secondary)}

.db-moves{margin-top:1rem;border-radius:var(--ui-radius);border:1px solid var(--ui-line);
  background:var(--ui-panel);padding:1.3rem 1.4rem}
.db-moves__head span{font-size:.72rem;font-weight:800;letter-spacing:.1em;text-transform:uppercase;
  color:var(--text-secondary)}
.db-tag{font-style:normal;padding:.2rem .55rem;border-radius:5px;margin-right:.5rem;
  color:#fff;background:var(--ui-magenta)}
.db-moves__head h2{margin:.6rem 0 .2rem;font-size:1.18rem}
.db-moves__head p{margin:0 0 1rem;font-size:.84rem;color:var(--text-secondary)}
.db-moves__row{display:grid;gap:.7rem;grid-template-columns:repeat(auto-fit,minmax(210px,1fr))}
.db-move{display:flex;align-items:center;gap:.7rem;padding:.85rem 1rem;border-radius:12px;
  border:1px solid var(--ui-line);background:rgba(255,255,255,.025);text-decoration:none;
  color:var(--text);font-size:.86rem;font-weight:600;transition:border-color .18s,background .18s}
.db-move:hover{border-color:rgba(232,41,200,.45);background:rgba(255,255,255,.05)}
.db-move__tick{color:var(--text-secondary);font-size:1.05rem}
.db-move.is-done{border-color:rgba(46,230,168,.4);background:rgba(46,230,168,.07)}
.db-move.is-done .db-move__tick{color:var(--ui-mint)}
.db-move.is-done span:last-child{color:var(--text-secondary);text-decoration:line-through}

.db-queue{margin-top:1rem}
.db-due{display:block;margin-top:.35rem;font-size:.76rem;color:var(--text-secondary)}
.db-empty,.db-more,.db-missed{margin:0;font-size:.86rem;color:var(--text-secondary);line-height:1.6}
.db-empty a,.db-more a,.db-missed a{color:var(--ui-mint)}
.db-missed{display:flex;align-items:flex-start;gap:.6rem;margin-top:.3rem;padding-top:.9rem;
  border-top:1px solid var(--ui-line)}
.db-missed i{color:var(--sev-med);margin-top:.15rem}
.db-queue .pf-btn{padding:.56rem 1.05rem;font-size:.78rem}

@media(max-width:620px){
  .db-welcome{padding:1.2rem}
  .db-metrics{width:100%}
  .db-metric{flex:1 1 0;min-width:0}
  .db-move span:last-child{min-width:0}
}

/* Points-table avatar. The profile tells students their photo shows up here,
   so it has to actually show up here. */
.lb-ava{flex:0 0 auto;width:34px;height:34px;border-radius:50%;display:grid;place-items:center;
  overflow:hidden;font-size:.72rem;font-weight:800;color:#fff;font-family:"Orbitron",sans-serif}
.lb-ava img{width:100%;height:100%;object-fit:cover}

/* --- Featured operations: lab of the day + games ------------------------- */
.db-ops{display:grid;gap:1rem;grid-template-columns:minmax(0,1.3fr) minmax(0,1fr);margin-top:1rem}
.db-op{border-radius:var(--ui-radius);border:1px solid var(--ui-line);padding:1.3rem 1.4rem;
  background:linear-gradient(120deg,rgba(124,58,237,.16),rgba(255,255,255,.02) 62%)}
.db-op--alt{background:linear-gradient(120deg,rgba(34,211,255,.13),rgba(255,255,255,.02) 62%)}
.db-op--clear{background:linear-gradient(120deg,rgba(46,230,168,.14),rgba(255,255,255,.02) 62%)}
.db-op__chips{display:flex;align-items:center;gap:.45rem;flex-wrap:wrap;margin-bottom:.9rem}
.db-op__chip{font-size:.62rem;font-weight:800;letter-spacing:.11em;text-transform:uppercase;
  padding:.26rem .6rem;border-radius:6px;border:1px solid var(--ui-line);
  color:var(--text-secondary);background:rgba(255,255,255,.05);white-space:nowrap}
.db-op__chip--day{color:var(--ui-cyan);border-color:rgba(34,211,255,.4);background:rgba(34,211,255,.1)}
.db-op__chip--hot{color:var(--sev-med);border-color:rgba(255,163,47,.4);background:rgba(255,163,47,.1)}
.db-op__chip--cy{color:var(--ui-mint);border-color:rgba(46,230,168,.4);background:rgba(46,230,168,.1)}
.db-op__id{margin-left:auto;font-family:ui-monospace,Consolas,monospace;font-size:.7rem;color:var(--text-secondary)}
.db-op h2{margin:0 0 .5rem;font-size:1.4rem;font-style:italic;letter-spacing:-.6px;color:var(--text)}
.db-op p{margin:0;font-size:.86rem;line-height:1.6;color:var(--text-secondary)}
.db-op__foot{display:flex;align-items:center;justify-content:space-between;gap:1rem;flex-wrap:wrap;margin-top:1.2rem}
.db-op__reward{font-size:.72rem;letter-spacing:.06em;text-transform:uppercase;color:var(--text-secondary)}
.db-op__reward strong{color:var(--ui-mint)}
.db-op .pf-btn{padding:.6rem 1.2rem;font-size:.8rem}

/* --- Badges -------------------------------------------------------------- */
.db-badges{margin-top:1rem;border-radius:var(--ui-radius);border:1px solid var(--ui-line);
  background:var(--ui-panel);padding:1.25rem 1.35rem}
.db-badges__head{display:flex;align-items:flex-start;justify-content:space-between;gap:1rem;
  flex-wrap:wrap;margin-bottom:1.1rem}
.db-streak{display:inline-flex;align-items:center;gap:.45rem;font-size:.74rem;font-weight:800;
  letter-spacing:.06em;color:var(--sev-med);white-space:nowrap}
.db-badges__row{display:grid;gap:.7rem;grid-template-columns:repeat(auto-fill,minmax(132px,1fr))}
.db-badge{position:relative;display:block;text-align:center;text-decoration:none;padding:1rem .6rem 1.1rem;
  border-radius:13px;border:1px solid var(--ui-line);background:rgba(255,255,255,.02);
  transition:transform .18s,border-color .18s,background .18s}
.db-badge:hover{transform:translateY(-3px);border-color:rgba(232,41,200,.4)}
.db-badge__ico{display:grid;place-items:center;width:46px;height:46px;margin:0 auto .6rem;
  border-radius:50%;font-size:1.1rem;color:var(--text-secondary);
  background:rgba(127,127,127,.14);border:1px solid var(--ui-line)}
.db-badge__name{display:block;font-size:.8rem;font-weight:800;color:var(--text-secondary);line-height:1.25}
.db-badge__sub{display:block;margin-top:.3rem;font-size:.66rem;color:var(--text-secondary);opacity:.8;line-height:1.3}
.db-badge__bar{display:block;height:3px;border-radius:999px;margin:.55rem .4rem 0;
  background:rgba(127,127,127,.25);overflow:hidden}
.db-badge__bar span{display:block;height:100%;background:linear-gradient(90deg,var(--ui-magenta),var(--ui-mint))}

/* Earned badges light up in their tier colour; locked ones stay muted on
   purpose, so the lit ones actually read as something achieved. */
.db-badge.is-earned .db-badge__name{color:var(--text)}
.db-badge.is-earned .db-badge__sub{color:var(--ui-mint);opacity:1;font-weight:700}
.db-badge--bronze.is-earned{border-color:rgba(217,139,74,.5);background:rgba(217,139,74,.08)}
.db-badge--bronze.is-earned .db-badge__ico{color:#0b0718;background:linear-gradient(145deg,#ffc083,#d98b4a);border-color:transparent}
.db-badge--silver.is-earned{border-color:rgba(215,226,232,.45);background:rgba(215,226,232,.07)}
.db-badge--silver.is-earned .db-badge__ico{color:#0b0718;background:linear-gradient(145deg,#fff,#c6d2da);border-color:transparent}
.db-badge--gold.is-earned{border-color:rgba(255,212,59,.55);background:rgba(255,212,59,.09)}
.db-badge--gold.is-earned .db-badge__ico{color:#0b0718;background:linear-gradient(145deg,#fff0a8,#ffd43b);border-color:transparent}
.db-badge--plat.is-earned{border-color:rgba(232,41,200,.55);background:rgba(232,41,200,.1)}
.db-badge--plat.is-earned .db-badge__ico{color:#fff;
  background:linear-gradient(145deg,var(--ui-violet),var(--ui-magenta));border-color:transparent;
  box-shadow:0 0 18px rgba(232,41,200,.45)}

.db-metric strong.fire{color:var(--sev-med)}

@media(max-width:860px){.db-ops{grid-template-columns:1fr}}
@media(max-width:520px){.db-badges__row{grid-template-columns:repeat(2,1fr)}}

/* ------------------------------------------------------- mobile navigation */
/* The academy nav had no collapse: it wrapped. Signed out that is a 144px
   sticky header on a 375px phone (18% of the screen); signed in the nav
   carries 13 items and it is worse, on every page. */
.ac-header__tools { display: flex; align-items: center; gap: .5rem; order: 2; }
.ac-navtoggle { display: none; }

@media (max-width: 860px) {
  /* wrap, NOT nowrap: the nav is flex-basis 100% and must be able to drop onto
     its own row. With nowrap it stayed on the brand's line and the open menu
     rendered on top of the logo. */
  body.academy .ac-header__inner { flex-wrap: wrap; gap: .6rem; }
  body.academy .brand { order: 1; flex: 1 1 auto; min-width: 0; }
  body.academy .brand__name { font-size: 1.05rem; }

  .ac-navtoggle {
    display: inline-grid; place-content: center; gap: 4px;
    width: 40px; height: 40px; padding: 0;
    border-radius: 10px; cursor: pointer;
    color: var(--ui-mint);
    background: color-mix(in srgb, var(--ui-mint) 12%, transparent);
    border: 1px solid color-mix(in srgb, var(--ui-mint) 42%, transparent);
  }
  .ac-navtoggle span {
    display: block; width: 18px; height: 2px; border-radius: 2px;
    background: currentColor; transition: transform .2s, opacity .2s;
  }
  .ac-navtoggle.is-open span:nth-child(1) { transform: translateY(6px) rotate(45deg); }
  .ac-navtoggle.is-open span:nth-child(2) { opacity: 0; }
  .ac-navtoggle.is-open span:nth-child(3) { transform: translateY(-6px) rotate(-45deg); }

  /* Only collapse when the script is there to reopen it — otherwise a
     no-JS visitor would be left with no navigation at all. */
  .has-acnav-js body.academy .ac-nav {
    order: 3;
    display: none;
    flex: 1 1 100%;
    flex-direction: column;
    align-items: stretch;
    justify-content: flex-start;
    gap: 0;
    margin-top: .6rem;
    padding-top: .4rem;
    border-top: 1px solid var(--ui-line);
    max-height: calc(100vh - 150px);
    overflow-y: auto;
  }
  .has-acnav-js body.academy .ac-nav.is-open { display: flex; }

  body.academy .ac-nav a {
    padding: .8rem .25rem;
    font-size: .95rem;
    border-bottom: 1px solid color-mix(in srgb, var(--ui-line) 60%, transparent);
  }
  /* The underline-on-hover flourish is a desktop affordance; as a full-width
     row it just draws a second line under every item. */
  body.academy .ac-nav a:not(.btn)::after { content: none; }
  body.academy .ac-nav a.btn { margin-top: .7rem; border-bottom: 0; text-align: center; }
  body.academy .ac-nav__user { padding: .8rem .25rem; }
}
