/* =========================================================================
   The "edge" theme — dark blue, sharp, high contrast. Applied site-wide via
   body.edge, which the layout sets on every page.

   4px radii instead of soft pills, hairline borders with a lit top edge, cut
   corners on the hero, and blue glow used as light rather than decoration.
   Fixed dark: it does not follow the OS theme.

   The token block below does two jobs. It defines this theme's own names
   (--panel, --line, --accent …) and it *remaps* the names app.css components
   use (--surface, --border, --brand …) onto this palette — that is what makes
   every component written for the light theme adopt the dark one instead of
   rendering pale boxes inside a dark page.
   ====================================================================== */

body.edge {
  --bg: #050912;
  --bg-2: #080E1B;
  --panel: #0B1424;
  --panel-2: #101B2E;
  --panel-3: #16233A;

  --line: rgba(148, 178, 226, 0.10);
  --line-2: rgba(148, 178, 226, 0.20);
  --lit: rgba(191, 216, 255, 0.16);

  --text: #EDF3FF;
  --text-2: #93A7C8;
  --text-3: #7C90B4;

  --accent: #3B82F6;
  --accent-2: #22D3EE;
  --accent-deep: #1E40AF;
  --glow: rgba(59, 130, 246, 0.40);
  --glow-soft: rgba(59, 130, 246, 0.16);

  --ok: #34D399;
  --bad: #FB7185;
  --warn: #FBBF24;

  --r: 4px;
  --r-lg: 6px;

  /* --- remap of the app.css token names onto this palette --- */
  --surface: var(--panel);
  --surface-2: var(--panel-2);
  --border: var(--line);
  --border-strong: var(--line-2);

  --brand: var(--accent);
  --brand-strong: var(--accent-2);
  --brand-ink: #03101F;
  --brand-tint: rgba(59, 130, 246, 0.14);
  --brand-tint-2: rgba(34, 211, 238, 0.12);

  --ok-tint: rgba(52, 211, 153, 0.11);
  --ok-border: rgba(52, 211, 153, 0.34);
  --bad-tint: rgba(251, 113, 133, 0.11);
  --bad-border: rgba(251, 113, 133, 0.34);
  --warn-tint: rgba(251, 191, 36, 0.11);

  --sh-1: 0 1px 2px rgba(0, 0, 0, 0.45);
  --sh-2: 0 1px 3px rgba(0, 0, 0, 0.5), 0 4px 14px rgba(0, 0, 0, 0.4);
  --sh-3: 0 2px 8px rgba(0, 0, 0, 0.55), 0 14px 34px rgba(0, 0, 0, 0.5);
  --sh-brand: 0 4px 18px -6px var(--glow);

  /* Sharp corners everywhere, not just on this theme's own components. */
  --r-sm: 4px;
  --r-md: 4px;
  --r-xl: 8px;

  color-scheme: dark;
  background: var(--bg);
  color: var(--text);
  /* A faint blueprint grid, plus two light sources bled in from the top. */
  background-image:
    linear-gradient(var(--line) 1px, transparent 1px),
    linear-gradient(90deg, var(--line) 1px, transparent 1px),
    radial-gradient(70% 42% at 12% -4%, rgba(59, 130, 246, 0.20) 0%, transparent 68%),
    radial-gradient(58% 38% at 96% 2%, rgba(34, 211, 238, 0.13) 0%, transparent 70%);
  background-size: 44px 44px, 44px 44px, 100% 100%, 100% 100%;
  background-attachment: fixed;
}

/* ------------------------------ chrome ------------------------------- */
body.edge .appbar {
  background: rgba(5, 9, 18, 0.72);
  border-bottom: 1px solid var(--line);
  box-shadow: 0 1px 0 var(--lit) inset;
}
body.edge .brand { color: var(--text); letter-spacing: 0.01em; }
body.edge .brand-mark {
  border-radius: var(--r);
  background: linear-gradient(150deg, var(--accent-2) 0%, var(--accent) 45%, var(--accent-deep) 100%);
  color: #04121F;
  box-shadow: 0 0 0 1px var(--line-2), 0 4px 18px var(--glow);
}
body.edge .icon-btn { color: var(--text-2); border-radius: var(--r); }
body.edge .icon-btn:active { background: var(--panel-2); }

body.edge .chip {
  border-radius: var(--r);
  background: var(--panel-2);
  border: 1px solid var(--line-2);
  color: var(--text-2);
  box-shadow: 0 1px 0 var(--lit) inset;
}

body.edge .tabbar {
  background: rgba(5, 9, 18, 0.86);
  border-top: 1px solid var(--line);
  box-shadow: 0 1px 0 var(--lit) inset;
}
body.edge .tab { color: var(--text-3); letter-spacing: 0.02em; }
body.edge .tab[aria-current="page"] { color: var(--text); }
/* A lit bar over the active tab, rather than a colour change alone. */
body.edge .tab[aria-current="page"]::before {
  content: "";
  position: absolute;
  top: 0;
  width: 34px;
  height: 2px;
  background: linear-gradient(90deg, var(--accent-2), var(--accent));
  box-shadow: 0 0 12px var(--glow);
}
body.edge .tab { position: relative; }
body.edge .tab:active { background: rgba(59, 130, 246, 0.08); }

/* ------------------------------ hero --------------------------------- */
.edge-hero {
  position: relative;
  overflow: hidden;
  padding: 22px 18px 20px;
  background:
    linear-gradient(158deg, var(--panel-2) 0%, var(--panel) 58%, var(--bg-2) 100%);
  border: 1px solid var(--line-2);
  border-radius: var(--r-lg);
  /* The cut corner is the signature: a bevel, not a rounded edge. */
  --bevel: 22px;
  clip-path: polygon(0 0, calc(100% - var(--bevel)) 0, 100% var(--bevel), 100% 100%, 0 100%);
}

/* Guests see no headline, so the hero collapses to its eyebrow and CTA. */
.edge-hero-slim { padding: 18px; }
.edge-hero-slim .edge-eyebrow { margin-bottom: 4px; }
.edge-hero-slim .edge-btn { margin-top: 14px; }

/*
 * The accent that fills the bevel. Same size as the cut and clipped to the
 * lower-left triangle, so its hypotenuse lands exactly on the cut edge — which
 * the clip-path strips of its border.
 */
.edge-hero::after {
  content: "";
  position: absolute;
  top: 0;
  right: 0;
  width: var(--bevel);
  height: var(--bevel);
  background: linear-gradient(225deg, var(--accent-2) 0%, var(--accent) 100%);
  clip-path: polygon(0 0, 100% 100%, 0 100%);
}

/* Light spilling in from the top-left, inside the clip. */
.edge-hero::before {
  content: "";
  position: absolute;
  inset: -40% 40% 40% -40%;
  background: radial-gradient(circle, var(--glow-soft) 0%, transparent 65%);
  pointer-events: none;
}

.edge-hero > * { position: relative; }

.edge-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  margin: 0 0 12px;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--accent-2);
}
.edge-eyebrow .bar {
  width: 18px;
  height: 1px;
  background: linear-gradient(90deg, var(--accent-2), transparent);
}

.edge-title {
  font-family: "Space Grotesk", "Plus Jakarta Sans", system-ui, sans-serif;
  font-size: clamp(27px, 8.2vw, 36px);
  font-weight: 700;
  line-height: 1.06;
  letter-spacing: -0.032em;
  margin: 0;
}
.edge-title em {
  font-style: normal;
  background: linear-gradient(100deg, var(--accent-2) 0%, var(--accent) 70%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.edge-sub {
  margin: 10px 0 0;
  color: var(--text-2);
  font-size: 14px;
  max-width: 30em;
}

/* ------------------------------ buttons ------------------------------ */
.edge-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  width: 100%;
  min-height: 52px;
  margin-top: 20px;
  padding: 0 20px;
  border: 0;
  border-radius: var(--r);
  font: inherit;
  font-size: 15.5px;
  font-weight: 700;
  letter-spacing: 0.005em;
  text-decoration: none;
  cursor: pointer;
  color: #03101F;
  background: linear-gradient(100deg, var(--accent-2) 0%, var(--accent) 58%, var(--accent-deep) 100%);
  box-shadow: 0 0 0 1px rgba(191, 216, 255, 0.22) inset, 0 6px 24px -6px var(--glow);
  transition: transform 120ms cubic-bezier(0.32, 0.72, 0, 1), box-shadow 160ms ease;
}
.edge-btn:active { transform: translateY(1px) scale(0.995); box-shadow: 0 0 0 1px rgba(191,216,255,0.22) inset; }
.edge-btn svg { width: 18px; height: 18px; }

/* ------------------------------ stats -------------------------------- */
.edge-stats { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1px; background: var(--line); border: 1px solid var(--line-2); border-radius: var(--r-lg); overflow: hidden; }
.edge-stat { position: relative; background: var(--panel); padding: 15px 8px 13px; text-align: center; }
.edge-stat::before {
  content: "";
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 1px;
  background: var(--lit);
}
.edge-stat-n {
  display: block;
  font-family: "Space Grotesk", "Plus Jakarta Sans", system-ui, sans-serif;
  font-size: 22px;
  font-weight: 700;
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
  line-height: 1.1;
}
.edge-stat-k {
  display: block;
  margin-top: 3px;
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--text-3);
}

/* ------------------------------ section head ------------------------- */
.edge-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; margin: 22px 2px 10px; }
.edge-head h2 {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--text-3);
}
.edge-head .count { font-size: 11px; font-weight: 700; color: var(--text-3); font-variant-numeric: tabular-nums; }

/* ------------------------------ subject cards ------------------------ */
.edge-subjects { display: grid; gap: 8px; }

.edge-subject {
  position: relative;
  display: flex;
  align-items: center;
  gap: 13px;
  min-height: 56px;
  padding: 7px 14px 7px 13px;
  background: linear-gradient(100deg, var(--panel) 0%, var(--bg-2) 100%);
  border: 1px solid var(--line);
  border-radius: var(--r);
  text-decoration: none;
  color: var(--text);
  overflow: hidden;
  transition: border-color 160ms ease, transform 120ms cubic-bezier(0.32, 0.72, 0, 1);
}
/* A lit spine on the leading edge — the row's accent, and its tap feedback. */
.edge-subject::before {
  content: "";
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 2px;
  background: linear-gradient(180deg, var(--accent-2), var(--accent));
  opacity: 0.55;
  transition: opacity 160ms ease;
}
.edge-subject:active { transform: scale(0.995); border-color: var(--line-2); }
.edge-subject:active::before { opacity: 1; }

.edge-subject-key {
  display: grid;
  place-items: center;
  width: 38px; height: 38px;
  flex: 0 0 auto;
  border-radius: var(--r);
  background: var(--panel-3);
  border: 1px solid var(--line-2);
  box-shadow: 0 1px 0 var(--lit) inset;
  font-family: "Space Grotesk", system-ui, sans-serif;
  font-size: 15px;
  font-weight: 700;
  color: var(--accent-2);
}

.edge-subject-body { flex: 1 1 auto; min-width: 0; }
.edge-subject-name { display: block; font-size: 15px; font-weight: 650; letter-spacing: -0.01em; }
.edge-subject-meta { display: block; margin-top: 2px; font-size: 11.5px; font-weight: 600; letter-spacing: 0.04em; color: var(--text-3); font-variant-numeric: tabular-nums; }
.edge-subject-go { flex: 0 0 auto; color: var(--text-3); }
.edge-subject-go svg { width: 17px; height: 17px; display: block; }


/* ------------------------------ panel (feed) ------------------------- */
.edge-panel {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: 16px;
  box-shadow: 0 1px 0 var(--lit) inset;
}
body.edge .pill { border-radius: var(--r); background: var(--panel-2); border-color: var(--line-2); }
body.edge .feed li { background: var(--panel-2); border-color: var(--line); border-radius: var(--r); }
body.edge .feed pre { background: var(--bg-2); border-color: var(--line); border-radius: var(--r); }
body.edge .btn-secondary { background: var(--panel-2); border-color: var(--line-2); color: var(--text); border-radius: var(--r); }
body.edge .empty { color: var(--text-3); }
body.edge code { background: var(--panel-2); border-color: var(--line); }

/*
 * Flash messages come from app.css, whose success/error tints are light-theme
 * values this theme does not redefine — left alone they render as a pale box in
 * the middle of a dark blue page.
 */
body.edge .toast {
  border-radius: var(--r);
  background: var(--panel);
  border-color: var(--line-2);
  color: var(--text);
  box-shadow: 0 1px 0 var(--lit) inset;
}
body.edge .toast-ok {
  color: var(--ok);
  background: rgba(52, 211, 153, 0.10);
  border-color: rgba(52, 211, 153, 0.34);
}
body.edge .toast-bad {
  color: var(--bad);
  background: rgba(251, 113, 133, 0.10);
  border-color: rgba(251, 113, 133, 0.34);
}


@media (min-width: 600px) {
  .edge-subjects { grid-template-columns: 1fr 1fr; }
  .edge-hero { padding: 28px 24px 24px; }
  .edge-stat-n { font-size: 26px; }
}

/* =========================================================================
   Fit-to-viewport. The dashboard is a fixed-height app screen, not a document:
   nothing scrolls, and the subject rows absorb whatever space is left over.
   ====================================================================== */
body.edge.fit {
  height: 100vh;
  height: 100dvh;          /* dvh so a mobile URL bar appearing cannot cause a scroll */
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

body.edge.fit .appbar { flex: 0 0 auto; }

body.edge.fit main {
  flex: 1 1 auto;
  min-height: 0;           /* lets the flex children actually shrink */
  display: flex;
  flex-direction: column;
  gap: clamp(8px, 1.15vh, 12px);
  padding: clamp(9px, 1.4vh, 16px) 14px clamp(9px, 1.4vh, 14px);
  overflow: hidden;
}

/* Everything is fixed-size except the lists, which take the remainder. */
body.edge.fit main > * { flex: 0 0 auto; }

body.edge.fit .edge-hero-slim { padding: clamp(10px, 1.7vh, 18px) 16px; }
body.edge.fit .edge-btn { min-height: clamp(44px, 6vh, 54px); margin-top: clamp(9px, 1.4vh, 14px); }
body.edge.fit .edge-stat { padding: clamp(9px, 1.5vh, 15px) 8px clamp(8px, 1.3vh, 13px); }
body.edge.fit .edge-stat-n { font-size: clamp(18px, 2.7vh, 24px); }
body.edge.fit .edge-head { margin: clamp(2px, 0.5vh, 6px) 2px clamp(1px, 0.3vh, 4px); }

body.edge.fit .edge-subjects {
  /* Must be flex, not the grid it is by default: grid items ignore the flex
     sizing below, which let the list overflow and collide with the note. */
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  min-height: 0;
  gap: clamp(5px, 1.3vh, 13px);
  /*
   * Rows stop shrinking at the 44px touch-target floor. On a screen too short
   * to hold five of them, the list scrolls inside itself — the page still does
   * not scroll, and the note below can never be drawn over a row.
   */
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  justify-content: flex-start;
}

/* Share out spare height, shrink when tight, but never past the touch target —
   and never stretch far beyond the content either, or the extra height reads as
   padding on the card. */
body.edge.fit .edge-subject {
  flex: 1 1 auto;
  min-height: 44px;
  max-height: 54px;
  padding-block: 4px;
}
body.edge.fit .edge-subject-key {
  width: clamp(30px, 4.4vh, 38px);
  height: clamp(30px, 4.4vh, 38px);
  font-size: clamp(13px, 1.9vh, 15px);
}
body.edge.fit .edge-subject-name { font-size: clamp(13.5px, 1.95vh, 15px); }
body.edge.fit .edge-subject-meta { font-size: clamp(10px, 1.45vh, 11.5px); }

/* The feed panel scrolls inside itself, so the page still never scrolls. */
body.edge.fit .edge-panel {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding: clamp(10px, 1.6vh, 16px);
}


/* Flash messages must not push the screen out of its own height. */
body.edge.fit .toast { flex: 0 0 auto; margin: 8px 14px 0; padding: 9px 12px; font-size: 13px; }

/*
 * Compact tier. A 360x640 phone reports a viewport nearer 550px once browser UI
 * is counted, and five rows plus the hero, stats and note do not fit in that.
 * The note is the one piece that is supplementary, so it goes first, and the
 * fixed blocks tighten — which buys enough room for all five subjects.
 */
@media (max-height: 700px) {
  body.edge.fit main { gap: 7px; padding: 8px 12px; }
  body.edge.fit .edge-hero-slim { padding: 9px 14px; }
  body.edge.fit .edge-eyebrow { margin-bottom: 2px; font-size: 10px; }
  body.edge.fit .edge-btn { min-height: 44px; margin-top: 8px; }
  body.edge.fit .edge-stat { padding: 8px 6px 7px; }
  body.edge.fit .edge-stat-n { font-size: 18px; }
  body.edge.fit .edge-stat-k { font-size: 9px; letter-spacing: 0.1em; }
  body.edge.fit .edge-subject { min-height: 44px; max-height: 50px; padding-block: 3px; }
  body.edge.fit .edge-subjects { gap: 5px; }

  /* Measured: the list needs 240px here and was being given 203px. These trims
     free the 37px difference so all five subjects clear the tab bar. The
     "Subjects" label goes because the rows are self-evident without it. */
  body.edge.fit .edge-head { display: none; }
  body.edge.fit main { gap: 6px; padding: 6px 12px; }
  body.edge.fit .edge-eyebrow { line-height: 1.2; margin-bottom: 0; }
  body.edge.fit .edge-btn { min-height: 42px; margin-top: 7px; }
  body.edge.fit .edge-stat { padding: 6px 6px 5px; }
  body.edge.fit .edge-stat-n { font-size: 17px; }
}

/*
 * Very short screens (a 360x600 phone reports about 513px). The stats strip is
 * the redundant piece here — every subject row already carries its own unit and
 * MCQ counts — so dropping it keeps all five rows at a full 44px target.
 */
@media (max-height: 545px) {
  body.edge.fit .edge-stats { display: none; }
}

/*
 * Landscape, or anything shorter still: the content genuinely cannot fit at any
 * sensible size. Scrolling back is better than clipping it away.
 */
@media (max-height: 450px) {
  body.edge.fit {
    height: auto;
    min-height: 100dvh;
    overflow: visible;
    display: block;
  }
  body.edge.fit main { display: flex; overflow: visible; padding: 12px 12px 22px; }
  body.edge.fit .edge-subject { flex: 0 0 auto; min-height: 52px; }
  body.edge.fit .edge-subjects { overflow: visible; }
  body.edge.fit .edge-panel { overflow: visible; }
}

/* =========================================================================
   Attempt history
   ====================================================================== */
/*
 * Five figures across a phone leaves neighbouring labels almost touching. The
 * dashboard's stats strip solves the same problem with hairline dividers, so
 * this reuses that treatment rather than shrinking the type further.
 */
.att-figures {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 1px;
  /* --line is too faint to separate five cramped cells; --line-2 reads. */
  background: var(--line-2);
  border: 1px solid var(--line-2);
  border-radius: var(--r);
  overflow: hidden;
}
/* Darker than the panel around them, so the 1px separators actually read —
   with cells the same colour as their container the dividers were invisible. */
.att-fig { position: relative; text-align: center; background: var(--bg-2); padding: 11px 3px 10px; }
.att-fig::before {
  content: "";
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 1px;
  background: var(--lit);
}
.att-n {
  display: block;
  font-family: "Space Grotesk", "Plus Jakarta Sans", system-ui, sans-serif;
  font-size: clamp(15px, 4.6vw, 20px);
  font-weight: 700;
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
}
.att-n.att-ok { color: var(--ok); }
.att-n.att-bad { color: var(--bad); }
.att-k {
  display: block;
  margin-top: 3px;
  /* Five labels across a 320px phone: nowrap at a fixed size made neighbouring
     labels touch, so the type scales with the viewport instead. */
  font-size: clamp(7px, 2.15vw, 9px);
  font-weight: 700;
  letter-spacing: 0.04em;
  line-height: 1.15;
  text-transform: uppercase;
  color: var(--text-3);
}

.att-track { margin-top: 14px; height: 3px; background: var(--line); border-radius: 2px; overflow: hidden; }
.att-track span {
  display: block;
  height: 100%;
  width: 0;
  background: linear-gradient(90deg, var(--accent), var(--accent-2));
  transition: width 300ms cubic-bezier(0.32, 0.72, 0, 1);
}
@media (prefers-reduced-motion: reduce) { .att-track span { transition: none; } }

.att-tools { display: flex; align-items: center; gap: 10px; margin: 14px 0 10px; }
.att-filters { display: flex; gap: 5px; }

.att-chip {
  min-height: 36px;
  padding: 0 13px;
  border: 1px solid var(--line);
  border-radius: var(--r);
  background: var(--panel);
  color: var(--text-2);
  font: inherit;
  font-size: 12.5px;
  font-weight: 700;
  letter-spacing: 0.02em;
  cursor: pointer;
}
.att-chip.is-on {
  color: var(--text);
  border-color: rgba(59, 130, 246, 0.5);
  background: rgba(59, 130, 246, 0.14);
}


.att-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 7px; }

.att-item {
  position: relative;
  display: flex;
  gap: 11px;
  padding: 12px 13px 12px 14px;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--r);
}
/* Verdict shows as a lit spine as well as the mark, so it reads at a glance. */
.att-item::before { content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 2px; }
.att-item.is-right::before { background: var(--ok); }
.att-item.is-wrong::before { background: var(--bad); }

.att-mark {
  display: grid;
  place-items: center;
  width: 24px; height: 24px;
  flex: 0 0 auto;
  margin-top: 1px;
  border-radius: var(--r);
}
.att-mark svg { width: 14px; height: 14px; }
.att-item.is-right .att-mark { background: rgba(52, 211, 153, 0.14); color: var(--ok); }
.att-item.is-wrong .att-mark { background: rgba(251, 113, 133, 0.14); color: var(--bad); }

.att-body { min-width: 0; }
.att-stem { margin: 0; font-size: 14px; font-weight: 600; line-height: 1.42; letter-spacing: -0.008em; }
.att-answer { margin: 6px 0 0; display: grid; gap: 1px; }
.att-answer-k {
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-3);
}
/* The right answer always reads as the right answer, however it was attempted. */
.att-answer-t { font-size: 13.5px; font-weight: 650; line-height: 1.4; color: var(--ok); }
.att-where { margin: 3px 0 0; font-size: 11px; font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase; color: var(--text-3); }

.att-none { padding: 18px 14px; text-align: center; color: var(--text-3); font-size: 13px; border: 1px dashed var(--line-2); border-radius: var(--r); }

.att-foot { margin: 16px 2px 0; font-size: 11.5px; line-height: 1.5; color: var(--text-3); text-align: center; }

/* --- wordmark (edge) --------------------------------------------------- */
body.edge .brand { gap: 0; }
/* With no icon beside it the wordmark needs its own breathing room. */
body.edge .appbar { padding-left: 15px; }
body.edge .brand-word {
  font-family: "Space Grotesk", "Plus Jakarta Sans", system-ui, sans-serif;
  font-size: 18px;
  font-weight: 700;
  letter-spacing: -0.025em;
  color: var(--text);
}
body.edge .brand-tld {
  background: linear-gradient(100deg, var(--accent-2) 0%, var(--accent) 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

/* --- install steps sheet (edge) --------------------------------------- */
body.edge .sheet { background: rgba(3, 6, 12, 0.66); }
body.edge .sheet-card {
  background: var(--panel);
  border-color: var(--line-2);
  border-radius: var(--r-lg);
  box-shadow: 0 1px 0 var(--lit) inset, 0 -8px 40px rgba(0, 0, 0, 0.55);
}
body.edge .sheet-note { color: var(--text-3); }
body.edge .sheet-close {
  border-radius: var(--r);
  color: #03101F;
  background: linear-gradient(100deg, var(--accent-2) 0%, var(--accent) 58%, var(--accent-deep) 100%);
  box-shadow: 0 0 0 1px rgba(191, 216, 255, 0.22) inset;
}

/* A unit whose questions have all been attempted on this device. */
.edge-subject.is-done { opacity: 0.62; }
.edge-subject.is-done::before { opacity: 0.25; }
.edge-subject.is-done .edge-subject-key { color: var(--text-3); }

/* =========================================================================
   Components inherited from app.css, brought into the theme's language.
   The token remap above already recolours them; these rules match the shapes.
   ====================================================================== */

/* One primary-button ramp across the whole site — the dashboard CTA's. */
body.edge .btn-primary,
body.edge .sheet-close {
  background: linear-gradient(100deg, var(--accent-2) 0%, var(--accent) 58%, var(--accent-deep) 100%);
  color: #03101F;
  box-shadow: 0 0 0 1px rgba(191, 216, 255, 0.22) inset, 0 6px 24px -6px var(--glow);
}
body.edge .btn-primary:active { box-shadow: 0 0 0 1px rgba(191, 216, 255, 0.22) inset; }

body.edge .card,
body.edge .panel {
  box-shadow: 0 1px 0 var(--lit) inset;
}

/* Answer options get the same lit top edge as the theme's cards. */
body.edge .option {
  border-width: 1px;
  box-shadow: 0 1px 0 var(--lit) inset;
}
body.edge .option-key { box-shadow: none; }
body.edge .option.is-correct,
body.edge .option.is-wrong { box-shadow: none; }

body.edge .quiz-progress { background: var(--line); }
body.edge .stem { letter-spacing: -0.014em; }
body.edge .solution { background: var(--bg-2); border-left-color: var(--accent); }

/* Figures use the display face wherever they appear. */
body.edge .stat-n,
body.edge .result-pct,
body.edge .counter {
  font-family: "Space Grotesk", "Plus Jakarta Sans", system-ui, sans-serif;
}

body.edge .crumbs a { color: var(--text-3); }
body.edge .crumbs strong { color: var(--text); }
body.edge .input { box-shadow: 0 1px 0 var(--lit) inset; }
body.edge .input:focus { box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.18); }
body.edge .foot { color: var(--text-3); }

/* --- attempt pager ---------------------------------------------------- */
.att-pager {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  margin: 14px 0 2px;
}
.att-page {
  display: grid;
  place-items: center;
  width: 44px;
  height: 40px;
  border: 1px solid var(--line-2);
  border-radius: var(--r);
  background: var(--panel);
  color: var(--text-2);
  box-shadow: 0 1px 0 var(--lit) inset;
  cursor: pointer;
}
.att-page svg { width: 18px; height: 18px; }
.att-page:active:not(:disabled) { background: var(--panel-2); }
.att-page:disabled { opacity: 0.35; cursor: default; }
.att-page-of {
  min-width: 56px;
  text-align: center;
  font-family: "Space Grotesk", "Plus Jakarta Sans", system-ui, sans-serif;
  font-size: 13px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--text-2);
}
