/* ==========================================================================
   GOCOURSE AI — Design system
   Exact tokens from the original design, mapped onto Bootstrap 5.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Tokens
   -------------------------------------------------------------------------- */
:root {
  --bg: #F8FAFC;
  --bg2: #FFFFFF;
  --surface: #FFFFFF;
  --surface2: #F1F5F9;
  --sunken: #F8FAFC;
  --border: #E2E8F0;
  --border2: #CBD5E1;
  --text: #0F172A;
  --text2: #475569;
  --text3: #94A3B8;
  --brand: #2563EB;
  --brand2: #1D4ED8;
  --brand3: #3B82F6;
  --brandsoft: #EFF6FF;
  --brandline: #BFDBFE;
  --ai: #7C3AED;
  --aisoft: #F5F3FF;
  --ailine: #DDD6FE;
  --ok: #16A34A;
  --oksoft: #F0FDF4;
  --warn: #F59E0B;
  --warnsoft: #FFFBEB;
  --err: #DC2626;
  --errsoft: #FEF2F2;
  --shadow: 0 1px 2px rgba(15, 23, 42, .06), 0 1px 3px rgba(15, 23, 42, .04);
  --shadow2: 0 4px 6px -1px rgba(15, 23, 42, .07), 0 2px 4px -2px rgba(15, 23, 42, .05);
  --shadow3: 0 20px 40px -12px rgba(15, 23, 42, .18);
  --navbg: rgba(255, 255, 255, .85);

  --t-blue: #EFF6FF;      --t-blue-fg: #2563EB;
  --t-green: #F0FDF4;     --t-green-fg: #16A34A;
  --t-amber: #FFFBEB;     --t-amber-fg: #B45309;
  --t-red: #FEF2F2;       --t-red-fg: #DC2626;
  --t-purple: #F5F3FF;    --t-purple-fg: #7C3AED;
  --t-cyan: #ECFEFF;      --t-cyan-fg: #0891B2;
  --t-orange: #FFF7ED;    --t-orange-fg: #EA580C;
  --t-slate: #F1F5F9;     --t-slate-fg: #334155;

  /* Fixed dark-surface colours used by code panels in both themes */
  --code-bg: #0B1120;
  --code-bg2: #0F172A;
  --code-bg3: #111827;
  --code-line: #1E293B;
  --code-line2: #334155;
  --code-fg: #E2E8F0;
  --code-dim: #64748B;
  --code-dim2: #475569;
  --code-green: #4ADE80;
  --code-purple: #A78BFA;
  --code-blue: #60A5FA;
  --code-red: #FCA5A5;
  --code-amber: #FBBF24;

  --sans: 'Plus Jakarta Sans', system-ui, -apple-system, sans-serif;
  --mono: 'JetBrains Mono', ui-monospace, monospace;

  --header-h: 101px; /* 60px nav + 40px tech bar + 1px border */
}

html[data-theme="dark"] {
  --bg: #0B1120;
  --bg2: #0F172A;
  --surface: #111827;
  --surface2: #172033;
  --sunken: #0B1120;
  --border: #1E293B;
  --border2: #334155;
  --text: #F1F5F9;
  --text2: #94A3B8;
  --text3: #64748B;
  --brand: #3B82F6;
  --brand2: #60A5FA;
  --brand3: #60A5FA;
  --brandsoft: rgba(37, 99, 235, .14);
  --brandline: rgba(59, 130, 246, .32);
  --ai: #A78BFA;
  --aisoft: rgba(124, 58, 237, .16);
  --ailine: rgba(167, 139, 250, .32);
  --ok: #22C55E;
  --oksoft: rgba(22, 163, 74, .14);
  --warn: #FBBF24;
  --warnsoft: rgba(245, 158, 11, .14);
  --err: #F87171;
  --errsoft: rgba(220, 38, 38, .16);
  --shadow: 0 1px 2px rgba(0, 0, 0, .4);
  --shadow2: 0 4px 10px -2px rgba(0, 0, 0, .5);
  --shadow3: 0 24px 48px -16px rgba(0, 0, 0, .7);
  --navbg: rgba(15, 23, 42, .85);

  --t-blue: rgba(59, 130, 246, .14);   --t-blue-fg: #60A5FA;
  --t-green: rgba(34, 197, 94, .14);   --t-green-fg: #4ADE80;
  --t-amber: rgba(245, 158, 11, .14);  --t-amber-fg: #FBBF24;
  --t-red: rgba(248, 113, 113, .14);   --t-red-fg: #F87171;
  --t-purple: rgba(167, 139, 250, .16);--t-purple-fg: #A78BFA;
  --t-cyan: rgba(34, 211, 238, .14);   --t-cyan-fg: #22D3EE;
  --t-orange: rgba(251, 146, 60, .14); --t-orange-fg: #FB923C;
  --t-slate: rgba(148, 163, 184, .14); --t-slate-fg: #CBD5E1;
}

/* --------------------------------------------------------------------------
   2. Bootstrap variable bridge
   -------------------------------------------------------------------------- */
:root {
  --bs-body-bg: var(--bg);
  --bs-body-color: var(--text);
  --bs-body-font-family: var(--sans);
  --bs-border-color: var(--border);
  --bs-primary: var(--brand);
  --bs-link-color: var(--brand);
  --bs-link-hover-color: var(--brand2);
  --bs-font-monospace: var(--mono);
  --bs-border-radius: 9px;
}

/* --------------------------------------------------------------------------
   3. Base
   -------------------------------------------------------------------------- */
* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--sans);
  -webkit-font-smoothing: antialiased;
}

a { color: var(--brand); text-decoration: none; }
a:hover { color: var(--brand2); }
::selection { background: var(--brandline); color: var(--text); }
button { font-family: inherit; }
:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
img { max-width: 100%; }

/* Scrollbars — transparent track, slim themed thumb, everywhere.
   The thumb is drawn inside a transparent border via background-clip, which
   is what gives it the inset pill shape instead of a full-width slab.
   scrollbar-color inherits, so setting it on html covers every scroller. */
html { scrollbar-width: thin; scrollbar-color: var(--border2) transparent; }
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track, ::-webkit-scrollbar-corner { background: transparent; }
::-webkit-scrollbar-thumb {
  border: 3px solid transparent; border-radius: 99px;
  background: var(--border2); background-clip: content-box;
}
::-webkit-scrollbar-thumb:hover { background: var(--text3); background-clip: content-box; }

/* horizontal scrollers with hidden scrollbar */
.sx { scrollbar-width: none; -ms-overflow-style: none; }
.sx::-webkit-scrollbar { height: 0; width: 0; }

/* --------------------------------------------------------------------------
   4. Animations
   -------------------------------------------------------------------------- */
@keyframes blink { 0%, 49% { opacity: 1; } 50%, 100% { opacity: 0; } }
@keyframes rise { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
@keyframes slidein { from { opacity: 0; transform: translateX(24px); } to { opacity: 1; transform: none; } }
@keyframes pulsering {
  0%   { box-shadow: 0 0 0 0 rgba(59, 130, 246, .35); }
  70%  { box-shadow: 0 0 0 10px rgba(59, 130, 246, 0); }
  100% { box-shadow: 0 0 0 0 rgba(59, 130, 246, 0); }
}
@keyframes shimmer { 0% { background-position: -400px 0; } 100% { background-position: 400px 0; } }
@media (prefers-reduced-motion: reduce) { * { animation: none !important; transition: none !important; } }

.anim-rise { animation: rise .25s ease-out; }
.caret {
  display: inline-block; width: 7px; height: 13px; margin-left: 3px;
  vertical-align: -2px; background: var(--code-purple);
  animation: blink 1s steps(1) infinite;
}

/* --------------------------------------------------------------------------
   5. Typography scale (exact sizes from the design)
   -------------------------------------------------------------------------- */
.t-hero      { font: 800 56px/1.06 var(--sans); letter-spacing: -.035em; color: var(--text); text-wrap: balance; margin: 0; }
.t-page      { font: 800 40px/1.05 var(--sans); letter-spacing: -.035em; color: var(--text); margin: 0; }
.t-h1        { font: 800 30px/1.1 var(--sans);  letter-spacing: -.03em;  color: var(--text); margin: 0; }
.t-h1-sm     { font: 800 28px/1.1 var(--sans);  letter-spacing: -.03em;  color: var(--text); margin: 0; }
.t-h2        { font: 800 32px/1.15 var(--sans); letter-spacing: -.03em;  color: var(--text); margin: 0; }
.t-h2-alt    { font: 800 34px/1.15 var(--sans); letter-spacing: -.035em; color: var(--text); margin: 0; }
.t-h3        { font: 700 24px/1.3 var(--sans);  letter-spacing: -.02em;  color: var(--text); margin: 0; }
.t-h4        { font: 700 19px/1 var(--sans);    letter-spacing: -.02em;  color: var(--text); margin: 0; }
.t-h5        { font: 700 17px/1 var(--sans);    color: var(--text); margin: 0; }
.t-h6        { font: 700 16px/1 var(--sans);    color: var(--text); margin: 0; }
.t-lead      { font: 400 17px/1.65 var(--sans); color: var(--text2); text-wrap: pretty; margin: 0; }
.t-sub       { font: 400 15.5px/1.6 var(--sans); color: var(--text2); margin: 0; }
.t-sub-sm    { font: 400 15px/1.45 var(--sans); color: var(--text2); margin: 0; }
.t-body      { font: 400 16px/1.75 var(--sans); color: var(--text2); text-wrap: pretty; margin: 0; }
.t-body-sm   { font: 400 14.5px/1.6 var(--sans); color: var(--text2); margin: 0; }
.t-meta      { font: 500 12.5px/1 var(--sans);  color: var(--text3); }
.t-mono      { font-family: var(--mono); }

.eyebrow {
  font: 700 11.5px/1 var(--sans); color: var(--text3);
  letter-spacing: .08em; text-transform: uppercase;
}
.eyebrow-sm {
  font: 700 10.5px/1 var(--sans); color: var(--text3); letter-spacing: .09em;
}

/* --------------------------------------------------------------------------
   6. Layout shells
   -------------------------------------------------------------------------- */
/* Wide row gutters. Bootstrap gives a .row negative side margins of half the
   gutter, so the gutter must never exceed twice the shell padding or the row
   escapes the container and the page scrolls sideways. These scale down in
   step with .shell's padding at each breakpoint. */
.row-x56 { --bs-gutter-x: 56px; }
.row-x48 { --bs-gutter-x: 48px; }
.row-x32 { --bs-gutter-x: 32px; }

.shell     { max-width: 1400px; margin: 0 auto; padding-inline: 40px; }
.shell-wide{ max-width: 1600px; margin: 0 auto; padding-inline: 24px; }
.shell-narrow { max-width: 1100px; margin: 0 auto; padding-inline: 40px; }
.section   { padding-top: 44px; }
.section-lg{ padding-top: 56px; }

/* --------------------------------------------------------------------------
   7. Header / navigation
   -------------------------------------------------------------------------- */
/* Space held for the chrome while it is still being drawn.

   The header and footer arrive as empty elements and app.js fills them at the
   foot of the page, so the document painted at zero height for both and then
   jumped as each was populated — the header pushing everything down, the
   footer changing the scroll height under the reader.

   `:empty` is what makes this safe: the reservation applies only while the
   element has no children, and stops applying the instant app.js writes into
   it. The real height is never constrained, so a header that grows or a
   footer with an extra column is unaffected. The figures below are the sum of
   what each one renders — navbar 60 + its border + tech bar 40 + its border. */
#gc-header:empty { display: block; min-height: 102px; }
#gc-footer:empty { display: block; min-height: 430px; }

.gc-header {
  position: sticky; top: 0; z-index: 40;
  backdrop-filter: blur(12px);
  background: var(--navbg);
  border-bottom: 1px solid var(--border);
}
.gc-navbar {
  display: flex; align-items: center; gap: 22px;
  height: 60px; padding: 0 24px; max-width: 1600px; margin: 0 auto; min-width: 0;
}
.gc-brand {
  display: flex; align-items: center; gap: 9px;
  background: none; border: 0; padding: 0; cursor: pointer; flex: none;
}
.gc-brand-logo { display: block; height: 32px; width: auto; flex: none; }
.gc-brand-mark {
  display: grid; place-items: center; width: 28px; height: 28px; border-radius: 7px;
  background: linear-gradient(140deg, #2563EB, #1D4ED8);
  color: #fff; font: 800 14px/1 var(--sans);
}
.gc-brand-text { font: 800 16px/1 var(--sans); color: var(--text); letter-spacing: -.02em; white-space: nowrap; }
.gc-brand-text span { color: var(--brand); }

.gc-nav { display: flex; align-items: center; gap: 2px; flex: 1 1 auto; min-width: 0; overflow-x: auto; }
.gc-nav-link {
  display: flex; align-items: center; gap: 7px; height: 34px; padding: 0 11px;
  border: 0; border-radius: 7px; background: none;
  font: 600 13.5px/1 var(--sans); color: var(--text2);
  cursor: pointer; white-space: nowrap; transition: background .15s, color .15s;
}
.gc-nav-link:hover { background: var(--surface2); color: var(--text); }
.gc-nav-link.active, .gc-nav-link[aria-current="page"] { color: var(--brand); }

.gc-actions { flex: none; display: flex; justify-content: flex-end; align-items: center; gap: 10px; }
.gc-kbd {
  flex: none; font: 600 11px/1 var(--mono); border: 1px solid var(--border);
  border-radius: 4px; padding: 3px 5px; color: var(--text3);
}
.gc-icon-btn {
  position: relative; display: grid; place-items: center;
  width: 34px; height: 34px; flex: none;
  border: 1px solid var(--border); border-radius: 8px;
  background: var(--surface); color: var(--text2); cursor: pointer;
}
.gc-icon-btn:hover { color: var(--text); }
.gc-dot {
  position: absolute; top: 6px; right: 7px; width: 6px; height: 6px;
  border-radius: 50%; background: var(--brand);
}
.gc-avatar {
  display: grid; place-items: center; width: 34px; height: 34px; flex: none;
  border-radius: 50%; background: linear-gradient(140deg, #3B82F6, #7C3AED);
  color: #fff; border: 0; font: 700 12px/1 var(--sans); cursor: pointer;
  overflow: hidden; padding: 0;
}
/* A GOCOSYS avatar photo fills the circle; without one the initials show
   through on the gradient behind. */
.gc-avatar img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* The signed-out counterpart to the avatar. Sized to sit level with the icon
   buttons beside it rather than towering over them.
   Qualified with .btn-gc deliberately: that rule is defined further down the
   file, so a lone .gc-signin would lose the height on source order. */
.btn-gc.gc-signin {
  height: 30px; padding: 0 12px; border-radius: 8px;
  font: 600 12.5px/1 var(--sans); text-decoration: none; box-shadow: none;
}
.gc-menu {
  position: absolute; top: 42px; right: 0; z-index: 60; width: 210px; padding: 6px;
  border: 1px solid var(--border); border-radius: 11px; background: var(--surface);
  box-shadow: var(--shadow3); animation: rise .14s ease-out;
}
.gc-menu-head { padding: 10px 10px 12px; border-bottom: 1px solid var(--border); margin-bottom: 6px; }
.gc-menu-item {
  display: flex; align-items: center; gap: 10px; width: 100%; text-align: left;
  padding: 9px 10px; border: 0; border-radius: 7px; background: none;
  font: 600 13px/1 var(--sans); color: var(--text2); cursor: pointer;
}
.gc-menu-item:hover { background: var(--surface2); color: var(--text); }

/* Sign out is the one entry here that undoes something, so it reads as such.
   The hover keeps the danger colour rather than falling back to --text, which
   is what the rule above would otherwise do to it. */
.gc-menu-item.is-danger { color: var(--err); }
.gc-menu-item.is-danger:hover { background: var(--errsoft); color: var(--err); }

/* notification popover */
.gc-notif-panel { width: 340px; padding: 0; overflow: hidden; }
.gc-notif-head {
  display: flex; align-items: center; gap: 8px; padding: 12px 14px;
  border-bottom: 1px solid var(--border);
}
.gc-notif-count {
  padding: 3px 8px; border-radius: 99px; background: var(--brandsoft);
  font: 700 10.5px/1 var(--sans); color: var(--brand); letter-spacing: .03em;
}
.gc-notif-clear {
  margin-left: auto; border: 0; background: none; padding: 0; cursor: pointer;
  font: 600 11.5px/1 var(--sans); color: var(--text3);
}
.gc-notif-clear:hover { color: var(--brand); }
.gc-notif-list { max-height: min(380px, 60vh); overflow-y: auto; overscroll-behavior: contain; }
.gc-notif-item {
  display: flex; gap: 11px; padding: 12px 14px; text-decoration: none;
  border-bottom: 1px solid var(--border);
}
.gc-notif-item:hover { background: var(--surface2); }
.gc-notif-item.is-unread { background: var(--brandsoft); }
.gc-notif-item.is-unread:hover { background: var(--brandsoft); filter: brightness(.98); }
.gc-notif-mark {
  display: grid; place-items: center; width: 30px; height: 30px; flex: none;
  border-radius: 9px; font: 800 11px/1 var(--sans);
}
.gc-notif-title { display: block; font: 700 13px/1.35 var(--sans); color: var(--text); }
.gc-notif-body  { display: block; margin-top: 3px; font: 400 12.5px/1.5 var(--sans); color: var(--text2); }
.gc-notif-when  { display: block; margin-top: 5px; font: 500 11px/1 var(--sans); color: var(--text3); }
.gc-notif-empty { padding: 26px 14px; text-align: center; font: 500 13px/1 var(--sans); color: var(--text3); }
.gc-notif-foot {
  display: block; padding: 11px 14px; text-align: center;
  font: 700 12px/1 var(--sans); color: var(--brand); background: var(--sunken);
}
.gc-notif-foot:hover { background: var(--surface2); }

.gc-techbar-wrap { border-top: 1px solid var(--border); background: var(--bg2); }
.gc-techbar-inner { position: relative; max-width: 1600px; margin: 0 auto; }
.gc-techbar {
  display: flex; align-items: center; gap: 4px; height: 40px;
  padding: 0 24px; overflow-x: auto; scroll-behavior: smooth;
  scroll-padding-left: 42px; scroll-padding-right: 42px;
}
/* edge fades — sit under the arrows so chips dissolve instead of being clipped */
.gc-techbar-inner::before,
.gc-techbar-inner::after {
  content: ''; position: absolute; top: 0; bottom: 0; width: 64px; z-index: 2;
  pointer-events: none; opacity: 0; transition: opacity .18s ease;
}
.gc-techbar-inner::before { left: 0; background: linear-gradient(90deg, var(--bg2) 30%, transparent); }
.gc-techbar-inner::after { right: 0; background: linear-gradient(270deg, var(--bg2) 30%, transparent); }
.gc-techbar-inner.can-prev::before,
.gc-techbar-inner.can-next::after { opacity: 1; }

.gc-techbar-arrow {
  position: absolute; top: 50%; z-index: 3; transform: translateY(-50%);
  display: grid; place-items: center; width: 26px; height: 26px; padding: 0;
  border: 1px solid var(--border); border-radius: 50%;
  background: var(--surface); color: var(--text2);
  box-shadow: var(--shadow2); cursor: pointer;
  opacity: 0; visibility: hidden; transition: opacity .18s ease, color .15s, border-color .15s, background .15s;
}
.gc-techbar-arrow.show { opacity: 1; visibility: visible; }
.gc-techbar-arrow:hover { background: var(--surface2); border-color: var(--brand); color: var(--brand); }
.gc-techbar-arrow:active { transform: translateY(-50%) scale(.94); }
.gc-techbar-arrow:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
.gc-techbar-arrow svg { display: block; }
.gc-techbar-arrow.prev { left: 6px; }
.gc-techbar-arrow.next { right: 6px; }
.gc-tech-link {
  display: flex; align-items: center; gap: 7px; height: 28px; padding: 0 9px;
  border: 1px solid transparent; border-radius: 6px; background: none;
  font: 600 12.5px/1 var(--sans); color: var(--text2);
  white-space: nowrap; cursor: pointer; transition: .15s;
}
.gc-tech-link:hover { background: var(--surface2); }
.gc-tech-link.active { color: var(--brand); }
.gc-tech-link img { display: block; flex: none; }

/* mobile nav toggle — hidden on desktop */
.gc-burger { display: none; }

/* --------------------------------------------------------------------------
   8. Buttons
   -------------------------------------------------------------------------- */
.btn-gc {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  height: 44px; padding: 0 22px; border-radius: 9px;
  border: 1px solid var(--brand); background: var(--brand); color: #fff;
  font: 700 14.5px/1 var(--sans); cursor: pointer;
  box-shadow: var(--shadow2); transition: .15s; white-space: nowrap;
}
.btn-gc:hover { background: var(--brand2); border-color: var(--brand2); color: #fff; }

.btn-gc-outline {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  height: 44px; padding: 0 20px; border-radius: 9px;
  border: 1px solid var(--border2); background: var(--surface); color: var(--text);
  font: 600 14.5px/1 var(--sans); cursor: pointer; transition: .15s; white-space: nowrap;
}
.btn-gc-outline:hover { background: var(--surface2); color: var(--text); }

.btn-gc-ai {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  height: 44px; padding: 0 16px; border-radius: 9px;
  border: 1px dashed var(--ailine); background: none; color: var(--ai);
  font: 600 14.5px/1 var(--sans); cursor: pointer; white-space: nowrap;
}
.btn-gc-ai:hover { background: var(--aisoft); color: var(--ai); }

.btn-solid-ai {
  display: inline-flex; align-items: center; justify-content: center; gap: 9px;
  height: 44px; padding: 0 22px; border: 0; border-radius: 9px;
  background: var(--ai); color: #fff; font: 700 14.5px/1 var(--sans); cursor: pointer;
}
.btn-solid-ai:hover { color: #fff; filter: brightness(1.05); }

.btn-solid-ok {
  display: inline-flex; align-items: center; justify-content: center; gap: 9px;
  height: 44px; padding: 0 22px; border: 0; border-radius: 9px;
  background: var(--ok); color: #fff; font: 700 14.5px/1 var(--sans); cursor: pointer;
}
.btn-solid-ok:hover { color: #fff; filter: brightness(1.05); }

.btn-solid-warn {
  display: inline-flex; align-items: center; justify-content: center; gap: 9px;
  height: 44px; padding: 0 22px; border: 0; border-radius: 9px;
  background: var(--warn); color: #0F172A; font: 700 14.5px/1 var(--sans); cursor: pointer;
}
.btn-solid-warn:hover { color: #0F172A; filter: brightness(1.05); }

/* small variants */
.btn-sm-solid {
  height: 32px; padding: 0 14px; border: 0; border-radius: 8px;
  background: var(--brand); color: #fff; font: 700 12.5px/1 var(--sans); cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center; white-space: nowrap;
}
.btn-sm-solid:hover { color: #fff; background: var(--brand2); }

.btn-sm-ghost {
  height: 32px; padding: 0 13px; border: 1px solid var(--border); border-radius: 8px;
  background: var(--surface); color: var(--text2); font: 600 12.5px/1 var(--sans);
  cursor: pointer; display: inline-flex; align-items: center; justify-content: center; white-space: nowrap;
}
.btn-sm-ghost:hover { color: var(--text); }

.btn-sm-ai {
  height: 32px; padding: 0 12px; border: 1px solid var(--ailine); border-radius: 8px;
  background: var(--aisoft); color: var(--ai); font: 700 12.5px/1 var(--sans);
  cursor: pointer; display: inline-flex; align-items: center; justify-content: center; white-space: nowrap;
}

/* The actions stacked inside the right rail's AI card. The class was already
   in use — tutorial.js has drawn three of these since the rail was written —
   but nothing ever styled it, so they came out as default browser buttons.
   Full width and left-aligned, because they read as a list of choices rather
   than a row of controls. */
.tool-btn {
  display: flex; align-items: center; width: 100%; min-height: 32px;
  padding: 8px 12px; border: 1px solid var(--ailine); border-radius: 8px;
  background: var(--aisoft); color: var(--ai);
  font: 600 12.5px/1.35 var(--sans); text-align: left; text-decoration: none;
  cursor: pointer; transition: background .15s, border-color .15s;
}
.tool-btn:hover { background: var(--surface2); border-color: var(--ai); color: var(--ai); }

.btn-xs {
  height: 29px; padding: 0 11px; border: 1px solid var(--border); border-radius: 7px;
  background: var(--surface); color: var(--text2); font: 600 11.5px/1 var(--sans);
  cursor: pointer; display: inline-flex; align-items: center; justify-content: center; white-space: nowrap;
}
.btn-xs:hover { color: var(--text); }
.btn-xs-brand { border-color: var(--brandline); background: var(--brandsoft); color: var(--brand); }
.btn-xs-danger { color: var(--err); }
.btn-xs-danger:hover { background: var(--errsoft); color: var(--err); }
.btn-xs-ok { border-color: var(--oksoft); background: var(--oksoft); color: var(--ok); }

.btn-link-brand {
  border: 0; background: none; color: var(--brand);
  font: 600 13px/1 var(--sans); cursor: pointer; padding: 0;
}

/* --------------------------------------------------------------------------
   9. Cards & surfaces
   -------------------------------------------------------------------------- */
.card-gc {
  border: 1px solid var(--border); border-radius: 12px;
  background: var(--surface); box-shadow: var(--shadow);
}
.card-gc-lg { border-radius: 14px; padding: 28px; }
.card-gc-pad { padding: 24px; border-radius: 13px; }
.card-flat { border: 1px solid var(--border); border-radius: 12px; background: var(--surface); }
.card-sunken { border: 1px solid var(--border); border-radius: 10px; background: var(--sunken); }

.hover-lift { transition: .16s; }
.hover-lift:hover { border-color: var(--brandline); box-shadow: var(--shadow2); transform: translateY(-2px); }
.hover-brand { transition: .15s; }
.hover-brand:hover { border-color: var(--brandline); background: var(--brandsoft); }
.hover-line:hover { border-color: var(--brandline); }
.hover-row:hover { background: var(--surface2); }

.ai-card { border: 1px solid var(--ailine); border-radius: 14px; background: var(--aisoft); }

/* --------------------------------------------------------------------------
   10. Badges, pills, chips
   -------------------------------------------------------------------------- */
.pill {
  display: inline-flex; align-items: center; gap: 8px; height: 26px; padding: 0 10px;
  border-radius: 99px; font: 700 11px/1 var(--sans); letter-spacing: .06em;
}
.pill-ai     { border: 1px solid var(--ailine); background: var(--aisoft); color: var(--ai); }
.pill-ok     { background: var(--oksoft); color: var(--ok); letter-spacing: .07em; padding: 0 11px; }
.pill-warn   { background: var(--warnsoft); color: var(--warn); letter-spacing: .07em; padding: 0 11px; }
.pill-ai-soft{ background: var(--aisoft); color: var(--ai); letter-spacing: .07em; padding: 0 11px; }
.pill-dot { width: 5px; height: 5px; border-radius: 50%; background: currentColor; }

/* hero search bar — types inline, hands the query to the search palette */
.hero-search {
  display: flex; align-items: center; gap: 11px; max-width: 520px;
  height: 54px; padding: 0 8px 0 16px;
  border: 1px solid var(--border); border-radius: 13px; background: var(--surface);
  box-shadow: var(--shadow2); transition: border-color .15s, box-shadow .15s;
}
.hero-search:focus-within { border-color: var(--brand); box-shadow: 0 0 0 3px var(--brandsoft); }
.hero-search input {
  flex: 1; min-width: 0; height: 100%; border: 0; outline: 0; background: none;
  font: 500 14.5px/1 var(--sans); color: var(--text);
}
.hero-search input::placeholder { color: var(--text3); font-weight: 400; }
.hero-search input::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; }
.hero-search .btn-gc { height: 38px; padding: 0 16px; font-size: 13.5px; flex: none; }

.hero-tags {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px; max-width: 520px;
  margin-top: 14px; font: 500 12.5px/1 var(--sans); color: var(--text3);
}
.hero-tags a {
  padding: 5px 11px; border: 1px solid var(--border); border-radius: 99px;
  background: var(--surface); font: 600 12px/1 var(--sans); color: var(--text2);
  transition: color .15s, border-color .15s, background .15s;
}
.hero-tags a:hover { color: var(--brand); border-color: var(--brandline); background: var(--brandsoft); }

/* live results dropdown under the hero bar (htmx swaps into #hero-results) */
.hero-search-wrap { position: relative; max-width: 520px; z-index: 5; }
.hero-results {
  position: absolute; left: 0; right: 0; top: calc(100% + 8px);
  /* Scrolls internally rather than running off the bottom of the hero. */
  max-height: min(340px, 52vh); overflow-y: auto; overscroll-behavior: contain;
  padding: 6px;
  border: 1px solid var(--border); border-radius: 12px;
  background: var(--surface); box-shadow: var(--shadow3);
}
/* the bar dims very slightly while a request is in flight */
.hero-search.htmx-request { border-color: var(--brandline); }

/* floating language marks around the hero panel */
.float-logos { position: absolute; inset: 0; pointer-events: none; }
.float-logo {
  position: absolute; display: grid; place-items: center;
  width: 46px; height: 46px; border-radius: 13px;
  border: 1px solid var(--border); background: var(--surface);
  box-shadow: var(--shadow2);
  animation: float-y 7s ease-in-out infinite;
}
.float-logo img { display: block; }
/* Staggered so they never bob in lockstep. Outward offsets stay inside the
   shell's side padding — the hero clips overflow, so anything further out is
   cut off at the window edge on narrower screens. */
.float-logo-a { top: -26px;    left: -16px;   animation-duration: 7s;   animation-delay: -0.4s; }
.float-logo-b { top: 44px;     right: -16px;  animation-duration: 8.5s; animation-delay: -2.1s; }
.float-logo-c { bottom: 110px; left: -16px;   animation-duration: 9.5s; animation-delay: -3.6s; }
.float-logo-d { bottom: -18px; right: -16px;  animation-duration: 8s;   animation-delay: -1.2s; }
.float-logo-e { top: -34px;    right: 88px;   animation-duration: 10s;  animation-delay: -5s; }

/* Past the shell's max width there is room outside it again, so let them drift
   further from the panel. */
@media (min-width: 1440px) {
  .float-logo-a { left: -34px; }
  .float-logo-b { right: -34px; }
  .float-logo-c { left: -44px; }
  .float-logo-d { right: -28px; }
}

@keyframes float-y {
  0%, 100% { transform: translateY(0) rotate(0deg); }
  50%      { transform: translateY(-14px) rotate(-2.5deg); }
}

.tag {
  display: inline-block; padding: 4px 8px; border-radius: 5px;
  font: 700 10px/1 var(--sans); letter-spacing: .05em;
}
.tag-lg { padding: 4px 9px; font-size: 10.5px; letter-spacing: 0; }
.chip {
  display: inline-flex; align-items: center; padding: 5px 9px;
  border: 1px solid var(--border); border-radius: 6px; background: var(--surface);
  font: 600 11.5px/1 var(--sans); color: var(--text2);
}
.chip-filter {
  height: 32px; padding: 0 13px; border: 1px solid var(--border); border-radius: 99px;
  background: var(--surface); color: var(--text2); font: 600 12.5px/1 var(--sans);
  white-space: nowrap; cursor: pointer; display: inline-flex; align-items: center;
}
.chip-filter.active { border-color: var(--brand); background: var(--brand); color: #fff; }

.status-live {
  display: inline-flex; align-items: center; gap: 8px; padding: 7px 12px;
  border: 1px solid var(--border); border-radius: 99px; background: var(--surface);
  font: 600 12px/1 var(--sans); color: var(--text2); white-space: nowrap;
}
.status-live .led { width: 6px; height: 6px; border-radius: 50%; background: var(--ok); }

.logo-tile {
  display: grid; place-items: center; width: 34px; height: 34px;
  border-radius: 9px; flex: none;
}
.logo-tile-sm { width: 26px; height: 26px; border-radius: 7px; }
.logo-tile-md { width: 36px; height: 36px; border-radius: 9px; }
.logo-tile-lg { width: 52px; height: 52px; border-radius: 13px; }

.ai-mark {
  display: grid; place-items: center; width: 26px; height: 26px; border-radius: 7px;
  background: linear-gradient(140deg, #7C3AED, #4F46E5);
  color: #fff; font: 800 10px/1 var(--sans); flex: none;
}
.ai-mark-sm { width: 22px; height: 22px; border-radius: 6px; font-size: 9.5px; }
.ai-mark-lg { width: 30px; height: 30px; border-radius: 9px; font-size: 11px; }

.avatar-initials {
  display: grid; place-items: center; width: 24px; height: 24px; border-radius: 50%;
  background: var(--surface2); font: 700 9.5px/1 var(--sans); color: var(--text2); flex: none;
}
.avatar-grad {
  display: grid; place-items: center; width: 34px; height: 34px; border-radius: 50%;
  background: linear-gradient(140deg, #3B82F6, #7C3AED);
  color: #fff; font: 700 12px/1 var(--sans); flex: none;
}

.check-dot {
  display: grid; place-items: center; width: 19px; height: 19px; flex: none;
  margin-top: 2px; border-radius: 50%; font: 700 11px/1 var(--sans);
}
.check-ok { background: var(--oksoft); color: var(--ok); }
.check-ai { background: var(--aisoft); color: var(--ai); }
.check-warn { background: var(--warnsoft); color: var(--warn); }

/* --------------------------------------------------------------------------
   11. Progress bars
   -------------------------------------------------------------------------- */
.bar { height: 4px; border-radius: 99px; background: var(--border); overflow: hidden; }
.bar > i { display: block; height: 100%; border-radius: 99px; background: var(--brand); }
.bar-5 { height: 5px; }
.bar-ai > i { background: var(--ai); transition: width .3s; }

/* --------------------------------------------------------------------------
   12. Code panels (fixed dark in both themes)
   -------------------------------------------------------------------------- */
.code-panel {
  border: 1px solid var(--border); border-radius: 14px; background: var(--code-bg);
  box-shadow: var(--shadow3); overflow: hidden; min-width: 0;
}
.code-panel-sm { border-radius: 11px; box-shadow: none; }
.code-bar {
  display: flex; align-items: center; gap: 10px; height: 40px; padding: 0 14px;
  border-bottom: 1px solid var(--code-line); background: var(--code-bg2);
}
.code-bar-sm { height: 38px; padding: 0 12px; }
.code-dots { display: flex; gap: 6px; flex: none; }
.code-dots i { width: 9px; height: 9px; border-radius: 50%; background: var(--code-line2); display: block; }
.code-file { font: 500 11.5px/1 var(--mono); color: var(--code-dim); }
.code-ready {
  margin-left: auto; display: inline-flex; align-items: center; gap: 5px;
  font: 700 10px/1 var(--sans); color: var(--code-green);
}
.code-ready i { width: 5px; height: 5px; border-radius: 50%; background: var(--code-green); display: block; }

.code-body { display: flex; }
.code-lines {
  padding: 16px 0 16px 14px; font: 400 13px/1.75 var(--mono);
  color: var(--code-line2); text-align: right; user-select: none; white-space: pre; flex: none;
}
.code-pre {
  margin: 0; padding: 16px 16px 16px 14px; font: 400 13px/1.75 var(--mono);
  color: var(--code-fg); overflow: auto; flex: 1; min-width: 0;
}
.code-pre-lg { font-size: 13.5px; line-height: 1.8; }
.code-lines-lg { font-size: 13.5px; line-height: 1.8; }

.code-out {
  display: flex; align-items: flex-start; gap: 10px;
  border-top: 1px solid var(--code-line); padding: 11px 16px;
}
.code-out .lbl { font: 700 10px/1.6 var(--sans); color: var(--code-dim2); letter-spacing: .08em; flex: none; }
.code-out pre { margin: 0; white-space: pre-wrap; font: 400 12.5px/1.6 var(--mono); color: var(--code-green); }

.code-btn {
  height: 26px; padding: 0 10px; border: 1px solid var(--code-line); border-radius: 6px;
  background: var(--code-bg3); color: #94A3B8; font: 600 11.5px/1 var(--sans); cursor: pointer;
}
.code-btn:hover { color: var(--code-fg); }
.code-btn-ai {
  border-color: rgba(167, 139, 250, .35); background: rgba(124, 58, 237, .16);
  color: var(--code-purple); font-weight: 700;
}

.inline-code {
  font: 500 12.5px/1 var(--mono); background: var(--surface2);
  padding: 2px 5px; border-radius: 4px;
}

/* --------------------------------------------------------------------------
   13. Forms
   -------------------------------------------------------------------------- */
.field-label { display: block; font: 600 12.5px/1 var(--sans); color: var(--text2); }
.field {
  width: 100%; height: 44px; padding: 0 14px;
  border: 1px solid var(--border); border-radius: 9px;
  background: var(--surface); color: var(--text);
  font: 500 14px/1 var(--sans); outline: none;
}
.field:focus { border-color: var(--brand); box-shadow: 0 0 0 3px var(--brandsoft); }
.field-sm { height: 38px; padding: 0 12px; border-radius: 8px; font-size: 13px; }
.field-mono { font-family: var(--mono); }
.select-gc {
  width: 100%; height: 36px; padding: 0 10px;
  border: 1px solid var(--border); border-radius: 8px;
  background: var(--surface); color: var(--text);
  font: 600 12.5px/1 var(--sans); cursor: pointer; outline: none;
}
.select-gc-lg { height: 38px; }

.search-inline {
  display: flex; align-items: center; gap: 9px; height: 36px;
  padding: 0 12px; border: 1px solid var(--border); border-radius: 9px; background: var(--surface);
}
.search-inline input {
  flex: 1; min-width: 0; border: 0; outline: 0; background: none;
  font: 500 13px/1 var(--sans); color: var(--text);
}

/* toggle switch */
.switch {
  width: 42px; height: 24px; flex: none; border: 0; border-radius: 99px;
  background: var(--border2); position: relative; cursor: pointer; padding: 0;
}
.switch > span {
  position: absolute; top: 3px; left: 3px; width: 18px; height: 18px;
  border-radius: 50%; background: #fff; transition: left .16s;
}
.switch[aria-pressed="true"] { background: var(--brand); }
.switch[aria-pressed="true"] > span { left: 21px; }
.switch-static {
  width: 38px; height: 22px; border-radius: 99px; background: var(--brand);
  position: relative; display: inline-block; flex: none;
}
.switch-static > span {
  position: absolute; top: 3px; right: 3px; width: 16px; height: 16px;
  border-radius: 50%; background: #fff;
}

/* --------------------------------------------------------------------------
   14. Tables (admin)
   -------------------------------------------------------------------------- */
.tbl { border: 1px solid var(--border); border-radius: 12px; background: var(--surface); overflow: hidden; }
.tbl-head {
  padding: 11px 18px; border-bottom: 1px solid var(--border); background: var(--sunken);
  font: 700 10.5px/1 var(--sans); color: var(--text3); letter-spacing: .08em;
}
.tbl-row { align-items: center; padding: 13px 18px; border-bottom: 1px solid var(--border); }
.tbl-row:last-child { border-bottom: 0; }
.tbl-row:hover { background: var(--surface2); }
.tbl-scroll { overflow-x: auto; }

/* --------------------------------------------------------------------------
   15. Modals (search + AI)
   -------------------------------------------------------------------------- */
.gc-overlay {
  position: fixed; inset: 0; z-index: 1090;
  background: rgba(2, 6, 23, .62); backdrop-filter: blur(4px);
  display: flex; align-items: center; justify-content: center; padding: 5vh 20px;
}
.gc-overlay[hidden] { display: none; }
.gc-overlay-top {
  align-items: flex-start; justify-content: center; padding: 12vh 16px 20px;
  background: rgba(2, 6, 23, .55); backdrop-filter: blur(3px);
}

.gc-dialog {
  width: min(780px, 100%); max-height: 88vh; display: flex; flex-direction: column;
  border: 1px solid var(--border); border-radius: 16px; background: var(--surface);
  box-shadow: var(--shadow3); overflow: hidden; animation: rise .18s ease-out;
}
.gc-dialog-search { width: min(720px, 100%); max-height: 70vh; border-radius: 14px; }

.gc-dialog-head {
  display: flex; align-items: center; gap: 12px; padding: 0 20px;
  height: 64px; border-bottom: 1px solid var(--border); flex: none;
}
.gc-dialog-foot {
  display: flex; flex-wrap: wrap; align-items: center; gap: 7px;
  padding: 14px 20px; border-top: 1px solid var(--border); background: var(--bg2); flex: none;
}
.gc-close {
  display: grid; place-items: center; width: 32px; height: 32px; flex: none;
  border: 1px solid var(--border); border-radius: 50%; background: var(--surface2);
  color: var(--text2); font: 600 13px/1 var(--sans); cursor: pointer;
}
.gc-close:hover { color: var(--text); }

.search-result {
  display: flex; align-items: center; gap: 12px; width: 100%; text-align: left;
  padding: 10px; border: 0; border-radius: 8px; background: none; cursor: pointer;
}
.search-result:hover { background: var(--surface2); }
.search-kind {
  display: grid; place-items: center; width: 26px; height: 26px; flex: none;
  border-radius: 7px; background: var(--surface2); color: var(--text2);
  font: 700 10.5px/1 var(--mono);
}

.ai-analysing {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 16px; padding: 44px 0;
}
.ai-ring { width: 46px; height: 46px; border-radius: 50%; background: var(--ai); animation: pulsering 1.4s ease-out infinite; }

/* --------------------------------------------------------------------------
   16. Toast
   -------------------------------------------------------------------------- */
.gc-toast {
  position: fixed; left: 50%; bottom: 28px; transform: translateX(-50%); z-index: 1080;
  display: flex; align-items: center; gap: 10px; padding: 12px 18px;
  border: 1px solid var(--border); border-radius: 10px; background: var(--surface);
  box-shadow: var(--shadow3); animation: rise .18s ease-out;
  font: 600 13px/1 var(--sans); color: var(--text);
}
.gc-toast[hidden] { display: none; }
.gc-toast .led { width: 7px; height: 7px; border-radius: 50%; background: var(--ok); }

/* --------------------------------------------------------------------------
   17. Footer
   -------------------------------------------------------------------------- */
.gc-footer { border-top: 1px solid var(--border); background: var(--bg2); }
.gc-footer-head { font: 700 12px/1 var(--sans); color: var(--text); letter-spacing: .06em; text-transform: uppercase; }
.gc-footer a { font: 500 13px/1.2 var(--sans); color: var(--text2); }
.gc-footer a:hover { color: var(--brand); }

/* newsletter band */
.gc-news {
  display: grid; grid-template-columns: 1fr minmax(320px, 460px); align-items: center; gap: 32px;
  margin: 0 0 34px; padding: 26px 30px; border: 1px solid var(--brandline); border-radius: 14px;
  background: linear-gradient(120deg, var(--brandsoft), var(--aisoft));
}
.gc-news h3 { margin: 0; font: 800 20px/1.25 var(--sans); letter-spacing: -.02em; color: var(--text); }
.gc-news p  { margin: 7px 0 0; font: 400 13.5px/1.6 var(--sans); color: var(--text2); }
.gc-news-form { display: flex; gap: 8px; flex-wrap: wrap; }
.gc-news-input {
  flex: 1 1 200px; min-width: 0; height: 42px; padding: 0 14px;
  border: 1px solid var(--border); border-radius: 10px; background: var(--surface);
  font: 500 13.5px/1 var(--sans); color: var(--text); outline: none;
  transition: border-color .15s, box-shadow .15s;
}
.gc-news-input::placeholder { color: var(--text3); font-weight: 400; }
.gc-news-input:focus { border-color: var(--brand); box-shadow: 0 0 0 3px var(--brandsoft); }
.gc-news-note { margin: 9px 0 0; font: 400 11.5px/1.5 var(--sans); color: var(--text3); }
.gc-news-done { grid-template-columns: 1fr; border-color: var(--ok); }
.gc-news-check {
  display: grid; place-items: center; width: 38px; height: 38px; flex: none;
  border-radius: 50%; background: var(--oksoft); color: var(--ok);
}
.gc-news.htmx-request .gc-news-input { opacity: .6; }
/* htmx swaps the "Load more" button out while the next page is in flight */
#study-more.htmx-request button { opacity: .55; pointer-events: none; }

/* brand + link columns */
.gc-footer-top {
  display: grid; grid-template-columns: minmax(220px, 1fr) 3.1fr; gap: 48px;
  padding-top: 44px; padding-bottom: 38px;
}
.gc-footer-logo { display: block; height: 32px; width: auto; }
.gc-footer-tag  { margin: 14px 0 0; font: 600 13px/1 var(--sans); color: var(--text3); letter-spacing: .02em; }
.gc-footer-note { margin: 11px 0 0; max-width: 34ch; font: 400 12.5px/1.7 var(--sans); color: var(--text3); }
.gc-footer-cols { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 30px 20px; }
.gc-footer-links { display: flex; flex-direction: column; gap: 9px; margin-top: 14px; }
.gc-footer-links a { width: fit-content; transition: color .15s, transform .15s; }
.gc-footer-links a:hover { transform: translateX(2px); }

.gc-social { display: flex; gap: 8px; margin-top: 18px; }
.gc-social a {
  display: grid; place-items: center; width: 32px; height: 32px; flex: none;
  border: 1px solid var(--border); border-radius: 9px; background: var(--surface); color: var(--text3);
  transition: color .15s, border-color .15s, background .15s, transform .15s;
}
.gc-social a:hover {
  color: var(--brand); border-color: var(--brandline); background: var(--brandsoft); transform: translateY(-1px);
}

.gc-footer-bottom {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 14px;
  padding-top: 18px; padding-bottom: 30px;
  border-top: 1px solid var(--border); font: 500 12.5px/1.5 var(--sans); color: var(--text3);
}
.gc-footer-legal { display: flex; flex-wrap: wrap; align-items: center; gap: 20px; }
.gc-footer-legal a { font-size: 12.5px; color: var(--text3); }

/* --------------------------------------------------------------------------
   18. Placeholder image blocks
   -------------------------------------------------------------------------- */
.img-ph {
  display: grid; place-items: center; position: relative;
  background: repeating-linear-gradient(135deg, var(--surface2), var(--surface2) 10px, var(--sunken) 10px, var(--sunken) 20px);
  border-bottom: 1px solid var(--border);
}
.img-ph .note {
  padding: 5px 10px; border: 1px dashed var(--border2); border-radius: 6px;
  background: var(--surface); font: 600 11px/1 var(--sans); color: var(--text3);
}
.dropzone {
  width: 100%; border: 1.5px dashed var(--border2); border-radius: 12px;
  background: var(--surface); cursor: pointer; transition: .15s;
}
.dropzone:hover { border-color: var(--brand); background: var(--brandsoft); }

/* --------------------------------------------------------------------------
   19. Tutorial page shell
   -------------------------------------------------------------------------- */
/* The lesson rail is sized to the longest lesson name in any track
   ("Implementation Process", 200px of button) plus its own padding. Going
   below ~230px starts wrapping those labels. */
.tut-grid {
  display: grid; grid-template-columns: 232px minmax(0, 1fr) 268px;
  max-width: 1600px; margin: 0 auto; align-items: start;
}
.tut-aside-l {
  position: sticky; top: var(--header-h); height: calc(100vh - var(--header-h));
  overflow: auto; padding: 24px 14px; border-right: 1px solid var(--border);
}
.tut-aside-r {
  position: sticky; top: var(--header-h); height: calc(100vh - var(--header-h));
  overflow: auto; padding: 36px 24px 40px; border-left: 1px solid var(--border);
}
/* Both rails keep their scrollbar out of sight until you point at them: two
   bars framing the article read as clutter, but the lesson list runs well past
   the fold and needs the affordance once you are in it.
   The gutter is reserved either way and only the thumb's colour changes —
   hiding the bar itself would hand its width back to the content and reflow
   every lesson label as the pointer crossed the edge. */
.tut-aside-l, .tut-aside-r { scrollbar-width: thin; scrollbar-color: transparent transparent; }
.tut-aside-l:hover, .tut-aside-r:hover { scrollbar-color: var(--border2) transparent; }

.tut-aside-l::-webkit-scrollbar-thumb, .tut-aside-r::-webkit-scrollbar-thumb {
  background: transparent; transition: background .15s;
}
.tut-aside-l:hover::-webkit-scrollbar-thumb, .tut-aside-r:hover::-webkit-scrollbar-thumb {
  background: var(--border2); background-clip: content-box;
}
.tut-aside-l:hover::-webkit-scrollbar-thumb:hover,
.tut-aside-r:hover::-webkit-scrollbar-thumb:hover {
  background: var(--text3); background-clip: content-box;
}
.tut-main { padding: 36px 48px 80px; min-width: 0; }
.lesson-link {
  display: flex; align-items: center; gap: 9px; text-align: left; width: 100%;
  padding: 8px 10px; border: 0; border-radius: 7px; background: none;
  font: 600 13.5px/1.3 var(--sans); color: var(--text2); cursor: pointer;
}
.lesson-link:hover { background: var(--surface2); }
.lesson-link.active { background: var(--brandsoft); color: var(--brand); }
/* Named `lesson-mark`, not `mark`: Bootstrap ships a `.mark` highlight utility
   whose pale-yellow background was painting a stray swatch behind the empty
   not-started marks. */
.lesson-link .lesson-mark { width: 15px; height: 15px; flex: none; color: var(--text3); }
.lesson-link .lesson-mark.is-done { color: var(--ok); }

.callout {
  padding: 18px 20px; border: 1px solid var(--border); border-left: 3px solid var(--brand);
  border-radius: 10px; background: var(--surface);
}
.callout-ai {
  padding: 16px 18px; border: 1px solid var(--ailine); border-left: 3px solid var(--ai);
  border-radius: 10px; background: var(--aisoft);
}
.callout-brand {
  padding: 16px 18px; border: 1px solid var(--brandline);
  border-radius: 10px; background: var(--brandsoft);
}

.toc-list {
  display: flex; flex-direction: column; gap: 9px;
  padding-left: 11px; border-left: 2px solid var(--border);
}
.toc-list a { font: 500 13px/1.3 var(--sans); color: var(--text2); }
.toc-list a:hover { color: var(--brand); }

.quiz-opt {
  display: flex; align-items: center; gap: 11px; text-align: left; width: 100%;
  padding: 12px 14px; border: 1px solid var(--border); border-radius: 9px;
  background: var(--surface); font: 500 14px/1.4 var(--sans); color: var(--text);
  cursor: pointer; transition: .14s;
}
.quiz-opt:hover { border-color: var(--brandline); }
.quiz-opt .key {
  display: grid; place-items: center; width: 20px; height: 20px; flex: none;
  border: 1px solid var(--border2); border-radius: 5px;
  font: 700 10.5px/1 var(--mono); color: var(--text3);
}
.quiz-opt.correct { border-color: var(--ok); background: var(--oksoft); }
.quiz-opt.wrong   { border-color: var(--err); background: var(--errsoft); }

.pager-btn {
  padding: 14px 18px; border: 1px solid var(--border); border-radius: 10px;
  background: var(--surface); cursor: pointer; text-align: left;
}
.pager-btn:hover { border-color: var(--brandline); }
.pager-next { border-color: var(--brandline); background: var(--brandsoft); text-align: right; }

/* --------------------------------------------------------------------------
   20. Compiler
   -------------------------------------------------------------------------- */
.ide {
  display: grid; grid-template-columns: 210px minmax(0, 1.45fr) minmax(0, 1fr);
  height: calc(100vh - 195px); min-height: 520px;
  border: 1px solid var(--border); border-radius: 12px;
  overflow: hidden; box-shadow: var(--shadow2);
}
.ide-explorer { background: var(--surface); border-right: 1px solid var(--border); padding: 14px 10px; overflow: auto; }
.ide-file {
  display: flex; align-items: center; gap: 8px; text-align: left; width: 100%;
  padding: 7px 8px 7px 20px; border: 0; border-radius: 6px; background: none;
  font: 500 12.5px/1 var(--mono); color: var(--text2); cursor: pointer;
}
.ide-file:hover { background: var(--surface2); }
.ide-file.active { background: var(--brandsoft); color: var(--brand); }
.ide-editor { display: flex; flex-direction: column; background: var(--code-bg); min-width: 0; }
.ide-tabs {
  display: flex; align-items: center; height: 36px; flex: none;
  border-bottom: 1px solid var(--code-line); background: var(--code-bg2); overflow-x: auto;
}
.ide-tab {
  height: 36px; display: flex; align-items: center; padding: 0 16px;
  font: 500 12px/1 var(--mono); color: var(--code-dim2); white-space: nowrap;
}
.ide-tab.active { border-right: 1px solid var(--code-line); background: var(--code-bg); color: var(--code-fg); }
.ide-code-wrap { flex: 1; display: flex; overflow: auto; position: relative; }
.ide-code-area { position: relative; flex: 1; min-width: 0; }
.ide-code-area pre {
  margin: 0; padding: 16px; font: 400 13.5px/1.7 var(--mono);
  white-space: pre-wrap; word-break: break-word; color: var(--code-fg); pointer-events: none;
}
.ide-code-area textarea {
  position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; padding: 16px;
  border: 0; outline: 0; resize: none; background: transparent; color: transparent;
  caret-color: var(--code-blue); font: 400 13.5px/1.7 var(--mono);
  white-space: pre-wrap; word-break: break-word; overflow: hidden;
}
.ide-status {
  display: flex; align-items: center; gap: 14px; height: 30px; padding: 0 14px; flex: none;
  border-top: 1px solid var(--code-line); background: var(--code-bg2);
  font: 500 11px/1 var(--mono); color: var(--code-dim2); overflow-x: auto;
}
.ide-term { display: flex; flex-direction: column; background: var(--code-bg); border-left: 1px solid var(--code-line); min-width: 0; }
.ide-term-head {
  display: flex; align-items: center; gap: 8px; height: 36px; padding: 0 14px; flex: none;
  border-bottom: 1px solid var(--code-line); background: var(--code-bg2);
}
.ide-term-body { flex: 1; overflow: auto; padding: 14px; font: 400 12.5px/1.85 var(--mono); }
.ide-error { border-top: 1px solid rgba(220, 38, 38, .35); background: rgba(220, 38, 38, .10); padding: 14px; flex: none; }

/* --------------------------------------------------------------------------
   21. Admin console
   -------------------------------------------------------------------------- */
.admin-grid { display: grid; grid-template-columns: 238px minmax(0, 1fr); min-height: 100vh; background: var(--bg); }
.admin-aside {
  display: flex; flex-direction: column; border-right: 1px solid var(--border);
  background: var(--bg2); position: sticky; top: 0; height: 100vh;
}
.admin-brand {
  display: flex; align-items: center; gap: 10px; height: 60px; padding: 0 18px; flex: none;
  border-bottom: 1px solid var(--border);
}
.admin-nav { flex: 1; overflow: auto; padding: 16px 10px; }
.admin-nav-item {
  display: flex; align-items: center; gap: 10px; width: 100%; text-align: left;
  padding: 9px 10px; border: 0; border-radius: 8px; background: transparent;
  font: 600 13px/1 var(--sans); color: var(--text2); cursor: pointer;
}
.admin-nav-item:hover { background: var(--surface2); }
.admin-nav-item.active { background: var(--brandsoft); color: var(--brand); }
.admin-nav-item .badge-n { font: 700 10.5px/1 var(--mono); color: var(--text3); }
.admin-topbar {
  position: sticky; top: 0; z-index: 20; display: flex; align-items: center; gap: 14px;
  height: 60px; padding: 0 26px; border-bottom: 1px solid var(--border);
  background: var(--navbg); backdrop-filter: blur(12px);
}
.admin-body { flex: 1; padding: 26px; min-width: 0; }
.pipeline-step {
  min-width: 130px; padding: 13px; border: 1px solid var(--border);
  border-radius: 9px; background: var(--sunken);
}

/* --------------------------------------------------------------------------
   22. Charts
   -------------------------------------------------------------------------- */
/* --------------------------------------------------------------------------
   Profile page
   -------------------------------------------------------------------------- */
.profile-cover {
  height: 104px;
  background: linear-gradient(120deg, var(--brandsoft), var(--aisoft) 60%, var(--oksoft));
  border-bottom: 1px solid var(--border);
}
.profile-head {
  display: flex; align-items: flex-end; gap: 20px; flex-wrap: wrap;
  padding: 0 26px 22px; margin-top: -38px;
}
.profile-avatar {
  display: grid; place-items: center; width: 92px; height: 92px; flex: none;
  border-radius: 26px; border: 3px solid var(--surface);
  background: linear-gradient(140deg, var(--brand), var(--ai));
  color: #fff; font: 800 30px/1 var(--sans); letter-spacing: -.02em;
  box-shadow: var(--shadow2);
}
.profile-actions { align-self: center; }
.profile-stats {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
  border-top: 1px solid var(--border);
}
.profile-stat { padding: 18px 26px; border-right: 1px solid var(--border); }
.profile-stat:last-child { border-right: 0; }
.profile-meta { display: flex; flex-wrap: wrap; gap: 10px; }
.profile-meta-item {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 6px 11px; border: 1px solid var(--border); border-radius: 99px;
  background: var(--sunken); font: 600 12px/1 var(--sans); color: var(--text2);
}

@media (max-width: 768px) {
  .profile-head { padding: 0 18px 18px; gap: 14px; }
  .profile-avatar { width: 72px; height: 72px; border-radius: 20px; font-size: 24px; }
  .profile-stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .profile-stat { padding: 15px 18px; }
  .profile-stat:nth-child(2) { border-right: 0; }
  .profile-stat:nth-child(-n+2) { border-bottom: 1px solid var(--border); }
}

.chart { display: flex; align-items: flex-end; gap: 10px; }
.chart-col { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: flex-end; gap: 8px; height: 100%; }
.chart-bar { width: 100%; border-radius: 5px 5px 0 0; background: var(--brandline); }
.chart-bar.hi { background: var(--brand); }
.chart-label { font: 600 11px/1 var(--sans); color: var(--text3); }

/* --------------------------------------------------------------------------
   23. Mobile mockups page
   -------------------------------------------------------------------------- */
.phone {
  width: 340px; max-width: 100%; height: 700px; display: flex; flex-direction: column;
  border-radius: 26px; overflow: hidden; box-shadow: var(--shadow3);
}
.phone-light { border: 1px solid #E2E8F0; background: #F8FAFC; }
.phone-dark  { border: 1px solid #1E293B; background: #0B1120; }
.phone-status {
  display: flex; align-items: center; justify-content: space-between;
  padding: 14px 18px 10px; font: 700 11.5px/1 var(--sans); flex: none;
}
.phone-tabbar { display: flex; justify-content: space-around; padding: 10px 8px 20px; flex: none; }
.phone-tabbar span { font: 600 11px/1.6 var(--sans); text-align: center; }

/* --------------------------------------------------------------------------
   24. Auth
   -------------------------------------------------------------------------- */
.auth-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(420px, 100%), 1fr)); min-height: 100vh; }
.auth-brandside {
  position: relative; overflow: hidden; background: #0B1120;
  padding: 56px 52px; display: flex; flex-direction: column; justify-content: space-between; gap: 40px;
}
.auth-formside { display: grid; place-items: center; padding: 56px 40px; background: var(--bg); }
.auth-panel { width: min(400px, 100%); }
.auth-h1 {
  margin: 0; font: 800 28px/1.2 var(--sans);
  letter-spacing: -.03em; color: var(--text); text-wrap: balance;
}
.auth-lead { margin: 10px 0 0; font: 400 14.5px/1.6 var(--sans); color: var(--text2); }

/* The two providers are the only action on the page, so they run full width
   and stacked rather than sitting side by side as secondary buttons. */
.auth-providers { display: flex; flex-direction: column; gap: 10px; margin-top: 28px; }
.auth-oauth {
  position: relative; width: 100%; height: 48px;
  /* Room for the pinned icon on both sides, so a long label stays centred in
     the button rather than centred in the space left over beside the icon. */
  padding: 0 46px;
  font: 600 14.5px/1 var(--sans); border-color: var(--border);
}
/* The marks are pinned to a shared inset instead of riding beside the label:
   the three labels differ in width, so centring the icon with them would leave
   the icons on three different x positions down the stack. */
.auth-oauth svg, .auth-oauth img {
  position: absolute; left: 16px; top: 50%; transform: translateY(-50%);
  width: 18px; height: 18px; object-fit: contain;
}
.auth-oauth:hover { border-color: var(--border2); }

/* Sign-in feedback (cancelled consent, expired link, misconfiguration). */
.auth-messages { margin-top: 20px; display: flex; flex-direction: column; gap: 8px; }
.auth-message {
  margin: 0; padding: 11px 13px; border-radius: 9px;
  font: 500 13.5px/1.5 var(--sans);
  border: 1px solid var(--border); background: var(--surface2); color: var(--text2);
}
.auth-message.error { border-color: var(--err); background: var(--errsoft); color: var(--err); }
.auth-message.success { border-color: var(--ok); background: var(--oksoft); color: var(--ok); }
.auth-message.warning { border-color: var(--warn); background: var(--warnsoft); color: var(--warn); }

.auth-note {
  margin: 16px 0 0; font: 400 13px/1.6 var(--sans);
  color: var(--text3); text-align: center;
}
.auth-fine {
  margin: 26px 0 0; padding-top: 18px; border-top: 1px solid var(--border);
  font: 400 12.5px/1.6 var(--sans); color: var(--text3);
}
.auth-back { margin: 12px 0 0; font: 500 12.5px/1.6 var(--sans); color: var(--text3); }

/* ==========================================================================
   25. RESPONSIVE
   Desktop above is pixel-exact to the original; below it adapts.
   ========================================================================== */

/* ---- ≤1400px: soften the outer gutters ---- */
@media (max-width: 1400px) {
  .shell { padding-inline: 28px; }
  .shell-narrow { padding-inline: 28px; }
  .tut-main { padding: 32px 32px 72px; }
  .row-x56 { --bs-gutter-x: 48px; }
}

/* ---- ≤1200px: drop the tutorial right rail, narrow the admin rail ---- */
@media (max-width: 1200px) {
  .tut-grid { grid-template-columns: 232px minmax(0, 1fr); }
  .tut-aside-r { display: none; }
  .admin-grid { grid-template-columns: 210px minmax(0, 1fr); }
  .ide { grid-template-columns: 180px minmax(0, 1.3fr) minmax(0, 1fr); }
  .row-x56 { --bs-gutter-x: 40px; }
  .row-x48 { --bs-gutter-x: 36px; }
  .t-hero { font-size: 46px; }
  .t-h2, .t-h2-alt { font-size: 28px; }
  .t-page { font-size: 34px; }
  .gc-footer-top { grid-template-columns: 1fr; gap: 34px; }
  .gc-footer-cols { grid-template-columns: repeat(6, minmax(0, 1fr)); }
}

/* ---- ≤992px: single-column body, off-canvas navigation ---- */
@media (max-width: 992px) {
  .shell, .shell-wide, .shell-narrow { padding-inline: 20px; }
  .section { padding-top: 36px; }
  .section-lg { padding-top: 42px; }
  .row-x56, .row-x48, .row-x32 { --bs-gutter-x: 24px; }

  .gc-footer-cols { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 28px 18px; }
  .gc-news { grid-template-columns: 1fr; gap: 20px; padding: 24px; }

  /* header collapses to brand + burger + actions */
  .gc-navbar { height: 56px; padding: 0 16px; gap: 12px; }
  .gc-nav { display: none; }
  .gc-burger {
    display: grid; place-items: center; width: 34px; height: 34px; flex: none;
    border: 1px solid var(--border); border-radius: 8px;
    background: var(--surface); color: var(--text2); cursor: pointer;
  }
  .gc-actions { gap: 7px; margin-left: auto; }
  .gc-notif { display: none; }
  .gc-techbar { padding: 0 16px; }
  :root { --header-h: 97px; }

  /* tutorial goes single column, lesson list becomes an off-canvas */
  .tut-grid { grid-template-columns: minmax(0, 1fr); }
  .tut-aside-l { display: none; }
  .tut-main { padding: 24px 20px 64px; }

  /* compiler stacks: editor over terminal, explorer hidden */
  .ide { grid-template-columns: minmax(0, 1fr); grid-template-rows: minmax(320px, 1fr) minmax(220px, .8fr); height: auto; }
  .ide-explorer { display: none; }
  .ide-term { border-left: 0; border-top: 1px solid var(--code-line); }

  /* admin rail becomes an off-canvas drawer */
  .admin-grid { grid-template-columns: minmax(0, 1fr); }
  .admin-aside {
    position: fixed; top: 0; left: 0; z-index: 1050; width: 260px; height: 100vh;
    transform: translateX(-100%); transition: transform .22s ease;
    box-shadow: var(--shadow3);
  }
  .admin-aside.open { transform: none; }
  .admin-scrim {
    position: fixed; inset: 0; z-index: 1040; background: rgba(2, 6, 23, .5);
    backdrop-filter: blur(2px);
  }
  .admin-scrim[hidden] { display: none; }
  .admin-body { padding: 18px 16px 40px; }
  .admin-topbar { padding: 0 16px; gap: 10px; }
  .admin-topbar .hide-md { display: none; }

  .auth-brandside { padding: 40px 28px; gap: 32px; }
  .auth-formside { padding: 40px 20px; }

  .card-gc-lg { padding: 22px; }
  .card-gc-pad { padding: 20px; }

  .t-hero { font-size: 38px; }
  .t-page { font-size: 30px; }
  .t-h1, .t-h1-sm { font-size: 26px; }
  .t-h2, .t-h2-alt { font-size: 25px; }
  .t-h3 { font-size: 21px; }
  .t-lead { font-size: 16px; }
}

/* ---- ≤768px: tighten everything, tables scroll ---- */
@media (max-width: 768px) {
  .shell, .shell-wide, .shell-narrow { padding-inline: 16px; }
  .section { padding-top: 30px; }
  .section-lg { padding-top: 34px; }
  .tut-main { padding: 20px 16px 56px; }
  .row-x56, .row-x48, .row-x32 { --bs-gutter-x: 16px; }

  .t-hero { font-size: 33px; line-height: 1.12; }
  .t-page { font-size: 27px; }
  .t-h2, .t-h2-alt { font-size: 23px; }

  .btn-gc, .btn-gc-outline, .btn-gc-ai, .btn-solid-ai, .btn-solid-ok, .btn-solid-warn {
    height: 42px; padding: 0 18px; font-size: 14px;
  }

  /* admin/CMS tables become horizontally scrollable strips */
  .tbl-scroll > .tbl-inner { min-width: 760px; }
  .code-lines { padding-left: 10px; }
  .code-pre { padding-right: 12px; }

  .gc-dialog-head { height: 56px; padding: 0 14px; gap: 8px; }
  .gc-dialog-head .hide-sm { display: none; }
  .gc-overlay { padding: 3vh 12px; }
  .gc-overlay-top { padding: 8vh 12px 16px; }

  .phone { width: 100%; max-width: 340px; }
}

/* ---- ≤576px: smallest phones ---- */
@media (max-width: 576px) {
  .shell, .shell-wide, .shell-narrow { padding-inline: 14px; }
  .t-hero { font-size: 29px; }
  .hero-search { height: 48px; gap: 9px; padding-left: 13px; }
  .hero-search .btn-gc { height: 34px; padding: 0 13px; font-size: 13px; }
  .gc-footer-cols { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .gc-footer-bottom { flex-direction: column; align-items: flex-start; }
  .gc-news h3 { font-size: 18px; }
  .gc-news-input { flex-basis: 100%; }
  .card-gc-lg, .card-gc-pad { padding: 18px; }
  .gc-brand-text { font-size: 14px; }
  .gc-brand-logo { height: 26px; }
  .auth-brandside { padding: 32px 20px; }
  .tbl-scroll > .tbl-inner { min-width: 640px; }
  .stack-sm { flex-direction: column !important; align-items: stretch !important; }
  .stack-sm > * { width: 100%; }
}

/* ---- auth: drop the brand pitch once the two columns stack ----
   .auth-grid is auto-fit at minmax(420px, 1fr), so below 2×420px the brand
   column stops sitting beside the form and stacks on top of it — pushing the
   sign-in fields a full screen down. Hide the pitch there and keep only the
   logo, leaving a compact brand bar above a form that starts in view.
   The breakpoint tracks the grid's own collapse point, not the generic
   992/768 stops, or the pitch would vanish while the column is still there. */
@media (max-width: 839.98px) {
  /* !important is required: the stats row also carries Bootstrap's .d-flex,
     which is itself declared !important and would otherwise win. */
  .auth-pitch { display: none !important; }
  .auth-brandside { padding: 16px 20px; gap: 0; justify-content: center; }
  .auth-grid { min-height: 0; }
  .auth-formside { padding: 36px 20px 48px; align-items: start; }
}

/* utility: allow a flex row to wrap on small screens only */
@media (max-width: 768px) { .wrap-sm { flex-wrap: wrap !important; } }

/* print */
@media print {
  .gc-header, .gc-footer, .gc-overlay, .gc-toast, .admin-aside { display: none !important; }
}

/* ── CMS page ──────────────────────────────────────────────────────────────
   Typography for a page written in the console. Everything here resolves to
   the tokens the rest of the blog already uses — the same sans, the same three
   text colours, the same border and radius — so a page reads as part of the
   site rather than as something bolted on. No existing rule is changed. */

.page-doc { max-width: 760px; margin: 0 auto; }

.page-hero {
  width: 100%;
  height: auto;
  margin-top: 28px;
  border: 1px solid var(--border);
  border-radius: 13px;
}

.page-body { margin-top: 28px; font: 400 16.5px/1.8 var(--sans); color: var(--text2); }
.page-body > :first-child { margin-top: 0; }

.page-body h1 { font: 800 30px/1.2 var(--sans); letter-spacing: -.03em; color: var(--text); margin: 40px 0 0; }
.page-body h2 { font: 800 25px/1.25 var(--sans); letter-spacing: -.025em; color: var(--text); margin: 36px 0 0; }
.page-body h3 { font: 700 20px/1.3 var(--sans); letter-spacing: -.02em; color: var(--text); margin: 30px 0 0; }
.page-body h4 { font: 700 17px/1.35 var(--sans); color: var(--text); margin: 26px 0 0; }
.page-body h5,
.page-body h6 { font: 700 15px/1.4 var(--sans); color: var(--text); margin: 22px 0 0; }

.page-body p,
.page-body ul,
.page-body ol,
.page-body dl,
.page-body table,
.page-body figure,
.page-body blockquote,
.page-body pre { margin: 16px 0 0; }

.page-body a { color: var(--brand); text-decoration: none; }
.page-body a:hover { text-decoration: underline; }

.page-body strong, .page-body b { font-weight: 700; color: var(--text); }
.page-body ul, .page-body ol { padding-left: 22px; }
.page-body li { margin-top: 6px; }
.page-body li::marker { color: var(--text3); }

.page-body img { max-width: 100%; height: auto; border-radius: 10px; }
.page-body figcaption { margin-top: 8px; font: 400 13px/1.5 var(--sans); color: var(--text3); }
.page-body hr { margin: 32px 0 0; border: 0; border-top: 1px solid var(--border); }

.page-body blockquote {
  padding: 2px 0 2px 18px;
  border-left: 3px solid var(--brand);
  color: var(--text2);
}

.page-body code {
  font: 500 13.5px/1 var(--mono);
  background: var(--surface2);
  color: var(--text);
  padding: 3px 6px;
  border-radius: 5px;
}
.page-body pre {
  padding: 16px 18px;
  background: var(--code-bg);
  border: 1px solid var(--code-line);
  border-radius: 10px;
  overflow-x: auto;
}
.page-body pre code { background: none; padding: 0; color: var(--code-fg); font-size: 13px; line-height: 1.75; }

/* Wide tables scroll inside the column rather than widening the page. */
.page-body table { width: 100%; border-collapse: collapse; font-size: 14.5px; display: block; overflow-x: auto; }
.page-body th, .page-body td { padding: 10px 12px; border: 1px solid var(--border); text-align: left; }
.page-body th { background: var(--surface2); color: var(--text); font-weight: 700; }

/* ── Code blocks in a post ──────────────────────────────────────────────
   Read, not run: the compiler is its own application, and these are the
   examples on the page you are reading.

   Scoped to .page-body so the tutorial screen's own panels are untouched —
   everything below refines the post reader's copy of them and nothing else. */

.page-body .code-panel {
  border: 1px solid var(--code-line);
  border-radius: 12px;
  background: var(--code-bg);
  box-shadow: 0 1px 2px rgba(2, 6, 23, .3), 0 8px 24px -16px rgba(2, 6, 23, .5);
  overflow: hidden;
}

/* The header carries the language and the Copy button. The reference design
   floats Copy over the first line of code, where it covers the code it is
   offering to copy; a bar of its own costs 38 pixels and covers nothing. */
.page-body .code-bar {
  height: 38px;
  padding: 0 10px 0 14px;
  border-bottom: 1px solid var(--code-line);
  background: var(--code-bg2);
}
.page-body .code-file {
  font: 600 11px/1 var(--sans);
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--code-dim);
}

/* Always visible, and quiet until it is wanted — a control that appears only
   on hover cannot be found by anyone who does not already know it is there,
   and is unreachable by touch. */
.page-body .code-btn {
  opacity: 1;
  height: 26px;
  padding: 0 11px;
  border: 1px solid var(--code-line2);
  border-radius: 7px;
  background: transparent;
  color: var(--code-dim);
  font: 600 11.5px/1 var(--sans);
  transition: color .15s, border-color .15s, background .15s;
}
.page-body .code-panel:hover .code-btn { color: #94A3B8; border-color: #3E4C63; }
.page-body .code-btn:hover {
  color: var(--code-fg);
  border-color: var(--brand);
  background: rgba(37, 99, 235, .12);
}
.page-body .code-btn:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
  opacity: 1;
}

/* The article stylesheet frames every <pre> in the body — its own border,
   corner radius, background and top margin. Inside a panel that frame is a
   second box drawn around the first, which is exactly what it looked like.
   Taken off here, for the example and for the output row alike. */
.page-body .code-panel pre {
  margin: 0;
  border: 0;
  border-radius: 0;
  background: none;
  box-shadow: none;
}

/* The gutter is a rule, not a slab: numbers sit against a hairline and close
   enough to the code to belong to it. */
.page-body .code-body { align-items: stretch; }
.page-body .code-lines {
  padding: 14px 10px 14px 14px;
  border-right: 1px solid var(--code-line);
  background: transparent;
  color: #3E4C63;
  font: 400 13.5px/1.75 var(--mono);
  font-variant-numeric: tabular-nums;
}
.page-body .code-panel pre.code-pre {
  padding: 14px 16px;
  font: 400 13.5px/1.75 var(--mono);
  color: var(--code-fg);
  tab-size: 4;
  /* A long line scrolls inside the block; the page itself must never scroll
     sideways because of one wide example. */
  overflow-x: auto;
  overscroll-behavior-x: contain;
}
.page-body .code-pre code { font: inherit; line-height: inherit; }
.page-body .code-pre::-webkit-scrollbar { height: 8px; }
.page-body .code-pre::-webkit-scrollbar-thumb {
  background: var(--code-line2); border-radius: 4px;
}

/* What the example prints, when the post says. Labelled, because a second
   dark box under a code block is otherwise just a second code block. */
.page-body .code-out {
  gap: 12px;
  padding: 12px 16px;
  border-top: 1px solid var(--code-line);
  background: var(--code-bg2);
}
.page-body .code-out .lbl {
  font: 700 9.5px/1.7 var(--sans);
  letter-spacing: .1em;
  color: var(--code-dim2);
}
.page-body .code-out pre {
  padding: 0;
  font: 400 12.5px/1.7 var(--mono);
  color: var(--code-green);
  white-space: pre-wrap;
}

/* ── Tokens ─────────────────────────────────────────────────────────────
   CodeMirror's runMode writes .cm-* spans and nothing else: no editor, no
   cursor, no stylesheet of its own. Its themes are written against its own
   palette, so the colours are set here from the --code-* variables the panel
   already uses — one palette, so the code and its frame cannot drift apart.

   The assignment follows what a reader is scanning for: the shape of the
   code first (keywords), then the names it defines, then its literals. */
.page-body .cm-s-gocourse .cm-keyword,
.page-body .cm-s-gocourse .cm-atom          { color: var(--code-purple); font-weight: 600; }
.page-body .cm-s-gocourse .cm-def           { color: var(--code-green); }
.page-body .cm-s-gocourse .cm-string,
.page-body .cm-s-gocourse .cm-string-2      { color: var(--code-amber); }
.page-body .cm-s-gocourse .cm-number        { color: var(--code-amber); }
.page-body .cm-s-gocourse .cm-comment       { color: var(--code-dim); font-style: italic; }
.page-body .cm-s-gocourse .cm-builtin,
.page-body .cm-s-gocourse .cm-variable-2,
.page-body .cm-s-gocourse .cm-variable-3,
.page-body .cm-s-gocourse .cm-type          { color: var(--code-blue); }
.page-body .cm-s-gocourse .cm-property      { color: var(--code-blue); }
.page-body .cm-s-gocourse .cm-operator      { color: #8FA3BF; }
.page-body .cm-s-gocourse .cm-tag           { color: var(--code-red); }
.page-body .cm-s-gocourse .cm-attribute     { color: var(--code-amber); }
.page-body .cm-s-gocourse .cm-qualifier     { color: var(--code-green); }
.page-body .cm-s-gocourse .cm-meta          { color: var(--code-purple); }
.page-body .cm-s-gocourse .cm-error         { color: var(--code-red); }
/* runMode marks a token it could not place; ordinary code, not a warning. */
.page-body .cm-s-gocourse .cm-variable      { color: var(--code-fg); }

@media (max-width: 640px) {
  .page-body .code-lines { padding-left: 12px; padding-right: 9px; }
  .page-body .code-pre { padding-left: 12px; padding-right: 12px; font-size: 12.5px; }
}

/* Confirmation reads as success rather than as another button state. */
.page-body .code-btn.copied {
  color: var(--code-green);
  border-color: rgba(74, 222, 128, .45);
  background: rgba(74, 222, 128, .1);
}

/* ── Actions under an example ───────────────────────────────────────────
   Try it Yourself opens the compiler — its own application — with this code
   loaded. AI Explain opens the panel every lesson on the site already uses.
   Neither runs anything here. */
.page-body .gc-run-form { margin: 22px 0; }
.page-body .gc-run-form .code-panel { margin: 0 !important; }

.page-body .editor-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 12px 0 22px;
}
.page-body .gc-run-form .editor-actions { margin-bottom: 0; }

.page-body .try-it-yourself,
.page-body .ai-explain-btn {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  height: 36px;
  padding: 0 15px;
  border-radius: 9px;
  font: 700 13px/1 var(--sans);
  cursor: pointer;
  transition: filter .15s, background .15s, border-color .15s;
}
.page-body .try-it-yourself {
  border: 1px solid transparent;
  background: var(--brand);
  color: #fff;
}
.page-body .try-it-yourself:hover { filter: brightness(1.1); }
/* A post carrying its own Try it Yourself address gets a link where the
   compiler gets a submit button (static/js/blog/post.js). Same object to the
   reader, so it must not arrive underlined and in link blue. */
.page-body a.try-it-yourself { text-decoration: none; }
.page-body a.try-it-yourself:hover { color: #fff; }
.page-body .ai-explain-btn {
  border: 1px solid var(--ailine);
  background: var(--aisoft);
  color: var(--ai);
}
.page-body .ai-explain-btn:hover { filter: brightness(1.12); }
.page-body .ai-explain-btn i { font-size: 14px; line-height: 1; }
.page-body .try-it-yourself:focus-visible,
.page-body .ai-explain-btn:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
}

/* ── "More in …" band ───────────────────────────────────────────────────
   The related posts under an article, as a region of their own: a rule and a
   change of ground so the page reads as "the article ended, here is what is
   next" rather than as one column that kept going. Full-bleed on purpose —
   the article above it is a three-column grid, and a band that stopped at the
   same gutters would look like a fourth row of it. */
.post-more {
  border-top: 1px solid var(--border);
  background: var(--bg2);
  padding: 40px 0 56px;
}

/* ==========================================================================
   Comments
   Built on the same tokens as the rest of the page, so the thread reads as
   part of the article rather than as a widget dropped underneath it. Every
   colour here is a variable, which is what makes it correct in both themes
   without a second set of rules.
   ========================================================================== */

.cm-head { display: flex; align-items: center; flex-wrap: wrap; gap: 14px; }
.cm-note { margin-left: auto; font: 500 12px/1 var(--sans); color: var(--text3); }

.cm-sort { display: flex; align-items: center; gap: 4px; }
.cm-sort-label {
  margin-right: 4px; font: 600 11.5px/1 var(--sans); color: var(--text3);
  letter-spacing: .04em; text-transform: uppercase;
}
.cm-sort-btn {
  padding: 5px 10px; border-radius: 7px; text-decoration: none;
  font: 600 12.5px/1 var(--sans); color: var(--text3);
}
.cm-sort-btn:hover { background: var(--surface2); color: var(--text); }
.cm-sort-btn.is-on { background: var(--surface2); color: var(--text); }

.cm-flash {
  margin-top: 14px; padding: 11px 14px; border-radius: 9px;
  border-left: 3px solid var(--brand); background: var(--surface2);
  font: 500 13px/1.55 var(--sans); color: var(--text2);
}
.cm-flash.is-error { border-left-color: var(--t-red-fg); }

.cm-empty { padding: 20px 0; font: 500 13.5px/1.6 var(--sans); color: var(--text3); }

/* The avatar. A letter on a tinted disc — the same idea as .avatar-initials,
   sized for a comment row rather than for a byline. */
.cm-avatar {
  flex: none; width: 38px; height: 38px; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--brandsoft); color: var(--brand);
  font: 700 15px/1 var(--sans); text-transform: uppercase;
}
.cm-avatar.is-sm { width: 30px; height: 30px; font-size: 12.5px; }

/* ── The box ─────────────────────────────────────────────────────────── */

.cm-form, .cm-signin { display: flex; gap: 14px; margin-top: 22px; }
.cm-form-body { flex: 1; min-width: 0; }

.cm-signin { align-items: center; flex-wrap: wrap; }
.cm-signin-text { flex: 1 1 220px; font: 500 13.5px/1.6 var(--sans); color: var(--text2); }

/* One line until it matters. The height change is on :focus-within so it
   happens before any script runs, and cannot be left stuck open by one. */
.cm-input {
  width: 100%; padding: 8px 2px; resize: none; overflow: hidden;
  border: 0; border-bottom: 1px solid var(--border); border-radius: 0;
  background: transparent; color: var(--text);
  font: 400 14px/1.6 var(--sans);
  transition: border-color .15s ease;
}
.cm-input::placeholder { color: var(--text3); }
.cm-input:focus { outline: none; border-bottom-color: var(--brand); border-bottom-width: 2px; }
.cm-form:focus-within .cm-input, .cm-input.is-open { min-height: 64px; overflow: auto; }

/* The buttons appear with the box rather than sitting under an empty field. */
.cm-form-foot {
  display: none; align-items: flex-end; justify-content: space-between;
  flex-wrap: wrap; gap: 14px; margin-top: 12px;
}
.cm-form:focus-within .cm-form-foot, .cm-form.is-open .cm-form-foot { display: flex; }
.cm-form-actions { display: flex; align-items: center; gap: 8px; margin-left: auto; }

.cm-btn {
  padding: 9px 17px; border: 0; border-radius: 999px; cursor: pointer;
  background: var(--brand); color: #fff;
  font: 700 13px/1 var(--sans); text-decoration: none;
  display: inline-flex; align-items: center;
}
.cm-btn:hover { filter: brightness(1.06); color: #fff; }
.cm-btn[disabled] { opacity: .55; cursor: default; }

.cm-btn-ghost {
  padding: 9px 15px; border: 0; border-radius: 999px; cursor: pointer;
  background: transparent; color: var(--text2); font: 600 13px/1 var(--sans);
}
.cm-btn-ghost:hover { background: var(--surface2); color: var(--text); }

.cm-replying { margin-bottom: 8px; font: 500 12.5px/1 var(--sans); color: var(--text3); }
.cm-replying strong { color: var(--text2); }
.cm-link {
  margin-left: 8px; padding: 0; border: 0; background: none; cursor: pointer;
  color: var(--brand); font: 600 12.5px/1 var(--sans);
}

/* reCAPTCHA sets its own width on the iframe; this only has to stop it
   stretching the row it sits in. */
.cm-captcha { flex: none; transform-origin: left center; }
@media (max-width: 420px) { .cm-captcha { transform: scale(.86); } }

/* ── The thread ──────────────────────────────────────────────────────── */

.cm-list { margin-top: 26px; display: flex; flex-direction: column; gap: 22px; }
.cm-item { display: flex; gap: 14px; }
.cm-item.is-reply { gap: 12px; }
.cm-body { flex: 1; min-width: 0; }

.cm-meta { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; }
.cm-author { font: 700 13px/1 var(--sans); color: var(--text); }
.cm-time { font: 500 12px/1 var(--sans); color: var(--text3); }

.cm-badge {
  padding: 3px 7px; border-radius: 5px;
  background: var(--brandsoft); color: var(--brand);
  font: 700 10px/1 var(--sans); letter-spacing: .04em;
}
.cm-badge.is-pending { background: var(--t-amber); color: var(--t-amber-fg); }

.cm-text {
  margin: 7px 0 0; white-space: pre-wrap; overflow-wrap: anywhere;
  font: 400 14px/1.65 var(--sans); color: var(--text2);
}

.cm-actions { display: flex; align-items: center; gap: 2px; margin-top: 8px; flex-wrap: wrap; }
.cm-actions form { display: inline-flex; }

.cm-act {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 10px; border: 0; border-radius: 999px; cursor: pointer;
  background: transparent; color: var(--text3);
  font: 600 12.5px/1 var(--sans);
}
.cm-act:hover { background: var(--surface2); color: var(--text2); }
.cm-act.is-on { color: var(--brand); }
.cm-act.is-danger:hover { color: var(--t-red-fg); }
.cm-act[disabled] { opacity: .5; cursor: default; }
.cm-count { font: 600 12px/1 var(--sans); }

.cm-edit { margin-top: 10px; }
.cm-edit .cm-form-actions { margin-top: 10px; }

.cm-replies-toggle {
  display: inline-flex; align-items: center; gap: 6px; margin-top: 10px;
  padding: 6px 12px; border: 0; border-radius: 999px; cursor: pointer;
  background: transparent; color: var(--brand); font: 700 12.5px/1 var(--sans);
}
.cm-replies-toggle:hover { background: var(--brandsoft); }
.cm-replies-toggle svg { transition: transform .15s ease; }
.cm-replies-toggle[aria-expanded="true"] svg { transform: rotate(180deg); }

.cm-replies { margin-top: 14px; display: flex; flex-direction: column; gap: 18px; }

/* ── Boosted navigation ─────────────────────────────────────────────────
   hx-boost on <body> means a click no longer discards the document, so the
   browser stops showing a loading state of its own. This bar is the only
   feedback a swapped navigation gets: htmx puts .htmx-request on it for
   exactly the life of the request.

   It creeps toward 90% rather than completing, because the request finishing
   is not the thing the reader is waiting for — the swap is, and that is what
   removes the class. */
.gc-progress {
  position: fixed;
  top: 0; left: 0; right: 0;
  height: 2px;
  z-index: 2000;
  pointer-events: none;
  opacity: 0;
  transform: scaleX(0);
  transform-origin: 0 50%;
  background: linear-gradient(90deg, var(--brand), var(--brand3));
  transition: opacity .15s;
}
.gc-progress.htmx-request { opacity: 1; animation: gc-progress-creep 1.4s ease-out forwards; }
@keyframes gc-progress-creep {
  0%   { transform: scaleX(0); }
  40%  { transform: scaleX(.55); }
  100% { transform: scaleX(.9); }
}
@media (prefers-reduced-motion: reduce) {
  .gc-progress.htmx-request { animation: none; transform: scaleX(1); }
}
