/* ============================================================================
   99Learn Academy LLP — design system
   Hand-authored, no build step. Sections:
   1. Tokens   2. Reset   3. Typography   4. Layout   5. Buttons   6. Forms
   7. Cards    8. Badges  9. Navigation  10. Components 11. Utilities
   ========================================================================= */

/* ---------------------------------------------------------------- 1. tokens */
:root {
  /* Brand */
  --brand-50:#f4f0ff; --brand-100:#e9e2ff; --brand-200:#d4c6ff; --brand-300:#b49bff;
  --brand-400:#9370ff; --brand-500:#7b42ff; --brand-600:#6d28d9; --brand-700:#5b21b6;
  --brand-800:#4c1d95; --brand-900:#3b1476;

  --accent-100:#fef3c7; --accent-200:#fde68a; --accent-300:#fcd34d;
  --accent-400:#fbbf24; --accent-500:#f59e0b; --accent-600:#d97706;

  --ink-50:#f7f9fa; --ink-100:#eceff1; --ink-200:#d1d7dc; --ink-300:#b2bac2;
  --ink-400:#8a919a; --ink-500:#6a6f73; --ink-600:#4e5257; --ink-700:#3e4143;
  --ink-800:#2d2f31; --ink-900:#1c1d1f; --ink-950:#0f1011;

  --green-50:#ecfdf5; --green-100:#d1fae5; --green-500:#10b981; --green-600:#059669; --green-700:#047857;
  --red-50:#fef2f2;   --red-100:#fee2e2;   --red-500:#ef4444;   --red-600:#dc2626;  --red-700:#b91c1c;
  --blue-50:#eff6ff;  --blue-100:#dbeafe;  --blue-500:#3b82f6;  --blue-600:#2563eb; --blue-700:#1d4ed8;
  --amber-50:#fffbeb;

  /* Semantic (light) */
  --surface:#ffffff;
  --surface-muted:#f7f9fa;
  --surface-raised:#ffffff;
  --surface-inverse:#1c1d1f;
  --line:#d6dce2;
  --line-soft:#e9edf1;
  --text:#1c1d1f;
  --text-soft:#4e5257;
  --text-muted:#6a6f73;
  --text-inverse:#ffffff;
  --brand:var(--brand-600);
  --brand-contrast:#ffffff;
  --ring:rgba(123,66,255,.28);

  /* Shape & motion */
  --r-xs:4px; --r-sm:6px; --r-md:8px; --r-lg:12px; --r-xl:16px; --r-2xl:22px; --r-full:999px;
  --sh-xs:0 1px 2px rgba(15,17,21,.06);
  --sh-sm:0 1px 3px rgba(15,17,21,.09), 0 1px 2px rgba(15,17,21,.05);
  --sh-md:0 4px 12px rgba(15,17,21,.09), 0 2px 4px rgba(15,17,21,.05);
  --sh-lg:0 12px 28px rgba(15,17,21,.13), 0 4px 10px rgba(15,17,21,.07);
  --sh-xl:0 24px 56px rgba(15,17,21,.18);
  --ease:cubic-bezier(.16,1,.3,1);
  --t-fast:.14s var(--ease);
  --t:.22s var(--ease);

  /* Layout */
  --header-h:68px;
  --topbar-h:0px;
  --container:1340px;
  --sidebar-w:260px;

  --font-sans:"Inter var","Inter",-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif;
  --font-display:"Inter var","Inter",-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;
  --font-mono:ui-monospace,SFMono-Regular,"SF Mono",Menlo,Consolas,monospace;
}

[data-theme="dark"] {
  --surface:#121315;
  --surface-muted:#1a1b1e;
  --surface-raised:#1f2124;
  --surface-inverse:#f7f9fa;
  --line:#33363b;
  --line-soft:#26282c;
  --text:#edeff2;
  --text-soft:#c3c8d0;
  --text-muted:#9aa0a9;
  --text-inverse:#1c1d1f;
  --brand:var(--brand-400);
  --brand-contrast:#14061f;
  --sh-sm:0 1px 3px rgba(0,0,0,.5);
  --sh-md:0 4px 14px rgba(0,0,0,.5);
  --sh-lg:0 14px 34px rgba(0,0,0,.6);
  --sh-xl:0 26px 60px rgba(0,0,0,.7);
  color-scheme:dark;
}

/* ----------------------------------------------------------------- 2. reset */
*,*::before,*::after{box-sizing:border-box}
*{margin:0;padding:0}
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth;scroll-padding-top:calc(var(--header-h) + 16px)}
body{
  font-family:var(--font-sans);
  font-size:15px;line-height:1.6;
  color:var(--text);background:var(--surface);
  -webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;
  text-rendering:optimizeLegibility;
  min-height:100vh;display:flex;flex-direction:column;
  /* `clip`, not `hidden`. Both stop a too-wide child spilling sideways, but
     `hidden` also makes this element a scroll container — and a scroll
     container is what `position:sticky` sticks to. With `hidden` here the
     course page's buy box measured its stickiness against a box that never
     scrolls, so it slid away with the page and left a column of white space
     taller than the screen next to the description. `clip` clips and nothing
     more, so sticky resolves against the window again. */
  overflow-x:clip;
}
img,svg,video,canvas{display:block;max-width:100%}
img{height:auto}
button,input,select,textarea{font:inherit;color:inherit;max-width:100%}
button{background:none;border:0;cursor:pointer}
fieldset{border:0;margin:0;padding:0;min-width:0}
/* Floating the legend takes it out of the fieldset's rendered-legend slot,
   so a bordered fieldset (.panel) draws an unbroken border instead of a
   notch with the label sitting across it. */
legend{float:left;width:100%;padding:0}
legend+*{clear:both}
a{color:inherit;text-decoration:none}
ul,ol{list-style:none}
table{border-collapse:collapse;width:100%}
hr{border:0;border-top:1px solid var(--line-soft)}
[hidden]{display:none!important}
::selection{background:rgba(123,66,255,.22)}
:focus-visible{outline:2px solid var(--brand-500);outline-offset:2px;border-radius:var(--r-xs)}
:where(button,a,input,select,textarea):focus:not(:focus-visible){outline:none}

::-webkit-scrollbar{width:10px;height:10px}
::-webkit-scrollbar-track{background:transparent}
::-webkit-scrollbar-thumb{background:var(--line);border-radius:8px;border:2px solid var(--surface)}
::-webkit-scrollbar-thumb:hover{background:var(--text-muted)}

@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.01ms!important;animation-iteration-count:1!important;
    transition-duration:.01ms!important;scroll-behavior:auto!important}
}

/* ------------------------------------------------------------ 3. typography */
h1,h2,h3,h4,h5,h6{font-family:var(--font-display);font-weight:800;line-height:1.18;letter-spacing:-.021em;color:var(--text)}
h1{font-size:clamp(1.85rem,1.2rem + 2.4vw,2.85rem)}
h2{font-size:clamp(1.45rem,1.1rem + 1.4vw,2rem)}
h3{font-size:clamp(1.2rem,1rem + .7vw,1.5rem)}
h4{font-size:1.125rem;font-weight:700}
h5{font-size:1rem;font-weight:700}
h6{font-size:.875rem;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:var(--text-muted)}
p{color:var(--text-soft)}
/* Text a person typed -- an email address, a pasted URL, a review, a course
   title -- is not guaranteed to have a space where the box ends. `break-word`
   only splits a word that cannot fit on a line of its own, so ordinary prose
   wraps exactly as before and nothing spills out of its container. */
p,li,dd,dt,td,th,h1,h2,h3,h4,h5,h6,blockquote,figcaption{overflow-wrap:break-word}
small{font-size:.8125rem}
strong,b{font-weight:700;color:var(--text)}
code,kbd{font-family:var(--font-mono);font-size:.875em;background:var(--surface-muted);
  padding:.12em .4em;border-radius:var(--r-xs);border:1px solid var(--line-soft)}
.display{font-size:clamp(2.1rem,1.2rem + 3.4vw,3.6rem);line-height:1.05;letter-spacing:-.032em;font-weight:800}
.lede{font-size:clamp(1rem,.95rem + .35vw,1.1875rem);line-height:1.62;color:var(--text-soft)}
.eyebrow{font-size:.75rem;font-weight:800;letter-spacing:.1em;text-transform:uppercase;color:var(--brand)}
.muted{color:var(--text-muted)}
.soft{color:var(--text-soft)}
.mono{font-family:var(--font-mono)}
.balance{text-wrap:balance}
/* The same three colours, in the same order, at the same angle — the gradient
   simply travels across the words. The band is drawn three times as wide as
   the text and slid by exactly one third, so it loops without a seam. */
.gradient-text{
  background:linear-gradient(115deg,
    var(--brand-500), var(--brand-300) 15%, var(--accent-400) 30%,
    var(--brand-500) 45%, var(--brand-300) 60%, var(--accent-400) 75%,
    var(--brand-500) 90%, var(--brand-300) 100%);
  background-size:300% 100%;
  -webkit-background-clip:text;background-clip:text;color:transparent;
  animation:gradient-drift 9s linear infinite}
@keyframes gradient-drift{from{background-position:0% 50%}to{background-position:-200% 50%}}
/* Anybody who has asked their computer for less movement gets the original
   still gradient, not a stopped animation mid-cycle. */
@media (prefers-reduced-motion:reduce){
  /* background-size comes after the shorthand, which would otherwise reset it:
     the band is one screen wide here because there is nothing left to slide. */
  .gradient-text{animation:none;
    background:linear-gradient(115deg,var(--brand-500),var(--brand-300) 45%,var(--accent-400));
    background-size:100% 100%;
    -webkit-background-clip:text;background-clip:text}
}
.clamp-1,.clamp-2,.clamp-3,.clamp-4{display:-webkit-box;-webkit-box-orient:vertical;overflow:hidden}
.clamp-1{-webkit-line-clamp:1}.clamp-2{-webkit-line-clamp:2}
.clamp-3{-webkit-line-clamp:3}.clamp-4{-webkit-line-clamp:4}
/* A clamp inside a table cell needs a width cap of its own: in automatic table
   layout the column is sized from the cell's max-content, so without one the
   column grows to the full untruncated string and pushes the table wider than
   its card. (The clamp belongs on this inner span, never on the cell itself --
   display:-webkit-box would replace display:table-cell and break the row.) */
td>.clamp-1,th>.clamp-1{max-width:280px}

/* ---------------------------------------------------------------- 4. layout */
.container{width:100%;max-width:var(--container);margin-inline:auto;padding-inline:16px}
.container-narrow{width:100%;max-width:880px;margin-inline:auto;padding-inline:16px}
.container-mid{width:100%;max-width:1100px;margin-inline:auto;padding-inline:16px}
@media (min-width:768px){.container,.container-narrow,.container-mid{padding-inline:24px}}
@media (min-width:1280px){.container{padding-inline:32px}}

main{flex:1 0 auto}
.section{padding-block:clamp(32px,4vw,64px)}
.section-sm{padding-block:clamp(24px,3vw,40px)}
.section-head{display:flex;align-items:flex-end;justify-content:space-between;gap:16px;margin-bottom:20px;flex-wrap:wrap}
.section-head h2{margin-bottom:4px}
.section-head p{font-size:.9375rem}

.stack{display:flex;flex-direction:column}
.stack-1{gap:4px}.stack-2{gap:8px}.stack-3{gap:12px}.stack-4{gap:16px}
.stack-5{gap:20px}.stack-6{gap:24px}.stack-8{gap:32px}
.row{display:flex;align-items:center}
.row-2{gap:8px}.row-3{gap:12px}.row-4{gap:16px}.row-6{gap:24px}
.row-wrap{flex-wrap:wrap}
.between{justify-content:space-between}
.center{justify-content:center}
.end{justify-content:flex-end}
.items-start{align-items:flex-start}
.items-end{align-items:flex-end}
.grow{flex:1 1 auto;min-width:0}
.shrink-0{flex-shrink:0}

.grid{display:grid;gap:20px}
.grid-2{grid-template-columns:repeat(2,minmax(0,1fr))}
.grid-3{grid-template-columns:repeat(3,minmax(0,1fr))}
.grid-4{grid-template-columns:repeat(4,minmax(0,1fr))}
.grid-5{grid-template-columns:repeat(5,minmax(0,1fr))}
.grid-auto{grid-template-columns:repeat(auto-fill,minmax(250px,1fr))}
.grid-auto-sm{grid-template-columns:repeat(auto-fill,minmax(190px,1fr))}
.grid-auto-lg{grid-template-columns:repeat(auto-fill,minmax(320px,1fr))}
@media (max-width:1100px){.grid-4,.grid-5{grid-template-columns:repeat(3,minmax(0,1fr))}}
@media (max-width:860px){
  .grid-3,.grid-4,.grid-5{grid-template-columns:repeat(2,minmax(0,1fr))}
  .grid-auto{grid-template-columns:repeat(auto-fill,minmax(200px,1fr))}
}
@media (max-width:560px){
  .grid-2,.grid-3,.grid-4,.grid-5{grid-template-columns:minmax(0,1fr)}
  .grid-auto,.grid-auto-sm{grid-template-columns:repeat(auto-fill,minmax(150px,1fr))}
  /* `-lg` says these items need 320px to make sense. Squeezing two of them
     into a 350px phone leaves 150px each, which breaks a word like
     "Instructors" across two lines. One column, then. */
  .grid-auto-lg{grid-template-columns:minmax(0,1fr)}
}

.split{display:grid;grid-template-columns:minmax(0,1fr) 340px;gap:32px;align-items:start}
@media (max-width:1024px){.split{grid-template-columns:minmax(0,1fr)}}
.split-wide{display:grid;grid-template-columns:280px minmax(0,1fr);gap:32px;align-items:start}
@media (max-width:900px){.split-wide{grid-template-columns:minmax(0,1fr)}}

.sticky{position:sticky;top:calc(var(--header-h) + 16px)}
/* A sticky box can only travel as far as the column it sits in. These grids
   align their items to the start, so the column was only as tall as the box
   itself — the course page's buy box had about 150px of travel and then left
   the screen with it, leaving a column of white space taller than the window
   beside the description. A column holding something sticky stretches to the
   row instead, which is the height it needs to stay put for. */
.split > *:has(.sticky),
.split-wide > *:has(.sticky){align-self:stretch}

/* --------------------------------------------------------------- 5. buttons */
.btn{
  --btn-bg:transparent;--btn-fg:var(--text);--btn-bd:transparent;
  display:inline-flex;align-items:center;justify-content:center;gap:8px;
  height:42px;padding-inline:18px;border-radius:var(--r-md);
  font-size:.9375rem;font-weight:700;line-height:1;white-space:nowrap;
  background:var(--btn-bg);color:var(--btn-fg);border:1px solid var(--btn-bd);
  transition:filter var(--t-fast),transform var(--t-fast),background var(--t-fast),border-color var(--t-fast),box-shadow var(--t-fast);
  cursor:pointer;user-select:none;text-align:center;
}
.btn:hover{filter:brightness(.94)}
.btn:active{transform:translateY(1px) scale(.995)}
.btn:disabled,.btn.is-disabled{opacity:.5;pointer-events:none}
.btn .lw-icon{flex-shrink:0}

.btn-primary{--btn-bg:var(--brand-600);--btn-fg:#fff;box-shadow:var(--sh-xs)}
.btn-primary:hover{--btn-bg:var(--brand-700);filter:none}
[data-theme="dark"] .btn-primary{--btn-bg:var(--brand-500)}
.btn-dark{--btn-bg:var(--ink-900);--btn-fg:#fff}
[data-theme="dark"] .btn-dark{--btn-bg:#fff;--btn-fg:var(--ink-900)}
.btn-accent{--btn-bg:var(--accent-400);--btn-fg:var(--ink-900)}
.btn-outline{--btn-bd:var(--text);--btn-fg:var(--text)}
.btn-outline:hover{--btn-bg:var(--surface-muted);filter:none}
.btn-line{--btn-bd:var(--line);--btn-fg:var(--text);background:var(--surface-raised)}
.btn-line:hover{--btn-bd:var(--text-muted);--btn-bg:var(--surface-muted);filter:none}
.btn-soft{--btn-bg:var(--brand-50);--btn-fg:var(--brand-700)}
[data-theme="dark"] .btn-soft{--btn-bg:rgba(123,66,255,.18);--btn-fg:var(--brand-200)}
.btn-ghost{--btn-fg:var(--text-soft)}
.btn-ghost:hover{--btn-bg:var(--surface-muted);--btn-fg:var(--text);filter:none}
.btn-danger{--btn-bg:var(--red-600);--btn-fg:#fff}
.btn-success{--btn-bg:var(--green-600);--btn-fg:#fff}
.btn-white{--btn-bg:#fff;--btn-fg:var(--ink-900)}

.btn-xs{height:28px;padding-inline:10px;font-size:.75rem;border-radius:var(--r-sm)}
.btn-sm{height:34px;padding-inline:13px;font-size:.8125rem}
.btn-lg{height:50px;padding-inline:26px;font-size:1rem}
.btn-xl{height:56px;padding-inline:32px;font-size:1.0625rem}
.btn-block{width:100%}
.btn-icon{width:42px;padding:0}
.btn-icon.btn-sm{width:34px}
.btn-icon.btn-xs{width:28px}
.btn-icon.btn-lg{width:50px}
.btn-round{border-radius:var(--r-full)}

.link{color:var(--brand);font-weight:600}
.link:hover{text-decoration:underline;text-underline-offset:2px}
.link-quiet{color:var(--text-soft)}
.link-quiet:hover{color:var(--text)}

/* ----------------------------------------------------------------- 6. forms */
.field{display:block;margin-bottom:16px}
.label{display:block;font-size:.875rem;font-weight:700;margin-bottom:6px;color:var(--text)}
.label .req{color:var(--red-600)}
.hint{font-size:.8125rem;color:var(--text-muted);margin-top:5px;line-height:1.5}
.err{font-size:.8125rem;color:var(--red-600);margin-top:5px;font-weight:600;display:flex;gap:5px;align-items:center}

.input,.select,.textarea{
  width:100%;height:44px;padding:0 14px;
  background:var(--surface-raised);color:var(--text);
  border:1px solid var(--line);border-radius:var(--r-md);
  font-size:.9375rem;transition:border-color var(--t-fast),box-shadow var(--t-fast);
}
.input::placeholder,.textarea::placeholder{color:var(--text-muted);opacity:.75}
.input:hover,.select:hover,.textarea:hover{border-color:var(--text-muted)}
.input:focus,.select:focus,.textarea:focus{
  outline:none;border-color:var(--brand-500);box-shadow:0 0 0 3px var(--ring)}
.input:disabled,.select:disabled,.textarea:disabled{background:var(--surface-muted);opacity:.7;cursor:not-allowed}
.input.is-error,.select.is-error,.textarea.is-error{border-color:var(--red-500)}
.textarea{height:auto;min-height:120px;padding:12px 14px;line-height:1.6;resize:vertical}
.select{
  appearance:none;padding-right:38px;cursor:pointer;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%236a6f73' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right 12px center;
}
.input-sm{height:36px;font-size:.875rem;padding-inline:11px}
.input-lg{height:52px;font-size:1rem}

.input-group{position:relative;display:flex;align-items:center}
.input-group .lw-icon{position:absolute;left:13px;color:var(--text-muted);pointer-events:none;z-index:1}
.input-group .input{padding-left:40px}
.input-group .input-suffix{position:absolute;right:6px}

/* A row of three, pick one. Used on the sign-up form, where the question is
   "which of these three are you" — three radios with a paragraph each is a
   block to read before the form has begun. */
.pickrow{display:grid;grid-template-columns:repeat(3,1fr);gap:8px}
.pick{position:relative;display:block;cursor:pointer}
.pick input{position:absolute;opacity:0;width:0;height:0}
.pick__face{
  display:flex;align-items:center;justify-content:center;gap:7px;
  padding:11px 8px;border:1.5px solid var(--line);border-radius:var(--r-md);
  background:var(--surface-raised);font-weight:650;font-size:.9375rem;
  color:var(--ink-700);transition:all var(--t-fast);text-align:center;
  /* "Promote" at 320px has nowhere to go, so the icon is what gives. */
  min-width:0;white-space:nowrap}
.pick__face .lw-icon{flex-shrink:0;opacity:.7}
.pick:hover .pick__face{border-color:var(--brand-400);color:var(--brand-700)}
.pick input:checked + .pick__face{
  border-color:var(--brand-600);background:var(--brand-50);color:var(--brand-700);
  box-shadow:0 0 0 1px var(--brand-600) inset}
.pick input:checked + .pick__face .lw-icon{opacity:1}
/* The keyboard has to be able to see where it is, and the box is the input's
   sibling rather than the input itself. */
.pick input:focus-visible + .pick__face{outline:2px solid var(--brand-600);outline-offset:2px}
@media (max-width:380px){
  .pick__face{gap:5px;padding:10px 4px;font-size:.875rem}
  .pick__face .lw-icon{display:none}
}
/* Until the script runs, every line shows — which is the form as it was. */
[data-pick-note].is-live span[hidden]{display:none}

.check{display:flex;align-items:flex-start;gap:10px;cursor:pointer;font-size:.9375rem;line-height:1.5}
.check input[type=checkbox],.check input[type=radio]{
  appearance:none;width:19px;height:19px;flex-shrink:0;margin-top:2px;
  border:1.5px solid var(--line);border-radius:var(--r-xs);background:var(--surface-raised);
  cursor:pointer;transition:all var(--t-fast);position:relative}
.check input[type=radio]{border-radius:50%}
.check input:hover{border-color:var(--brand-500)}
.check input:checked{background:var(--brand-600);border-color:var(--brand-600)}
.check input[type=checkbox]:checked::after{
  content:"";position:absolute;inset:0;
  background:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='3.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E") center/13px no-repeat}
.check input[type=radio]:checked::after{
  content:"";position:absolute;inset:4px;border-radius:50%;background:#fff}
.check input:focus-visible{box-shadow:0 0 0 3px var(--ring)}

.switch{display:inline-flex;align-items:center;gap:10px;cursor:pointer}
.switch input{appearance:none;width:42px;height:24px;border-radius:var(--r-full);
  background:var(--line);position:relative;transition:background var(--t-fast);cursor:pointer;flex-shrink:0}
.switch input::after{content:"";position:absolute;top:3px;left:3px;width:18px;height:18px;border-radius:50%;
  background:#fff;box-shadow:var(--sh-xs);transition:transform var(--t-fast)}
.switch input:checked{background:var(--brand-600)}
.switch input:checked::after{transform:translateX(18px)}
.switch input:focus-visible{box-shadow:0 0 0 3px var(--ring)}

.form-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:0 18px}
.form-grid .full{grid-column:1/-1}
@media (max-width:640px){.form-grid{grid-template-columns:1fr}}

/* ----------------------------------------------------------------- 7. cards */
.card{background:var(--surface-raised);color:var(--text);border:1px solid var(--line-soft);
  border-radius:var(--r-lg);
  transition:box-shadow var(--t),border-color var(--t),transform var(--t)}
.card-hover:hover{box-shadow:var(--sh-lg);border-color:var(--line);transform:translateY(-2px)}
.card-body{padding:20px}
.card-head{padding:16px 20px;border-bottom:1px solid var(--line-soft);display:flex;
  align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap}
.card-head h3,.card-head h4{font-size:1rem;font-weight:700;letter-spacing:-.012em;line-height:1.3}
.card-foot{padding:14px 20px;border-top:1px solid var(--line-soft);background:var(--surface-muted);
  border-radius:0 0 var(--r-lg) var(--r-lg)}
/* Surfaces state their own text colour. Without it, a panel or card placed on
   a dark section inherits that section's white and its plain text vanishes.
   An inline `color` on a deliberately dark panel still wins over this. */
.panel{background:var(--surface-raised);color:var(--text);border:1px solid var(--line-soft);
  border-radius:var(--r-lg);padding:22px}
.panel-muted{background:var(--surface-muted);color:var(--text);border:1px solid var(--line-soft);border-radius:var(--r-lg);padding:18px}
/* Three heading sizes, and no fourth. Every panel used to carry its own
   inline `font-size`, so the same kind of heading came out at 16px on one
   screen and 17px on the next -- small enough that nobody could name it, big
   enough that the pages never quite looked like one product. */
.panel__title{font-size:1rem;font-weight:700;letter-spacing:-.012em;line-height:1.3}
.section-title{font-size:1.1875rem;font-weight:800;letter-spacing:-.018em;line-height:1.25}
.modal__title{font-size:1.0625rem;font-weight:800;letter-spacing:-.015em;line-height:1.3}
/* A title with something on the right of it -- a link, a count, a button --
   sitting on the panel's own hairline. */
.panel__head{display:flex;align-items:center;justify-content:space-between;gap:12px;
  flex-wrap:wrap;padding-bottom:13px;margin-bottom:16px;border-bottom:1px solid var(--line-soft)}
.panel__head--plain{padding-bottom:0;margin-bottom:14px;border-bottom:0}
/* Headings and paragraphs set their own colour, so a panel that only sets
   `color` on itself leaves dark body text on a dark fill. `.on-dark` hands
   the container's colour back to them. */
.on-dark,.on-dark h1,.on-dark h2,.on-dark h3,.on-dark h4,.on-dark h5,.on-dark h6,
.on-dark p,.on-dark a,.on-dark strong,.on-dark li{color:inherit}
.on-dark .muted,.on-dark .fs-xs.muted{color:rgba(255,255,255,.78)}

/* ---------------------------------------------------------------- 8. badges */
.badge{display:inline-flex;align-items:center;gap:5px;height:21px;padding-inline:8px;
  border-radius:var(--r-xs);font-size:.6875rem;font-weight:800;letter-spacing:.03em;
  text-transform:uppercase;white-space:nowrap;line-height:1}
.badge--brand{background:var(--brand-100);color:var(--brand-800)}
.badge--accent{background:var(--accent-200);color:#6b3f05}
.badge--success{background:var(--green-100);color:var(--green-700)}
.badge--danger{background:var(--red-100);color:var(--red-700)}
.badge--info{background:var(--blue-100);color:var(--blue-700)}
.badge--warn{background:var(--accent-100);color:#92400e}
.badge--muted{background:var(--ink-100);color:var(--ink-700)}
.badge--dark{background:var(--ink-900);color:#fff}
/* For a badge whose text is an identifier — an exception class, a setting key.
   Uppercasing DoesNotExist into DOESNOTEXIST loses the word boundaries, and
   the name is what somebody searches for. */
.badge--code{font-family:var(--font-mono);text-transform:none;letter-spacing:0;font-weight:700}
[data-theme="dark"] .badge--brand{background:rgba(123,66,255,.22);color:var(--brand-200)}
[data-theme="dark"] .badge--success{background:rgba(16,185,129,.2);color:#6ee7b7}
[data-theme="dark"] .badge--danger{background:rgba(239,68,68,.2);color:#fca5a5}
[data-theme="dark"] .badge--info{background:rgba(59,130,246,.2);color:#93c5fd}
[data-theme="dark"] .badge--warn{background:rgba(245,158,11,.2);color:#fcd34d}
[data-theme="dark"] .badge--muted{background:rgba(255,255,255,.1);color:var(--ink-200)}
[data-theme="dark"] .badge--accent{background:rgba(251,191,36,.22);color:#fcd34d}
[data-theme="dark"] .badge--dark{background:#fff;color:var(--ink-900)}
.badge-lg{height:26px;padding-inline:10px;font-size:.75rem}
.badge-dot{width:8px;height:8px;border-radius:50%;padding:0;display:inline-block}

/* nowrap keeps a pill on one line, so it also needs a ceiling and an ellipsis
   or a long label runs off the side of a phone. */
.pill{display:inline-flex;align-items:center;gap:6px;height:32px;padding-inline:13px;
  border-radius:var(--r-full);border:1px solid var(--line);background:var(--surface-raised);
  font-size:.8125rem;font-weight:600;color:var(--text-soft);transition:all var(--t-fast);
  white-space:nowrap;max-width:100%;overflow:hidden;text-overflow:ellipsis}
.pill:hover{border-color:var(--text-muted);color:var(--text)}
.pill.is-active{background:var(--ink-900);border-color:var(--ink-900);color:#fff}
[data-theme="dark"] .pill.is-active{background:#fff;color:var(--ink-900);border-color:#fff}
/* How many are behind the filter, next to what the filter is called. Left off
   when the answer is none, so a quiet queue is a row of names rather than a row
   of zeros. */
.pill__count{display:inline-grid;place-items:center;min-width:19px;height:19px;padding-inline:5px;
  border-radius:var(--r-full);background:var(--surface-muted);color:var(--text-muted);
  font-size:.6875rem;font-weight:800;font-variant-numeric:tabular-nums;line-height:1}
.pill.is-active .pill__count{background:rgba(255,255,255,.22);color:#fff}
[data-theme="dark"] .pill.is-active .pill__count{background:rgba(0,0,0,.14);color:var(--ink-900)}

/* ------------------------------------------------------------ 9. navigation */
.topbar{background:var(--ink-900);color:#fff;font-size:.8125rem;font-weight:600}
.topbar--accent{background:linear-gradient(90deg,var(--brand-700),var(--brand-500) 60%,var(--accent-500))}
.topbar--info{background:var(--blue-700)}
.topbar--success{background:var(--green-700)}
.topbar__inner{display:flex;align-items:center;justify-content:center;gap:12px;
  min-height:38px;padding-block:7px;text-align:center;flex-wrap:wrap}
.topbar a{text-decoration:underline;text-underline-offset:2px}
.topbar__close{margin-left:auto;opacity:.75}
.topbar__close:hover{opacity:1}

.header{position:sticky;top:0;z-index:60;background:var(--surface);
  border-bottom:1px solid var(--line-soft);box-shadow:var(--sh-xs)}
/* Stays in the body's own column — a brand mark that does not line up with the
   heading beneath it is its own alignment fault — and gets the room it needs
   from the search box instead, which is what the shrink weights below are for. */
.header__inner{display:flex;align-items:center;gap:12px;height:var(--header-h);min-width:0}
.brand{display:flex;align-items:center;gap:9px;font-weight:800;font-size:1.1875rem;
  letter-spacing:-.03em;flex-shrink:0;color:var(--text)}
.brand__mark{width:34px;height:34px;border-radius:9px;display:grid;place-items:center;
  background:linear-gradient(135deg,var(--brand-500),var(--brand-700));color:#fff;
  font-weight:900;font-size:.9375rem;letter-spacing:-.04em;box-shadow:var(--sh-xs)}
.brand__text{display:none}
@media (min-width:480px){.brand__text{display:block}}
/* An uploaded logo replaces the mark entirely, so it sets the brand's height. */
.brand__logo{display:block;height:34px;width:auto;max-width:200px;object-fit:contain}
.brand__logo--dark{display:none}
@media (prefers-color-scheme:dark){
  :root:not([data-theme="light"]) .brand__logo--light{display:none}
  :root:not([data-theme="light"]) .brand__logo--dark{display:block}
}
:root[data-theme="dark"] .brand__logo--light{display:none}
:root[data-theme="dark"] .brand__logo--dark{display:block}

.nav-link{display:inline-flex;align-items:center;gap:6px;height:38px;padding-inline:11px;
  border-radius:var(--r-md);font-size:.875rem;font-weight:600;color:var(--text-soft);
  transition:all var(--t-fast);white-space:nowrap}
.nav-link:hover{color:var(--brand);background:var(--surface-muted)}
.nav-link.is-active{color:var(--brand);font-weight:700}
/* How many links this holds is an editor's choice, so no fixed width can be
   right for every site. It keeps its own: min-width:0 and the scroll let it give
   way when the links genuinely outgrow the bar — the case an editor creates by
   adding one more — instead of pushing the window sideways, which is what used
   to happen on a 1280px laptop. */
.header__nav{display:none;align-items:center;gap:2px;flex:0 1 auto;min-width:0;
  max-width:100%;overflow-x:auto;overflow-y:hidden;scrollbar-width:none;-ms-overflow-style:none}
.header__nav::-webkit-scrollbar{display:none}
/* Tighter in the bar than anywhere else, because the bar is where the room runs
   out — and 8px is what the five links give back between them without reading as
   cramped. */
.header__nav .nav-link,.header__inner>.mega>.nav-link{padding-inline:8px}
/* 1080px was where the links appeared, not where they fit. Brand, Explore, a
   usable search box, five links and the account controls want about 1400, so
   below that they were squeezed until the page scrolled sideways and "For
   business" lost its ending. They now wait for the room; until then the drawer
   carries every one of them, which it did already. */
@media (min-width:1440px){.header__nav{display:flex}}

/* Grows into whatever is spare and gives ground long before the links do:
   flexbox shares a shortfall in proportion to these factors, so at 100 against
   the nav's 1 this box reaches its floor first and the links are touched only
   when there is nothing left to take. The floor is the point — without one it
   sat at 81px on a 1440px screen, showing the "S" of its placeholder. */
.searchbar{flex:1 100 auto;min-width:170px;max-width:640px;position:relative;display:none}
@media (min-width:860px){.searchbar{display:block}}
.searchbar .input{height:42px;border-radius:var(--r-full);background:var(--surface-muted);padding-left:42px}
.searchbar .input:focus{background:var(--surface-raised)}
.searchbar .lw-icon{position:absolute;left:15px;top:50%;transform:translateY(-50%);color:var(--text-muted)}

.icon-btn{position:relative;display:inline-grid;place-items:center;width:40px;height:40px;
  border-radius:var(--r-md);color:var(--text-soft);transition:all var(--t-fast)}
.icon-btn:hover{background:var(--surface-muted);color:var(--text)}
.icon-btn__count{position:absolute;top:2px;right:2px;min-width:17px;height:17px;padding-inline:4px;
  border-radius:var(--r-full);background:var(--brand-600);color:#fff;font-size:.625rem;
  font-weight:800;display:grid;place-items:center;line-height:1;border:2px solid var(--surface)}
.icon-btn__count--danger{background:var(--red-600)}

/* Dropdown / popover */
.dd{position:relative}
.dd__panel{
  position:absolute;top:calc(100% + 8px);right:0;z-index:70;min-width:230px;
  background:var(--surface-raised);border:1px solid var(--line);border-radius:var(--r-lg);
  box-shadow:var(--sh-lg);padding:6px;opacity:0;visibility:hidden;
  transform:translateY(-6px) scale(.98);transform-origin:top right;
  transition:opacity var(--t-fast),transform var(--t-fast),visibility var(--t-fast)}
.dd__panel--left{right:auto;left:0;transform-origin:top left}
/* A suggestion list holds course titles, not short menu labels, so it does not
   take its width from the box above it — the header's box can be 170px, which
   broke a title across three lines. It still never outgrows the window. */
.searchbar>.dd__panel,.hero-search>.dd__panel{min-width:min(360px,calc(100vw - 32px))}
.dd.is-open>.dd__panel{opacity:1;visibility:visible;transform:translateY(0) scale(1)}
.dd__item{display:flex;align-items:center;gap:10px;padding:9px 11px;border-radius:var(--r-sm);
  font-size:.875rem;font-weight:600;color:var(--text-soft);width:100%;text-align:left;transition:all var(--t-fast)}
.dd__item:hover{background:var(--surface-muted);color:var(--text)}
/* Where the arrow keys are. It has to look the same as a hover, or moving
   between mouse and keyboard shows two different highlights at once. */
.dd__item.is-cursor{background:var(--surface-muted);color:var(--text)}
.dd__item .lw-icon{color:var(--text-muted);flex-shrink:0}
.dd__item:hover .lw-icon{color:var(--brand)}
.dd__item--danger{color:var(--red-600)}
.dd__item--danger:hover{background:var(--red-50)}
[data-theme="dark"] .dd__item--danger:hover{background:rgba(239,68,68,.14)}
.dd__sep{height:1px;background:var(--line-soft);margin:6px 4px}
.dd__head{padding:11px 12px 9px;border-bottom:1px solid var(--line-soft);margin-bottom:4px}
.dd__label{padding:8px 11px 5px;font-size:.6875rem;font-weight:800;text-transform:uppercase;
  letter-spacing:.07em;color:var(--text-muted)}

/* Mega menu */
.mega{position:relative}
.mega__panel{position:absolute;top:100%;left:0;z-index:70;width:min(760px,90vw);
  background:var(--surface-raised);border:1px solid var(--line);border-radius:var(--r-lg);
  box-shadow:var(--sh-xl);padding:18px;display:grid;grid-template-columns:repeat(3,1fr);gap:6px 20px;
  opacity:0;visibility:hidden;transform:translateY(-6px);transition:all var(--t-fast)}
.mega:hover .mega__panel,.mega.is-open .mega__panel{opacity:1;visibility:visible;transform:translateY(0)}
.mega__group{padding:8px 0}
.mega__title{display:flex;align-items:center;gap:8px;font-size:.8125rem;font-weight:800;
  margin-bottom:7px;color:var(--text)}
.mega__title .lw-icon{color:var(--brand)}
.mega__link{display:block;padding:5px 8px;border-radius:var(--r-sm);font-size:.8125rem;color:var(--text-muted)}
.mega__link:hover{background:var(--surface-muted);color:var(--brand)}

/* Mobile drawer */
.drawer-backdrop{position:fixed;inset:0;z-index:90;background:rgba(15,17,21,.5);
  backdrop-filter:blur(2px);opacity:0;visibility:hidden;transition:all var(--t)}
.drawer-backdrop.is-open{opacity:1;visibility:visible}
.drawer{position:fixed;top:0;bottom:0;left:0;z-index:95;width:min(330px,88vw);
  background:var(--surface);box-shadow:var(--sh-xl);transform:translateX(-100%);
  transition:transform var(--t);display:flex;flex-direction:column;overflow-y:auto}
.drawer.is-open{transform:translateX(0)}
.drawer--right{left:auto;right:0;transform:translateX(100%)}
.drawer__head{display:flex;align-items:center;justify-content:space-between;
  padding:14px 16px;border-bottom:1px solid var(--line-soft);position:sticky;top:0;background:var(--surface);z-index:2}
.drawer__body{padding:12px;flex:1}
.drawer__link{display:flex;align-items:center;gap:11px;padding:11px 12px;border-radius:var(--r-md);
  font-weight:600;font-size:.9375rem;color:var(--text-soft)}
.drawer__link:hover,.drawer__link.is-active{background:var(--surface-muted);color:var(--brand)}
/* Shown wherever the main links are not, so nothing becomes unreachable. */
.menu-toggle{display:inline-grid}
@media (min-width:1440px){.menu-toggle{display:none}}

/* Tabs */
.tabs{display:flex;gap:2px;border-bottom:1px solid var(--line);overflow-x:auto;scrollbar-width:none}
.tabs::-webkit-scrollbar{display:none}
.tab{position:relative;padding:11px 15px;font-size:.875rem;font-weight:700;color:var(--text-muted);
  white-space:nowrap;border-bottom:2px solid transparent;margin-bottom:-1px;transition:all var(--t-fast)}
.tab:hover{color:var(--text)}
.tab.is-active{color:var(--brand);border-bottom-color:var(--brand)}
.tab__count{margin-left:5px;font-size:.6875rem;background:var(--surface-muted);
  padding:1px 6px;border-radius:var(--r-full);font-weight:800}

/* Breadcrumbs */
.crumbs{display:flex;align-items:center;gap:6px;font-size:.8125rem;color:var(--text-muted);flex-wrap:wrap}
.crumbs a{color:var(--text-muted)}
.crumbs a:hover{color:var(--brand);text-decoration:underline}
.crumbs .sep{opacity:.5}
.crumbs [aria-current]{color:var(--text-soft);font-weight:600}

/* Pagination */
.pagination{display:flex;align-items:center;justify-content:center;gap:5px;flex-wrap:wrap;margin-top:32px}
.pagination a,.pagination span{min-width:38px;height:38px;padding-inline:11px;display:inline-flex;
  align-items:center;justify-content:center;border-radius:var(--r-md);border:1px solid var(--line);
  font-size:.875rem;font-weight:600;color:var(--text-soft);background:var(--surface-raised);transition:all var(--t-fast)}
.pagination a:hover{border-color:var(--text);color:var(--text)}
.pagination .is-active{background:var(--ink-900);border-color:var(--ink-900);color:#fff}
[data-theme="dark"] .pagination .is-active{background:#fff;color:var(--ink-900)}
.pagination .gap{border:0;background:none;min-width:22px}

/* ------------------------------------------------------- 10. components ---- */
/* Icons, avatars, covers */
.lw-icon{display:inline-block;vertical-align:middle;flex-shrink:0}
.lw-avatar{display:inline-grid;place-items:center;border-radius:50%;object-fit:cover;
  font-weight:800;color:#fff;overflow:hidden;flex-shrink:0;line-height:1;background:var(--ink-300)}
.lw-avatar--monogram{letter-spacing:-.02em}
.lw-avatar--square{border-radius:var(--r-md)}

.lw-cover{position:relative;display:block;width:100%;object-fit:cover;overflow:hidden;background:var(--surface-muted);container-type:inline-size}
/* minmax(0,1fr): the label is centred in a grid track, so without an explicit
   floor the track sizes to the full untruncated string and drags the cover --
   and any auto-width column holding it -- out past the viewport. */
.lw-cover--generated{display:grid;grid-template-columns:minmax(0,1fr);place-items:center;padding:14px}
.lw-cover__mesh{position:absolute;inset:0;opacity:.5;
  background-image:radial-gradient(circle at 18% 12%,rgba(255,255,255,.4),transparent 42%),
                   radial-gradient(circle at 82% 88%,rgba(0,0,0,.28),transparent 48%)}
.lw-cover__text{position:relative;color:#fff;font-weight:800;font-size:clamp(.8rem,1.6vw,1.05rem);
  line-height:1.24;text-align:center;letter-spacing:-.02em;text-shadow:0 1px 10px rgba(0,0,0,.28);
  display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}
@supports (width:1cqw){
  .lw-cover--generated{padding:clamp(5px,5cqw,14px)}
  .lw-cover__text{font-size:clamp(.5rem,10.5cqw,1.05rem)}
}

/* Stars */
.lw-stars{display:inline-flex;gap:1px;vertical-align:middle;line-height:1}
.lw-star{position:relative;display:inline-block;color:var(--ink-200)}
[data-theme="dark"] .lw-star{color:rgba(255,255,255,.2)}
.lw-star svg{fill:currentColor;display:block}
.lw-star::after{content:"";position:absolute;inset:0;width:var(--fill);overflow:hidden;
  color:#e59819;background:
    linear-gradient(currentColor,currentColor) no-repeat;
  -webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='m12 2 3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01z'/%3E%3C/svg%3E") left center/auto 100% no-repeat;
  mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='m12 2 3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01z'/%3E%3C/svg%3E") left center/auto 100% no-repeat}
.lw-stars__value{font-size:.8125rem;font-weight:800;color:#a6631b;margin-left:5px;vertical-align:middle}
[data-theme="dark"] .lw-stars__value{color:#e5a53f}

/* Progress */
.lw-progress{display:block;width:100%;height:7px;border-radius:var(--r-full);
  background:var(--line-soft);overflow:hidden}
.lw-progress__fill{display:block;height:100%;border-radius:inherit;
  background:var(--brand-600);transition:width .5s var(--ease)}
.lw-progress--thin{height:4px}
.lw-progress--thick{height:10px}

/* Data viz */
.lw-sparkline{display:block;width:100%;overflow:visible}
.lw-barchart{position:relative;display:flex;align-items:flex-end;justify-content:space-evenly;
  gap:5px;width:100%;padding-top:10px}
/* Four quiet gridlines give the bars something to be read against, so a tall
   bar beside a short one is a comparison rather than a shape. */
.lw-barchart__grid{position:absolute;left:0;right:0;top:10px;bottom:22px;pointer-events:none;
  background:repeating-linear-gradient(to top,transparent,transparent calc(25% - 1px),
    var(--line-soft) calc(25% - 1px),var(--line-soft) 25%)}
/* Bars share the width evenly, but stop growing past a sensible column: a
   chart of three days used to draw three 350px slabs, which reads as a block
   diagram rather than a trend. Spacing them evenly keeps the axis honest. */
.lw-bar{flex:1 1 0;max-width:72px;display:flex;flex-direction:column;justify-content:flex-end;
  height:100%;min-width:0;position:relative;z-index:1}
.lw-bar__fill{display:block;height:var(--h);border-radius:4px 4px 1px 1px;min-height:3px;
  opacity:.92;transition:opacity var(--t-fast),transform var(--t-fast);transform-origin:bottom}
.lw-bar:hover .lw-bar__fill{opacity:1;transform:scaleY(1.02)}
/* A day with nothing on it still draws a hairline, so a quiet week reads as
   zero rather than as missing data. */
.lw-bar.is-zero .lw-bar__fill{height:2px;opacity:.28}
.lw-bar__label{font-size:.625rem;color:var(--text-muted);text-align:center;margin-top:7px;
  white-space:nowrap;overflow:visible;min-height:14px;font-variant-numeric:tabular-nums}
.lw-donut__text{font-size:19px;font-weight:800;fill:var(--text)}
.lw-trend{display:inline-flex;align-items:center;gap:3px;font-size:.75rem;font-weight:800}
.lw-trend--up{color:var(--green-600)}
.lw-trend--down{color:var(--red-600)}
.lw-trend--flat{color:var(--text-muted)}
.lw-empty{font-size:.875rem;color:var(--text-muted);text-align:center;padding:28px 0}
/* A lesson listed during a free preview but not included in it. */
.player-lesson.is-locked{opacity:.55;cursor:default}
.player-lesson.is-locked:hover{background:transparent}

/* Stat tile
   Four of these sit in a row at the top of nearly every dashboard, so they
   have to read as one instrument rather than four. Three things do that: the
   tiles stretch to a common height and pin their footnote to the bottom, so
   the numbers sit on one line even when one label wraps to two; the numbers
   are tabular, so digits fall into columns instead of jittering; and the
   whole tile is a flex column, so an icon can be added without moving
   anything else. */
.stat{background:var(--surface-raised);border:1px solid var(--line-soft);border-radius:var(--r-lg);
  padding:18px;display:flex;flex-direction:column;height:100%;
  transition:border-color var(--t-fast),box-shadow var(--t-fast)}
.stat:hover{border-color:var(--line);box-shadow:var(--sh-sm)}
/* A label is a flex row so it can carry an icon, and a flex row does not wrap
   unless told to -- which is how "Newsletter subscribers" ran out of its tile
   on a phone. */
.stat__label{font-size:.75rem;font-weight:700;text-transform:uppercase;letter-spacing:.05em;
  color:var(--text-muted);display:flex;align-items:center;flex-wrap:wrap;gap:4px 7px;
  min-width:0;overflow-wrap:break-word;min-height:1.1em}
.stat__value{font-size:1.75rem;font-weight:800;letter-spacing:-.025em;margin-top:8px;line-height:1.1;
  font-variant-numeric:tabular-nums;word-break:break-word}
.stat__foot{display:flex;align-items:center;gap:8px;margin-top:auto;padding-top:8px;
  font-size:.75rem;color:var(--text-muted)}
.stat__icon{width:34px;height:34px;border-radius:var(--r-md);display:grid;place-items:center;
  background:var(--brand-50);color:var(--brand-600);flex-shrink:0}
[data-theme="dark"] .stat__icon{background:rgba(123,66,255,.16);color:var(--brand-300)}

/* Course card */
.course-card{display:flex;flex-direction:column;background:var(--surface-raised);
  border:1px solid var(--line-soft);border-radius:var(--r-lg);overflow:hidden;height:100%;
  transition:box-shadow var(--t),transform var(--t),border-color var(--t)}
.course-card:hover{box-shadow:var(--sh-lg);transform:translateY(-3px);border-color:var(--line)}
.course-card__media{position:relative;overflow:hidden;background:var(--surface-muted)}
.course-card__media .lw-cover{transition:transform .6s var(--ease)}
.course-card:hover .course-card__media .lw-cover{transform:scale(1.045)}
.course-card__flags{position:absolute;top:9px;left:9px;display:flex;gap:5px;flex-wrap:wrap;z-index:2}
.course-card__wish{position:absolute;top:9px;right:9px;z-index:2;width:32px;height:32px;
  border-radius:50%;display:grid;place-items:center;background:rgba(255,255,255,.94);
  color:var(--ink-800);box-shadow:var(--sh-sm);opacity:0;transform:scale(.85);transition:all var(--t-fast)}
.course-card:hover .course-card__wish,.course-card__wish:focus-visible,
.course-card__wish.is-on{opacity:1;transform:scale(1)}
.course-card__wish.is-on{color:var(--red-600)}
.course-card__wish.is-on .lw-icon{fill:currentColor}
.course-card__mode{position:absolute;bottom:9px;left:9px;z-index:2}
.course-card__body{padding:13px 14px 15px;display:flex;flex-direction:column;gap:5px;flex:1}
.course-card__title{font-size:.9375rem;font-weight:800;line-height:1.32;letter-spacing:-.012em;color:var(--text)}
.course-card__meta{font-size:.75rem;color:var(--text-muted)}
.course-card__rating{display:flex;align-items:center;gap:5px;font-size:.75rem}
.course-card__facts{display:flex;align-items:center;gap:5px;font-size:.6875rem;
  color:var(--text-muted);flex-wrap:wrap}
.course-card__facts .dot{opacity:.5}
.course-card__price{display:flex;align-items:baseline;gap:7px;margin-top:auto;padding-top:7px}
.course-card__price .now{font-size:1.0625rem;font-weight:800;letter-spacing:-.02em}
.course-card__price .was{font-size:.8125rem;color:var(--text-muted);text-decoration:line-through}
.course-card__price .off{font-size:.6875rem;font-weight:800;color:var(--green-700)}
[data-theme="dark"] .course-card__price .off{color:#6ee7b7}

.course-card--row{flex-direction:row;align-items:stretch}
.course-card--row .course-card__body{padding:16px 18px}
/* The cover keeps 16:9 and the column is centred against the row, rather than
   stretched to fill it.
   It used to stretch, to avoid the gap a 141px cover leaves in a 264px row.
   But `height:100%` beats `aspect-ratio`, so a 16:9 picture was cropped into
   whatever box the *text* happened to make — 250x262 on one card, 250x239 on
   the next. With object-fit:cover that takes the sides off, and a cover with
   words on it, which is most of them, came out as "TAL RKETING". A gap is a
   gap; artwork you cannot read is a broken page.
   `align-self:center` rather than a fixed height: the column becomes exactly
   as tall as its cover, so the badges — which are positioned against the
   column — stay on the picture instead of floating above it. */
.course-card--row .course-card__media{width:300px;flex-shrink:0;align-self:center;
  margin:12px 0 12px 12px;border-radius:var(--r-md)}
.course-card--row .course-card__media>a{display:block}
@media (max-width:860px){
  .course-card--row .course-card__media{width:240px}
}
@media (max-width:700px){
  .course-card--row{flex-direction:column}
  .course-card--row .course-card__media{width:auto;align-self:stretch;
    margin:0;border-radius:0}
}

/* Carousel */
.carousel{position:relative}
.carousel__track{display:flex;gap:18px;overflow-x:auto;scroll-behavior:smooth;
  scroll-snap-type:x mandatory;padding-bottom:6px;scrollbar-width:none;-ms-overflow-style:none}
.carousel__track::-webkit-scrollbar{display:none}
.carousel__track>*{flex:0 0 clamp(230px,24vw,278px);scroll-snap-align:start}
.carousel__nav{position:absolute;top:38%;z-index:5;width:42px;height:42px;border-radius:50%;
  background:var(--surface-raised);border:1px solid var(--line);box-shadow:var(--sh-md);
  display:grid;place-items:center;color:var(--text);transition:all var(--t-fast)}
.carousel__nav:hover{background:var(--ink-900);color:#fff;border-color:var(--ink-900)}
.carousel__nav--prev{left:-18px}
.carousel__nav--next{right:-18px}
.carousel__nav[disabled]{opacity:0;pointer-events:none}
@media (max-width:1400px){.carousel__nav--prev{left:4px}.carousel__nav--next{right:4px}}
@media (max-width:640px){.carousel__nav{display:none}}

/* Dots: a page indicator for a scroll-snapped track. Not every carousel wants
   them, so they are opt-in and the JS only fills them when the element exists. */
.carousel__dots{display:flex;justify-content:center;align-items:center;gap:7px;margin-top:20px}
.carousel__dot{width:9px;height:9px;padding:0;border:0;border-radius:var(--r-full);
  background:var(--ink-200);cursor:pointer;transition:all var(--t-fast)}
[data-theme="dark"] .carousel__dot{background:rgba(255,255,255,.22)}
.carousel__dot:hover{background:var(--ink-400)}
.carousel__dot.is-on{width:26px;background:var(--brand-600)}
[data-theme="dark"] .carousel__dot.is-on{background:var(--brand-400)}

/* ---------------------------------------------- skills slider (category) --- */
/* A pinned pitch on the left, the categories sliding past on the right. */
.skills{display:grid;grid-template-columns:minmax(0,320px) minmax(0,1fr);gap:clamp(24px,4vw,56px);
  align-items:center}
.skills__pitch h2{font-size:clamp(1.6rem,1.2rem + 1.6vw,2.35rem);line-height:1.14}
.skills__pitch h2 em{font-style:italic;font-weight:600}
.skills__pitch p{margin-top:14px;color:var(--text-soft);font-size:1.0625rem;max-width:34ch}
.skills__pitch .btn{margin-top:22px}
.skills__rail{position:relative;min-width:0}

.skill-card{position:relative;display:flex;flex-direction:column;justify-content:flex-end;
  aspect-ratio:1/1;border-radius:var(--r-lg);overflow:hidden;padding:18px;
  background:var(--surface-muted);isolation:isolate}
.skill-card__art{position:absolute;inset:0;z-index:-1;background-size:cover;background-position:center}
.skill-card__art::after{content:"";position:absolute;inset:0;
  background:linear-gradient(transparent 38%,rgba(0,0,0,.18))}
.skill-card__plate{display:flex;align-items:center;justify-content:space-between;gap:12px;
  background:var(--surface-raised);color:var(--text);border-radius:var(--r-md);
  padding:15px 17px;box-shadow:var(--sh-sm);transition:transform var(--t-fast)}
.skill-card:hover .skill-card__plate{transform:translateY(-3px)}
.skill-card__name{font-weight:700;font-size:1.0625rem;letter-spacing:-.015em;line-height:1.25;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.skill-card__go{flex-shrink:0;color:var(--text-muted)}
.skill-card:hover .skill-card__go{color:var(--brand-600)}
.skills .carousel__track>*{flex:0 0 clamp(210px,23vw,260px)}
@media (max-width:900px){
  .skills{grid-template-columns:minmax(0,1fr);gap:22px}
  .skills__pitch p{max-width:none}
}

/* ---------------------------------------------------------------- marquee --- */
/* Until the script clones the row the strip is an ordinary scrollable row, so
   the logos are reachable with no JavaScript and under reduced motion. */
.marquee{overflow-x:auto;scrollbar-width:none;-ms-overflow-style:none}
.marquee::-webkit-scrollbar{display:none}
.marquee.is-running{overflow:hidden;
  -webkit-mask-image:linear-gradient(90deg,transparent,#000 5%,#000 95%,transparent);
          mask-image:linear-gradient(90deg,transparent,#000 5%,#000 95%,transparent)}
.marquee__inner{display:flex;width:max-content}
.marquee.is-running .marquee__inner{animation:marquee var(--marquee-duration,40s) linear infinite}
.marquee.is-running:hover .marquee__inner,
.marquee.is-running:focus-within .marquee__inner{animation-play-state:paused}
@keyframes marquee{to{transform:translateX(var(--marquee-shift,-50%))}}
@media (prefers-reduced-motion:reduce){
  .marquee.is-running{overflow-x:auto;-webkit-mask-image:none;mask-image:none}
  .marquee.is-running .marquee__inner{animation:none}
}

/* ------------------------------------------------------- trusted-by strip --- */
.trusted{--logo-gap:clamp(30px,5vw,66px);
  background:var(--surface-muted);padding-block:clamp(36px,5vw,60px)}
.trusted__title{text-align:center;color:var(--text-soft);font-size:clamp(1rem,.9rem + .5vw,1.25rem);
  max-width:74ch;margin-inline:auto;text-wrap:balance}
.trusted__track{margin-top:26px}
/* Each copy carries its own trailing gap, so a copy is exactly as wide as the
   distance the strip travels — the shift lands on a seam every time. */
.trusted__row{display:flex;align-items:center;gap:var(--logo-gap);padding-right:var(--logo-gap)}
.logo-mark{flex:0 0 auto;scroll-snap-align:center;display:grid;place-items:center;height:46px;
  min-width:96px;opacity:.62;filter:grayscale(1);transition:all var(--t-fast);text-decoration:none}
.logo-mark:hover{opacity:1;filter:grayscale(0)}
.logo-mark img{max-height:38px;width:auto;object-fit:contain}
/* No logo file: the name becomes the wordmark, so the strip never shows a gap. */
.logo-mark__text{font-family:var(--font-display);font-weight:800;
  font-size:clamp(.8125rem,.72rem + .45vw,1.0625rem);
  letter-spacing:.01em;color:var(--text-soft);white-space:nowrap}
.logo-mark__text .sub{display:block;font-size:.5625rem;font-weight:600;letter-spacing:.14em;
  color:var(--text-muted);text-align:center;margin-top:1px}

/* ----------------------------------------------------------- story slider --- */
.story{display:flex;flex-direction:column;gap:14px;height:100%;
  background:var(--surface-raised);border:1px solid var(--line-soft);border-radius:var(--r-lg);
  padding:24px 22px 20px;color:var(--text)}
.story__mark{font-family:Georgia,"Times New Roman",serif;font-size:2.6rem;line-height:.7;
  color:var(--text);height:26px}
/* Every quote is clamped to the same four lines so the row shares one height
   however long an individual story runs. */
.story__quote{font-size:.9375rem;line-height:1.62;color:var(--text);
  display:-webkit-box;-webkit-line-clamp:4;-webkit-box-orient:vertical;overflow:hidden;
  min-height:calc(4 * 1.62em)}
.story__who{display:flex;align-items:center;gap:11px;margin-top:auto;padding-top:6px}
.story__name{font-size:.8125rem;color:var(--text-muted)}
.story__link{font-size:.875rem;font-weight:700;color:var(--brand-700);display:inline-flex;
  align-items:center;gap:5px}
[data-theme="dark"] .story__link{color:var(--brand-300)}
.story__link:hover{text-decoration:underline}
/* The stories page shows each quote whole; only the slider needs the clamp. */
.story__quote--full{display:block;-webkit-line-clamp:none;min-height:0;overflow:visible}
.stories .carousel__track>*{flex:0 0 clamp(258px,25vw,320px)}
.stories .carousel__track{align-items:stretch}

/* ------------------------------------------------------- upload field --- */
.upload{display:flex;align-items:flex-start;gap:12px}
.upload__preview{flex:0 0 auto;display:grid;place-items:center;width:78px;height:54px;padding:5px;
  border:1px solid var(--line);border-radius:var(--r-md);background:var(--surface-muted);
  overflow:hidden}
.upload__preview.is-empty{border-style:dashed}
.upload__preview img{max-width:100%;max-height:100%;object-fit:contain}
.upload__body{flex:1 1 auto;min-width:0}

/* ------------------------------------------------- directory cards ------ */
/* The count sits beside the words on a wide screen and above them on a narrow
   one, because at 390px three columns left the heading too little room and its
   text spilled out of the card. */
.dir-card__head{display:grid;grid-template-columns:auto 1fr auto;align-items:start;
  gap:12px;column-gap:12px}
.dir-card__text{min-width:0}
.dir-card__text h2{font-size:1rem;line-height:1.3;overflow-wrap:anywhere}
.dir-card__text p{margin-top:3px;overflow-wrap:anywhere}
.dir-card__count{font-size:1.125rem;font-weight:800;font-variant-numeric:tabular-nums;
  line-height:1.2;white-space:nowrap}
@media (max-width:460px){
  .dir-card__head{grid-template-columns:auto 1fr;row-gap:8px}
  .dir-card__count{grid-column:2;justify-self:start;font-size:1.25rem}
}

/* ------------------------------------------------- upload progress ------ */
/* A large file now uploads in pieces before the form posts, which takes long
   enough that silence would read as a hang. */
.up-progress{margin:14px 0;width:100%}
.up-progress[hidden]{display:none}
.up-progress__bar{height:6px;border-radius:var(--r-full);background:var(--surface-muted);
  overflow:hidden;border:1px solid var(--line-soft)}
.up-progress__bar span{display:block;height:100%;width:0;border-radius:var(--r-full);
  background:var(--brand-600);transition:width .18s linear}
.up-progress__note{margin-top:7px;font-size:.8125rem;font-weight:600;color:var(--text-muted)}
.up-progress.is-error .up-progress__bar span{background:var(--red-600)}
.up-progress.is-error .up-progress__note{color:var(--red-600)}

/* ---------------------------------------------------- currency switch --- */
.cur-switch{display:flex;align-items:center}
.cur-switch__select{appearance:none;border:1px solid var(--line);border-radius:var(--r-full);
  background:var(--surface);color:var(--text-soft);font-size:.8125rem;font-weight:700;
  padding:6px 26px 6px 12px;cursor:pointer;line-height:1.2;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%236b7280' stroke-width='3' stroke-linecap='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right 9px center}
.cur-switch__select:hover{border-color:var(--brand-400);color:var(--text)}
.cur-switch__select:focus-visible{outline:2px solid var(--brand-500);outline-offset:2px}

/* ------------------------------------------------------- file picker --- */
/* Every `input[type=file]` on the site is upgraded into one of these at load,
   so nothing is left showing the browser's own grey "Choose File" control. The
   real input stays in the form and is laid transparently over the zone, which
   means clicking and dropping still work exactly as the browser intends — the
   script only has to draw what was chosen. */
.picker{position:relative}
.picker__zone{position:relative;display:flex;align-items:center;gap:12px;
  padding:14px 16px;border:1.5px dashed var(--line);border-radius:var(--r-md);
  background:var(--surface-muted);transition:border-color .15s,background .15s;min-height:62px}
.picker__zone:hover{border-color:var(--brand-400);background:var(--brand-50)}
[data-theme="dark"] .picker__zone:hover{background:rgba(123,66,255,.08)}
.picker.is-dragging .picker__zone{border-color:var(--brand-500);background:var(--brand-50);
  border-style:solid}
[data-theme="dark"] .picker.is-dragging .picker__zone{background:rgba(123,66,255,.12)}
.picker.is-filled .picker__zone{border-style:solid;border-color:var(--line);
  background:var(--surface-raised)}
.picker.is-error .picker__zone{border-color:var(--red-400);background:var(--red-50)}
[data-theme="dark"] .picker.is-error .picker__zone{background:rgba(239,68,68,.1)}

.picker__input{position:absolute;inset:0;width:100%;height:100%;opacity:0;cursor:pointer;
  z-index:2;font-size:0}
.picker__input:focus-visible+.picker__zone{outline:2px solid var(--brand-500);outline-offset:2px}
.picker__input:disabled{cursor:not-allowed}

.picker__icon{flex:0 0 auto;display:grid;place-items:center;width:38px;height:38px;
  border-radius:var(--r-md);background:var(--brand-100);color:var(--brand-700)}
[data-theme="dark"] .picker__icon{background:rgba(123,66,255,.18);color:var(--brand-200)}
.picker__thumb{flex:0 0 auto;width:52px;height:38px;border-radius:var(--r-sm);
  border:1px solid var(--line-soft);background:var(--surface);object-fit:contain;padding:3px}
.picker__body{flex:1 1 auto;min-width:0;display:block}
.picker__title{display:block;font-size:.875rem;font-weight:600;color:var(--text);line-height:1.35;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.picker__title b{color:var(--brand-700);font-weight:700}
[data-theme="dark"] .picker__title b{color:var(--brand-300)}
.picker__meta{display:block;font-size:.75rem;color:var(--text-muted);margin-top:2px;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.picker__clear{position:relative;z-index:3;flex:0 0 auto;display:grid;place-items:center;
  width:28px;height:28px;border-radius:50%;border:1px solid var(--line);background:var(--surface);
  color:var(--text-muted);cursor:pointer}
.picker__clear:hover{color:var(--red-600);border-color:var(--red-300);background:var(--red-50)}
.picker--sm .picker__zone{padding:10px 12px;min-height:50px}
.picker--sm .picker__icon{width:30px;height:30px}

.picker__list{margin-top:8px;border:1px solid var(--line-soft);border-radius:var(--r-md);
  max-height:190px;overflow-y:auto;background:var(--surface)}
.picker__row{display:flex;align-items:center;gap:9px;padding:7px 11px;font-size:.8125rem;
  border-bottom:1px solid var(--line-soft)}
.picker__row:last-child{border-bottom:0}
.picker__row span:first-of-type{flex:1 1 auto;min-width:0;overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap}
.picker__row em{flex:0 0 auto;font-style:normal;color:var(--text-muted);
  font-variant-numeric:tabular-nums}

/* --------------------------------------------------- bulk upload list --- */
.bulk-list{margin-top:14px;border:1px solid var(--line-soft);border-radius:var(--r-md);
  max-height:230px;overflow-y:auto}
.bulk-list__row{display:flex;align-items:center;gap:10px;padding:8px 12px;font-size:.8125rem;
  border-bottom:1px solid var(--line-soft)}
.bulk-list__name{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.bulk-list__size{flex:0 0 auto;color:var(--text-muted);font-variant-numeric:tabular-nums}
.bulk-list__clock{flex:0 0 auto;min-width:46px;text-align:right;color:var(--text-muted);
  font-variant-numeric:tabular-nums;font-weight:600}
.bulk-list__preview{flex:0 0 auto;display:inline-flex;align-items:center;gap:5px;cursor:pointer;
  padding:3px 8px;border:1px solid var(--line);border-radius:var(--r-full);font-size:.6875rem;
  font-weight:700;color:var(--text-muted);white-space:nowrap;transition:.15s}
.bulk-list__preview:hover{border-color:var(--brand-400);color:var(--brand-700)}
.bulk-list__preview input{width:13px;height:13px;margin:0;accent-color:var(--brand-600)}
.bulk-list__preview:has(input:checked){border-color:var(--brand-500);background:var(--brand-50);
  color:var(--brand-700)}
[data-theme="dark"] .bulk-list__preview:has(input:checked){background:rgba(123,66,255,.14)}
.bulk-list__total{padding:8px 12px;font-size:.75rem;font-weight:700;color:var(--text-soft);
  background:var(--surface-muted);position:sticky;bottom:0}
/* One bar per file. A single overall percentage cannot say which of five
   lectures is going up, which is the only thing anybody watching wants to
   know. Absent until an upload starts, so the list stays a list. */
.row-progress{flex:0 0 auto;width:52px;height:5px;border-radius:var(--r-full);
  background:var(--line);overflow:hidden}
.row-progress>span{display:block;height:100%;width:0;border-radius:inherit;
  background:var(--brand-600);transition:width .18s linear}
.bulk-list__row.is-uploading{background:var(--brand-50)}
[data-theme="dark"] .bulk-list__row.is-uploading{background:rgba(123,66,255,.12)}
.bulk-list__row.is-uploaded .row-progress>span{background:var(--green-600)}
.bulk-list__row.is-uploaded .bulk-list__size{color:var(--green-600)}
@media (prefers-reduced-motion:reduce){.row-progress>span{transition:none}}

/* ------------------------------------------------- pick list (checkboxes) --- */
/* A scrollable list of choices with a price, used where a form offers the whole
   catalogue and the page cannot simply grow to fit it. */
.pick{border:1px solid var(--line-soft);border-radius:var(--r-md);max-height:340px;overflow-y:auto}
.pick__row{display:flex;align-items:center;gap:12px;padding:10px 13px;cursor:pointer;
  border-bottom:1px solid var(--line-soft)}
.pick__row:last-child{border-bottom:0}
.pick__row:hover{background:var(--surface-muted)}
.pick__row:has(input:checked){background:var(--brand-50)}
[data-theme="dark"] .pick__row:has(input:checked){background:rgba(167,139,250,.12)}
.pick__body{flex:1 1 auto;min-width:0;display:flex;flex-direction:column}
.pick__price{flex:0 0 auto;font-weight:700;font-size:.875rem;font-variant-numeric:tabular-nums}

/* ------------------------------------------------ accredited add-on pick --- */
.addon-pick{border:1px solid var(--line-soft);border-radius:var(--r-md);padding:0;margin:0}
.addon-pick legend{float:left;width:100%;padding:10px 12px 8px}
.addon-pick legend+*{clear:both}
.addon-pick__row{display:flex;align-items:flex-start;gap:10px;padding:9px 12px;cursor:pointer;
  border-top:1px solid var(--line-soft)}
.addon-pick__row:hover{background:var(--surface-muted)}
.addon-pick__row:has(input:checked){background:var(--brand-50)}
[data-theme="dark"] .addon-pick__row:has(input:checked){background:rgba(167,139,250,.12)}
.addon-pick__body{flex:1 1 auto;min-width:0;display:flex;flex-direction:column;gap:1px}
.addon-pick__price{flex:0 0 auto;font-weight:700;font-size:.8125rem;white-space:nowrap}

/* ----------------------------------------------- assistant → human handoff --- */
.bot-handoff{padding:10px 12px;border-top:1px solid var(--line-soft);background:var(--surface-muted)}
.bot-handoff__state{display:block;font-size:.75rem;color:var(--text-soft);margin-bottom:7px}

/* --------------------------------------------------------- live chat desk --- */
.chatlog{display:flex;flex-direction:column;gap:10px;padding:16px;max-height:52vh;
  overflow-y:auto;background:var(--surface-muted);border-radius:var(--r-md)}
.chatlog__row{display:flex;gap:9px;max-width:78%}
.chatlog__row--mine{margin-left:auto;flex-direction:row-reverse}
.chatlog__bubble{background:var(--surface);border:1px solid var(--line-soft);
  border-radius:var(--r-lg);padding:9px 13px;font-size:.875rem;line-height:1.5}
.chatlog__row--mine .chatlog__bubble{background:var(--brand-600);color:#fff;border-color:transparent}
.chatlog__row--system{max-width:none;justify-content:center}
.chatlog__row--system .chatlog__bubble{background:transparent;border:0;color:var(--text-muted);
  font-size:.75rem;text-align:center;padding:2px}
.chatlog__meta{font-size:.625rem;color:var(--text-muted);margin-top:3px}
.chatlog__row--mine .chatlog__meta{text-align:right}

/* Alerts / messages */
.alert{display:flex;gap:11px;padding:13px 15px;border-radius:var(--r-md);
  border:1px solid;font-size:.875rem;line-height:1.55;align-items:flex-start}
.alert .lw-icon{flex-shrink:0;margin-top:1px}
.alert--info{background:var(--blue-50);border-color:#bfdbfe;color:#1e40af}
.alert--success{background:var(--green-50);border-color:#a7f3d0;color:var(--green-700)}
.alert--warning{background:var(--amber-50);border-color:var(--accent-200);color:#92400e}
.alert--error,.alert--danger{background:var(--red-50);border-color:#fecaca;color:var(--red-700)}
.alert--brand{background:var(--brand-50);border-color:var(--brand-200);color:var(--brand-800)}
[data-theme="dark"] .alert--info{background:rgba(59,130,246,.12);border-color:rgba(59,130,246,.3);color:#93c5fd}
[data-theme="dark"] .alert--success{background:rgba(16,185,129,.12);border-color:rgba(16,185,129,.3);color:#6ee7b7}
[data-theme="dark"] .alert--warning{background:rgba(245,158,11,.12);border-color:rgba(245,158,11,.3);color:#fcd34d}
[data-theme="dark"] .alert--error,[data-theme="dark"] .alert--danger{background:rgba(239,68,68,.12);border-color:rgba(239,68,68,.3);color:#fca5a5}
[data-theme="dark"] .alert--brand{background:rgba(123,66,255,.14);border-color:rgba(123,66,255,.32);color:var(--brand-200)}

/* Toasts */
.toasts{position:fixed;right:16px;bottom:82px;z-index:200;display:flex;flex-direction:column;
  gap:9px;pointer-events:none;max-width:min(380px,calc(100vw - 32px))}
.toast{pointer-events:auto;display:flex;gap:11px;align-items:flex-start;padding:13px 15px;
  border-radius:var(--r-md);background:var(--ink-900);color:#fff;box-shadow:var(--sh-lg);
  font-size:.875rem;font-weight:600;animation:toast-in .3s var(--ease)}
.toast--success{background:var(--green-600)}
.toast--error{background:var(--red-600)}
.toast--warning{background:var(--accent-600)}
.toast.is-out{animation:toast-out .25s var(--ease) forwards}
@keyframes toast-in{from{opacity:0;transform:translateY(14px) scale(.96)}to{opacity:1;transform:none}}
@keyframes toast-out{to{opacity:0;transform:translateX(24px)}}

/* Tables */
.table-wrap{overflow-x:auto;border:1px solid var(--line-soft);border-radius:var(--r-lg);background:var(--surface-raised)}
.table{width:100%;font-size:.875rem;border-collapse:collapse;min-width:640px}
.table thead th{position:sticky;top:0;background:var(--surface-muted);text-align:left;
  padding:11px 15px;font-size:.6875rem;font-weight:800;text-transform:uppercase;
  letter-spacing:.06em;color:var(--text-muted);border-bottom:1px solid var(--line);white-space:nowrap;z-index:1}
.table tbody td{padding:12px 15px;border-bottom:1px solid var(--line-soft);vertical-align:middle}
.table tbody tr:last-child td{border-bottom:0}
.table tbody tr{transition:background var(--t-fast)}
.table tbody tr:hover{background:var(--surface-muted)}
.table .num{text-align:right;font-variant-numeric:tabular-nums}
.table .nowrap{white-space:nowrap}
/* Money, counts and dates line up column-wise wherever they appear, without
   every table having to remember to say so. */
.table td .mono,.table td time,.table .money{font-variant-numeric:tabular-nums}
/* A table dropped straight into a card borrows the card's border, so it must
   not draw its own -- and its first column has to line up with the card's
   heading rather than sitting 5px inside it. */
.table-wrap--flush{border:0;border-radius:0;background:transparent}
.table-wrap--flush .table thead th:first-child,
.table-wrap--flush .table tbody td:first-child{padding-left:20px}
.table-wrap--flush .table thead th:last-child,
.table-wrap--flush .table tbody td:last-child{padding-right:20px}
/* 640px is right for a wide data table, but a compact one often sits in a
   half-width card -- there the minimum pushed the last column out of view
   behind the wrapper's scroll. Min-content still stops it squashing. */
.table-compact{min-width:0}
.table-compact tbody td,.table-compact thead th{padding:8px 12px}

/* Empty state */
.empty{text-align:center;padding:48px 20px;border:1px dashed var(--line);border-radius:var(--r-lg);
  background:var(--surface-muted)}
.empty__icon{width:52px;height:52px;border-radius:var(--r-lg);display:grid;place-items:center;
  margin:0 auto 14px;background:var(--surface-raised);color:var(--text-muted);border:1px solid var(--line-soft)}
.empty h3{font-size:1.0625rem;margin-bottom:5px}
.empty p{font-size:.875rem;color:var(--text-muted);max-width:420px;margin:0 auto 16px}

/* Accordion */
.acc{border:1px solid var(--line);border-radius:var(--r-lg);overflow:hidden;background:var(--surface-raised)}
.acc__item+.acc__item{border-top:1px solid var(--line-soft)}
.acc__head{width:100%;display:flex;align-items:center;gap:12px;padding:14px 16px;
  text-align:left;font-weight:700;font-size:.9375rem;background:var(--surface-muted);transition:background var(--t-fast)}
.acc__head:hover{background:var(--line-soft)}
.acc__head .chev{margin-left:auto;transition:transform var(--t-fast);color:var(--text-muted)}
.acc__item.is-open .acc__head .chev{transform:rotate(180deg)}
.acc__body{display:none;padding:0;background:var(--surface-raised)}
.acc__item.is-open .acc__body{display:block;animation:acc-in .22s var(--ease)}
@keyframes acc-in{from{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:none}}
.acc--plain .acc__head{background:var(--surface-raised)}
.acc--plain .acc__head:hover{background:var(--surface-muted)}

/* Modal */
.modal-backdrop{position:fixed;inset:0;z-index:150;background:rgba(15,17,21,.62);
  backdrop-filter:blur(3px);display:grid;place-items:center;padding:16px;
  opacity:0;visibility:hidden;transition:all var(--t)}
.modal-backdrop.is-open{opacity:1;visibility:visible}
.modal{width:100%;max-width:540px;max-height:88vh;overflow-y:auto;background:var(--surface-raised);
  border-radius:var(--r-xl);box-shadow:var(--sh-xl);transform:scale(.96) translateY(10px);
  transition:transform var(--t)}
.modal-backdrop.is-open .modal{transform:none}
.modal__head{display:flex;align-items:center;justify-content:space-between;gap:12px;
  padding:18px 22px;border-bottom:1px solid var(--line-soft);position:sticky;top:0;
  background:var(--surface-raised);border-radius:var(--r-xl) var(--r-xl) 0 0;z-index:2}
.modal__body{padding:22px}
.modal__foot{padding:16px 22px;border-top:1px solid var(--line-soft);display:flex;
  justify-content:flex-end;gap:10px;flex-wrap:wrap}
.modal--lg{max-width:760px}
.modal--sm{max-width:420px}

/* Skeleton */
.skeleton{position:relative;overflow:hidden;background:var(--line-soft);border-radius:var(--r-sm)}
.skeleton::after{content:"";position:absolute;inset:0;transform:translateX(-100%);
  background:linear-gradient(90deg,transparent,rgba(255,255,255,.5),transparent);
  animation:shimmer 1.5s infinite}
@keyframes shimmer{100%{transform:translateX(100%)}}

/* --------------------------------------------------- hero & marketing ----- */
.hero{position:relative;overflow:hidden;background:var(--surface-muted)}
.hero__mesh{position:absolute;inset:0;pointer-events:none;
  background-image:
    radial-gradient(52rem 26rem at 8% -8%,rgba(123,66,255,.22),transparent 62%),
    radial-gradient(40rem 24rem at 94% 4%,rgba(245,158,11,.18),transparent 64%),
    radial-gradient(36rem 22rem at 46% 108%,rgba(59,130,246,.15),transparent 62%)}
.hero__grid{position:absolute;inset:0;pointer-events:none;opacity:.5;
  background-image:linear-gradient(rgba(127,127,127,.08) 1px,transparent 1px),
                   linear-gradient(90deg,rgba(127,127,127,.08) 1px,transparent 1px);
  background-size:46px 46px;
  -webkit-mask-image:radial-gradient(ellipse 80% 60% at 50% 40%,#000,transparent);
  mask-image:radial-gradient(ellipse 80% 60% at 50% 40%,#000,transparent)}
.hero__inner{position:relative;padding-block:clamp(40px,6vw,84px)}
.hero__layout{display:grid;grid-template-columns:minmax(0,1.05fr) minmax(0,.95fr);
  gap:clamp(28px,4vw,56px);align-items:center}
@media (max-width:920px){.hero__layout{grid-template-columns:1fr}}

/* One control rather than a field with a button parked beside it. The wrapper
   is the pill; the field and the button live inside it, both sized from --hs-h
   and inset by --hs-pad on every edge they touch. That is what makes the
   button's curve concentric with the wrapper's: matching the radius alone still
   left it a different distance from the top, the bottom and the right. */
.hero-search{--hs-pad:6px;--hs-h:46px;
  display:flex;align-items:center;gap:8px;max-width:560px;
  background:var(--surface-raised);padding:var(--hs-pad);
  border-radius:var(--r-full);border:1px solid var(--line);box-shadow:var(--sh-md);
  transition:box-shadow var(--t-fast),border-color var(--t-fast)}
.hero-search:focus-within{border-color:var(--brand-500);box-shadow:var(--sh-lg),0 0 0 4px var(--ring)}
.hero-search .input{border:0;background:transparent;box-shadow:none;height:var(--hs-h)}
.hero-search .input:focus{box-shadow:none}
/* Optically centred in the rounded end, not measured from a corner that is no
   longer there: 13px from a square edge reads as crowded inside a 30px curve. */
.hero-search .input-group .lw-icon{left:16px}
.hero-search .input-group .input{padding-left:45px}

/* The one thing in the hero with real weight, because it is what the page is
   asking for: a brand gradient rather than a flat fill, a shadow tinted with
   the brand colour so the button reads as lit rather than pasted on, and a
   hairline of white inside the top edge. */
.hero-search .btn{
  --btn-bg:linear-gradient(135deg,var(--brand-500),var(--brand-700) 92%);
  flex:none;height:var(--hs-h);padding-inline:22px;gap:7px;border-radius:var(--r-full);
  font-size:.9375rem;letter-spacing:-.005em;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.22),0 6px 16px -6px rgba(91,33,182,.55)}
.hero-search .btn:hover{
  --btn-bg:linear-gradient(135deg,var(--brand-400),var(--brand-600) 92%);filter:none;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.3),0 10px 22px -8px rgba(91,33,182,.62)}
.hero-search .btn:active{transform:translateY(1px);
  box-shadow:inset 0 1px 3px rgba(0,0,0,.22)}
/* The arrow leans into the direction of travel on hover. Held still for anybody
   who has asked for less movement. */
.hero-search .btn .lw-icon{transition:transform var(--t-fast)}
.hero-search .btn:hover .lw-icon{transform:translateX(3px)}
@media (prefers-reduced-motion:reduce){.hero-search .btn:hover .lw-icon{transform:none}}
/* On a dark page a purple glow turns to mud, so the lift comes from black. */
[data-theme="dark"] .hero-search .btn{
  box-shadow:inset 0 1px 0 rgba(255,255,255,.16),0 6px 18px -6px rgba(0,0,0,.7)}
[data-theme="dark"] .hero-search .btn:hover{
  box-shadow:inset 0 1px 0 rgba(255,255,255,.22),0 10px 24px -8px rgba(0,0,0,.8)}

@media (max-width:520px){
  .hero-search{flex-direction:column;align-items:stretch;border-radius:var(--r-xl);padding:8px}
  .hero-search .input-group .lw-icon{left:13px}
  .hero-search .input-group .input{padding-left:40px}
  .hero-search .btn{width:100%;border-radius:var(--r-full)}
}

.trust-row{display:flex;align-items:center;gap:22px;flex-wrap:wrap;
  font-size:.8125rem;color:var(--text-muted);font-weight:600}
.trust-row .item{display:flex;align-items:center;gap:7px}
.trust-row .lw-icon{color:var(--green-600)}

.stat-strip{display:grid;grid-template-columns:repeat(4,1fr);gap:1px;
  background:var(--line-soft);border:1px solid var(--line-soft);border-radius:var(--r-lg);overflow:hidden}
.stat-strip>div{background:var(--surface-raised);padding:18px 16px;text-align:center}
.stat-strip .v{font-size:clamp(1.3rem,1rem + 1vw,1.75rem);font-weight:800;letter-spacing:-.03em;
  color:var(--text);line-height:1.1}
.stat-strip .l{font-size:.75rem;color:var(--text-muted);margin-top:4px;font-weight:600}
@media (max-width:640px){.stat-strip{grid-template-columns:repeat(2,1fr)}}

.feature{display:flex;gap:14px;align-items:flex-start}
.feature__icon{width:42px;height:42px;border-radius:var(--r-lg);display:grid;place-items:center;
  flex-shrink:0;background:var(--brand-50);color:var(--brand-600)}
[data-theme="dark"] .feature__icon{background:rgba(123,66,255,.16);color:var(--brand-300)}
.feature h4{font-size:.9375rem;margin-bottom:4px}
.feature p{font-size:.875rem;line-height:1.55}

.cat-tile{display:flex;flex-direction:column;gap:9px;padding:18px;border-radius:var(--r-lg);
  border:1px solid var(--line-soft);background:var(--surface-raised);transition:all var(--t)}
.cat-tile:hover{border-color:var(--brand-300);box-shadow:var(--sh-md);transform:translateY(-2px)}
.cat-tile__icon{width:40px;height:40px;border-radius:var(--r-md);display:grid;place-items:center;color:#fff}
.cat-tile h4{font-size:.9375rem}
.cat-tile .n{font-size:.75rem;color:var(--text-muted)}

.testimonial{display:flex;flex-direction:column;gap:14px;padding:22px;border-radius:var(--r-lg);
  border:1px solid var(--line-soft);background:var(--surface-raised);height:100%}
.testimonial__quote{font-size:.9375rem;line-height:1.65;color:var(--text-soft)}
.testimonial__who{display:flex;align-items:center;gap:11px;margin-top:auto}
.testimonial__who .n{font-weight:700;font-size:.875rem}
.testimonial__who .r{font-size:.75rem;color:var(--text-muted)}

.cta-band{position:relative;overflow:hidden;border-radius:var(--r-2xl);
  background:linear-gradient(120deg,var(--brand-800),var(--brand-600) 55%,var(--brand-500));
  color:#fff;padding:clamp(28px,4vw,48px)}
.cta-band::after{content:"";position:absolute;inset:0;pointer-events:none;
  background:radial-gradient(28rem 18rem at 88% 20%,rgba(255,255,255,.22),transparent 60%)}
.cta-band *{position:relative}
.cta-band h2{color:#fff}
.cta-band p{color:rgba(255,255,255,.86)}

/* --------------------------------------------------- course detail -------- */
.course-hero{background:var(--ink-900);color:#fff;padding-block:clamp(26px,3.4vw,44px)}
.course-hero h1{color:#fff;font-size:clamp(1.5rem,1.1rem + 1.6vw,2.25rem)}
.course-hero .sub{color:rgba(255,255,255,.82);font-size:1.0625rem;line-height:1.55;margin-top:10px}
.course-hero .meta{display:flex;align-items:center;gap:8px;flex-wrap:wrap;
  font-size:.8125rem;color:rgba(255,255,255,.76);margin-top:14px}
.course-hero .crumbs,.course-hero .crumbs a{color:rgba(255,255,255,.66)}
.course-hero .crumbs a:hover{color:#fff}
.course-hero .lw-stars__value{color:#f3ca8c}

/* A light card inside the dark hero: it has to state its own text colour or
   plain text inherits the hero's white and disappears. */
.buybox{background:var(--surface-raised);color:var(--text);border:1px solid var(--line);
  border-radius:var(--r-lg);overflow:hidden;box-shadow:var(--sh-lg)}
.buybox__media{position:relative;background:var(--ink-900)}
/* A button now, not a decorative span — it opens the preview, so it has to
   look and behave like something you can press, keyboard included. */
.buybox__play{position:absolute;inset:0;display:grid;place-items:center;border:0;padding:0;
  width:100%;cursor:pointer;background:rgba(15,17,21,.35);color:#fff;
  transition:background var(--t-fast)}
.buybox__play:hover{background:rgba(15,17,21,.2)}
.buybox__play:focus-visible{outline:3px solid var(--brand-400);outline-offset:-3px}
.buybox__play span{width:56px;height:56px;border-radius:50%;background:rgba(255,255,255,.95);
  color:var(--ink-900);display:grid;place-items:center;box-shadow:var(--sh-lg);
  transition:transform var(--t-fast)}
.buybox__play:hover span{transform:scale(1.07)}
.buybox__play-label{position:absolute;left:0;right:0;bottom:10px;text-align:center;color:#fff;
  font-size:.8125rem;font-weight:700;text-shadow:0 1px 6px rgba(0,0,0,.6);pointer-events:none}

/* The preview itself: a black stage that keeps the video's shape at any width. */
.preview-stage{position:relative;width:100%;aspect-ratio:16/9;background:#000;
  display:grid;place-items:center}
.preview-stage > iframe,.preview-stage > video{width:100%;height:100%;border:0;display:block;
  background:#000}
.preview-stage__fail{position:absolute;inset:auto 24px 24px;text-align:center;color:#fff;
  font-size:.875rem;font-weight:600;background:rgba(15,17,21,.75);padding:10px 14px;
  border-radius:var(--r-md)}
.player-stage__fail{position:absolute;inset:auto 24px 24px;text-align:center;color:#fff;
  font-size:.875rem;font-weight:600;background:rgba(15,17,21,.78);padding:10px 14px;
  border-radius:var(--r-md);z-index:2}

/* The lesson panel's own player: smaller than the course preview, because the
   fields below it are the point and it should not push them off the screen. */
.lesson-player{margin-bottom:18px}
.lesson-player .preview-stage{border-radius:var(--r-md);overflow:hidden;max-height:340px}
.lesson-player .preview-stage > video,.lesson-player .preview-stage > iframe{max-height:340px}
.lesson-player .preview-stage > [hidden]{display:none}
@media (max-width:640px){.preview-stage{aspect-ratio:auto;min-height:210px}}
@media (prefers-reduced-motion:reduce){.buybox__play:hover span{transform:none}}
.buybox__body{padding:20px}
.buybox__price{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap}
.buybox__price .now{font-size:1.875rem;font-weight:800;letter-spacing:-.03em}
.buybox__price .was{font-size:1rem;color:var(--text-muted);text-decoration:line-through}
.buybox__list{display:flex;flex-direction:column;gap:9px;font-size:.875rem;color:var(--text-soft)}
.buybox__list li{display:flex;gap:10px;align-items:flex-start}
.buybox__list .lw-icon{color:var(--text-muted);margin-top:2px;flex-shrink:0}

.learn-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px 26px}
@media (max-width:700px){.learn-grid{grid-template-columns:1fr}}
.learn-grid li{display:flex;gap:11px;font-size:.9375rem;line-height:1.55;color:var(--text-soft)}
.learn-grid .lw-icon{color:var(--green-600);flex-shrink:0;margin-top:3px}

.curriculum__section{border-bottom:1px solid var(--line-soft)}
.curriculum__section:last-child{border-bottom:0}
.curriculum__lesson{display:flex;align-items:center;gap:11px;padding:11px 18px;
  font-size:.875rem;border-top:1px solid var(--line-soft);color:var(--text-soft);
  background:var(--surface-raised)}
.curriculum__lesson:hover{background:var(--surface-muted)}

/* --------------------------------------------------- drag to reorder ---- */
/* The handle is the only part that starts a drag, so the rest of the row can
   still be clicked, selected and read normally. */
.grip{display:grid;place-items:center;width:26px;height:26px;flex-shrink:0;
  border-radius:var(--r-sm);color:var(--text-muted);cursor:grab;
  touch-action:none;                 /* or the browser scrolls instead of dragging */
  transition:background var(--t-fast),color var(--t-fast)}
.grip:hover{background:var(--surface-muted);color:var(--text)}
.grip:active{cursor:grabbing}
.grip:focus-visible{outline:2px solid var(--brand-500);outline-offset:1px}
.card-head .grip{margin-right:2px}

.is-dragging{opacity:.9;box-shadow:var(--sh-lg);position:relative;z-index:30;
  border-radius:var(--r-md);outline:2px solid var(--brand-400)}
.curriculum__lesson.is-dragging{background:var(--surface-raised)}
/* While a row is in hand, nothing else on the page should select or highlight
   under the pointer. */
body.is-sorting{user-select:none;cursor:grabbing}
body.is-sorting .curriculum__lesson:hover{background:var(--surface-raised)}
[data-sortable="lessons"]:empty{min-height:54px}
/* A 26px handle is fine under a mouse pointer and too small under a thumb. */
@media (pointer:coarse){
  .grip{width:38px;height:38px}
  .curriculum__lesson{padding-block:8px}
}
/* The handle costs a row about 40px of width. On a phone that was enough to
   cut "Tools, templates and downloads" down to three words, so the badges and
   the running time drop to a second line instead and the title keeps the
   first one. */
@media (max-width:560px){
  .curriculum__lesson{flex-wrap:wrap;row-gap:3px;padding-inline:12px}
  .curriculum__lesson .t{flex:1 1 55%;min-width:120px}
  .curriculum__lesson .d{margin-left:auto}
}
@media (prefers-reduced-motion:reduce){.grip{transition:none}}
.curriculum__lesson .lw-icon:first-child{color:var(--text-muted);flex-shrink:0}
.curriculum__lesson .t{flex:1;min-width:0}
.curriculum__lesson .d{font-size:.75rem;color:var(--text-muted);white-space:nowrap;font-variant-numeric:tabular-nums}
.curriculum__lesson.is-preview .t{color:var(--brand);font-weight:600}

.review-item{display:flex;gap:14px;padding-block:20px;border-bottom:1px solid var(--line-soft)}
.review-item:last-child{border-bottom:0}
.review-item__body{flex:1;min-width:0}

/* ----------------------------------------------------- fact lists -------- */
/* A marker beside a line, level with that line. The bullet was nudged down by
   a hand-picked 7px and the icon pinned to the top of the line box, so on the
   course page the dots sat under their sentences and the little person icons
   floated above theirs. Aligning to the first line's own height puts both
   where the eye expects, whatever the text does next. */
.factlist{display:flex;flex-direction:column;gap:10px}
.factlist li{display:grid;grid-template-columns:20px minmax(0,1fr);gap:12px;
  align-items:start;font-size:.9375rem;line-height:1.6;color:var(--text-soft)}
.factlist__mark{display:flex;align-items:center;justify-content:center;
  height:calc(.9375rem * 1.6);color:var(--text-muted)}
.factlist__mark .lw-icon{flex-shrink:0}
.factlist__dot{width:6px;height:6px;border-radius:50%;background:currentColor}

.instructor-card{display:grid;grid-template-columns:88px minmax(0,1fr);gap:20px;align-items:start}
.instructor-card__face{display:block;flex-shrink:0}
.instructor-card__body{min-width:0}
.instructor-card__name{font-size:1.125rem;line-height:1.3;margin-bottom:2px}
@media (max-width:560px){
  .instructor-card{grid-template-columns:minmax(0,1fr);gap:14px}
}
/* Five tracks with a label at each end. Capped, so the bars stay a summary
   rather than five near-empty rules across the whole column. */
.rating-split{flex:1;min-width:240px;max-width:460px;display:flex;flex-direction:column;gap:8px}
.rating-split__row{display:grid;grid-template-columns:46px minmax(0,1fr) 38px;
  gap:12px;align-items:center}
.instructor-card__stats{display:flex;flex-direction:column;gap:7px;font-size:.875rem;color:var(--text-soft)}
.instructor-card__stats li{display:flex;align-items:center;gap:9px}
.instructor-card__stats .lw-icon{color:var(--text-muted)}

/* --------------------------------------------------- learn / player ------- */
.player-shell{display:grid;grid-template-columns:minmax(0,1fr) 360px;min-height:100vh;background:var(--ink-950)}
@media (max-width:1100px){.player-shell{grid-template-columns:1fr}}
.player-main{display:flex;flex-direction:column;background:var(--surface);min-width:0}
.player-stage{background:#000;position:relative;aspect-ratio:16/9;max-height:72vh}
.player-stage video,.player-stage iframe{width:100%;height:100%;display:block;border:0;object-fit:contain}
.player-empty{position:absolute;inset:0;display:grid;place-items:center;color:#8a919a;
  text-align:center;padding:24px;background:#0b0c0e}

.player-side{background:var(--surface-raised);border-left:1px solid var(--line);
  display:flex;flex-direction:column;max-height:100vh;position:sticky;top:0}
@media (max-width:1100px){.player-side{position:static;max-height:none;border-left:0;border-top:1px solid var(--line)}}
.player-side__head{padding:14px 16px;border-bottom:1px solid var(--line-soft)}
.player-side__list{overflow-y:auto;flex:1}
.player-lesson{display:flex;gap:11px;padding:11px 16px;font-size:.8125rem;
  border-bottom:1px solid var(--line-soft);color:var(--text-soft);transition:background var(--t-fast);cursor:pointer}
.player-lesson:hover{background:var(--surface-muted)}
.player-lesson.is-current{background:var(--brand-50);border-left:3px solid var(--brand-600);padding-left:13px}
[data-theme="dark"] .player-lesson.is-current{background:rgba(123,66,255,.14)}
.player-lesson__check{width:17px;height:17px;border-radius:var(--r-xs);border:1.5px solid var(--line);
  flex-shrink:0;margin-top:2px;display:grid;place-items:center;background:var(--surface-raised)}
.player-lesson.is-done .player-lesson__check{background:var(--green-600);border-color:var(--green-600);color:#fff}
.player-lesson__title{font-weight:600;line-height:1.4;color:var(--text)}
.player-lesson__meta{font-size:.6875rem;color:var(--text-muted);margin-top:2px;
  display:flex;gap:6px;align-items:center}

/* --------------------------------------------------- dashboard ------------ */
.dash{display:grid;grid-template-columns:var(--sidebar-w) minmax(0,1fr);min-height:100vh}
@media (max-width:1024px){.dash{grid-template-columns:1fr}}
.dash-side{background:var(--surface-raised);border-right:1px solid var(--line-soft);
  display:flex;flex-direction:column;position:sticky;top:0;height:100vh;overflow-y:auto;
  scrollbar-width:thin;scrollbar-color:var(--line) transparent}
.dash-side::-webkit-scrollbar{width:8px}
.dash-side::-webkit-scrollbar-thumb{background:var(--line);border-radius:var(--r-full);
  border:2px solid transparent;background-clip:padding-box}
.dash-side::-webkit-scrollbar-track{background:transparent}
@media (max-width:1024px){
  .dash-side{position:fixed;inset:0 auto 0 0;z-index:95;width:270px;transform:translateX(-100%);
    transition:transform var(--t);box-shadow:var(--sh-xl)}
  .dash-side.is-open{transform:none}
}
.dash-side__head{padding:16px;border-bottom:1px solid var(--line-soft)}
.dash-side__nav{padding:12px 10px;flex:1}
.dash-side__foot{padding:12px;border-top:1px solid var(--line-soft)}
.dash-group{margin-bottom:16px}
.dash-group__label{padding:6px 10px;font-size:.625rem;font-weight:800;text-transform:uppercase;
  letter-spacing:.09em;color:var(--text-muted)}
.dash-link{display:flex;align-items:center;gap:11px;padding:9px 11px;border-radius:var(--r-md);
  font-size:.875rem;font-weight:600;color:var(--text-soft);transition:all var(--t-fast);position:relative}
.dash-link:hover{background:var(--surface-muted);color:var(--text)}
.dash-link.is-active{background:var(--brand-50);color:var(--brand-700);font-weight:700}
[data-theme="dark"] .dash-link.is-active{background:rgba(123,66,255,.16);color:var(--brand-200)}
/* A tinted pill alone is easy to lose against a hover; the accent bar says
   "you are here" at a glance, down a sidebar of twenty links. */
.dash-link.is-active::before{content:"";position:absolute;left:0;top:50%;transform:translateY(-50%);
  width:3px;height:17px;border-radius:0 3px 3px 0;background:var(--brand-600)}
.dash-link .lw-icon{color:var(--text-muted);flex-shrink:0}
.dash-link.is-active .lw-icon{color:var(--brand)}
.dash-link__badge{margin-left:auto;min-width:19px;height:19px;padding-inline:5px;border-radius:var(--r-full);
  background:var(--red-600);color:#fff;font-size:.625rem;font-weight:800;display:grid;place-items:center}

.dash-main{min-width:0;display:flex;flex-direction:column;background:var(--surface-muted)}
.dash-top{position:sticky;top:0;z-index:40;background:var(--surface);
  border-bottom:1px solid var(--line-soft);padding:12px 20px;display:flex;
  align-items:center;gap:14px;flex-wrap:wrap}
@supports (backdrop-filter:blur(8px)){
  .dash-top{background:color-mix(in srgb,var(--surface) 86%,transparent);backdrop-filter:blur(10px)}
}
/* The chat launcher floats over the bottom-right corner. Without room left
   for it, it sat on top of the last panel on every long dashboard. */
.dash-body{padding:20px 20px 88px;flex:1;min-width:0}
@media (min-width:768px){.dash-body{padding:26px 28px 96px}}
/* A rule under the page title separates "what this screen is" from "what is
   on it" -- the same job the top bar's border does one level up. */
.dash-head{margin-bottom:22px;padding-bottom:16px;border-bottom:1px solid var(--line-soft)}
.dash-head h1{font-size:clamp(1.3rem,1.1rem + .8vw,1.75rem);letter-spacing:-.025em}
.dash-head p{font-size:.875rem;color:var(--text-muted);margin-top:4px;max-width:76ch}

.role-chip{display:inline-flex;align-items:center;gap:6px;height:24px;padding-inline:9px;
  border-radius:var(--r-full);font-size:.6875rem;font-weight:800;text-transform:uppercase;
  letter-spacing:.04em;color:#fff}

/* --------------------------------------------------- chat ----------------- */
.chat{display:grid;grid-template-columns:300px minmax(0,1fr);height:calc(100vh - var(--header-h));
  border:1px solid var(--line-soft);border-radius:var(--r-lg);overflow:hidden;background:var(--surface-raised)}
@media (max-width:820px){.chat{grid-template-columns:1fr;height:auto}.chat__list{display:none}.chat.show-list .chat__list{display:flex}.chat.show-list .chat__main{display:none}}
.chat__list{border-right:1px solid var(--line-soft);display:flex;flex-direction:column;overflow:hidden}
.chat__search{padding:12px;border-bottom:1px solid var(--line-soft)}
.chat__threads{overflow-y:auto;flex:1}
.chat__thread{display:flex;gap:11px;padding:12px 14px;border-bottom:1px solid var(--line-soft);
  cursor:pointer;transition:background var(--t-fast);width:100%;text-align:left}
.chat__thread:hover{background:var(--surface-muted)}
.chat__thread.is-active{background:var(--brand-50)}
[data-theme="dark"] .chat__thread.is-active{background:rgba(123,66,255,.14)}
.chat__thread .n{font-weight:700;font-size:.875rem}
.chat__thread .p{font-size:.75rem;color:var(--text-muted);margin-top:2px}
.chat__main{display:flex;flex-direction:column;min-width:0;height:100%}
.chat__head{padding:12px 16px;border-bottom:1px solid var(--line-soft);display:flex;
  align-items:center;gap:11px;flex-shrink:0}
.chat__scroll{flex:1;overflow-y:auto;padding:18px 16px;display:flex;flex-direction:column;gap:12px;
  background:var(--surface-muted);min-height:320px}
.chat__msg{display:flex;gap:9px;max-width:76%}
.chat__msg--out{align-self:flex-end;flex-direction:row-reverse}
.chat__bubble{padding:9px 13px;border-radius:14px;font-size:.875rem;line-height:1.5;
  background:var(--surface-raised);border:1px solid var(--line-soft);word-break:break-word}
.chat__msg--out .chat__bubble{background:var(--brand-600);color:#fff;border-color:transparent}
.chat__time{font-size:.625rem;color:var(--text-muted);margin-top:3px}
.chat__msg--out .chat__time{text-align:right}
.chat__compose{padding:12px 14px;border-top:1px solid var(--line-soft);display:flex;gap:9px;
  align-items:flex-end;background:var(--surface-raised);flex-shrink:0}
.chat__compose .textarea{min-height:44px;max-height:140px;resize:none}
.chat__day{align-self:center;font-size:.6875rem;font-weight:700;color:var(--text-muted);
  background:var(--surface-raised);padding:3px 11px;border-radius:var(--r-full);border:1px solid var(--line-soft)}

/* --------------------------------------------------- chatbot -------------- */
/* The launcher is a guest on every page, so it behaves like one: no pulsing
   ring demanding attention, out of the way of the toasts, smaller on a phone
   where the screen is the scarce thing, and dismissible for anybody who does
   not want it. Dismissal is remembered in this browser only. */
.bot-dock{position:fixed;right:18px;bottom:18px;z-index:120;
  padding-bottom:env(safe-area-inset-bottom)}
.bot-launcher{position:relative;width:50px;height:50px;border-radius:50%;
  background:var(--brand-600);color:#fff;display:grid;place-items:center;
  box-shadow:0 6px 18px -6px rgba(44,20,96,.5);opacity:.94;
  transition:transform var(--t),background var(--t-fast),opacity var(--t-fast)}
.bot-launcher:hover{transform:translateY(-2px);background:var(--brand-700);opacity:1}
.bot-dock.is-gone{display:none}
.bot-dismiss{position:absolute;top:-6px;right:-6px;width:21px;height:21px;border-radius:50%;
  background:var(--surface-raised);border:1px solid var(--line);color:var(--text-muted);
  display:grid;place-items:center;box-shadow:var(--sh-xs);
  opacity:0;transform:scale(.7);transition:opacity var(--t-fast),transform var(--t-fast)}
.bot-dock:hover .bot-dismiss,.bot-dismiss:focus-visible,
.bot-launcher:focus-visible+.bot-dismiss{opacity:1;transform:none}
.bot-dismiss:hover{color:var(--red-600);border-color:var(--red-300)}
@media (max-width:640px){
  .bot-dock{right:12px;bottom:12px}
  .bot-launcher{width:44px;height:44px}
  .bot-dismiss{opacity:1;transform:none}
}
@media print{.bot-dock,.bot-panel{display:none!important}}
.bot-panel{position:fixed;right:18px;bottom:80px;z-index:121;width:min(380px,calc(100vw - 32px));
  height:min(580px,calc(100vh - 120px));background:var(--surface-raised);border:1px solid var(--line);
  border-radius:var(--r-xl);box-shadow:var(--sh-xl);display:flex;flex-direction:column;overflow:hidden;
  opacity:0;visibility:hidden;transform:translateY(14px) scale(.97);transition:all var(--t)}
.bot-panel.is-open{opacity:1;visibility:visible;transform:none}
.bot-panel__head{padding:14px 16px;background:linear-gradient(120deg,var(--brand-700),var(--brand-500));
  color:#fff;display:flex;align-items:center;gap:11px;flex-shrink:0}
.bot-panel__body{flex:1;overflow-y:auto;padding:16px;display:flex;flex-direction:column;gap:11px;
  background:var(--surface-muted)}
.bot-msg{max-width:88%;padding:10px 13px;border-radius:14px;font-size:.875rem;line-height:1.52;
  animation:fade-up .28s var(--ease)}
.bot-msg--bot{background:var(--surface-raised);border:1px solid var(--line-soft);
  border-bottom-left-radius:5px;align-self:flex-start}
.bot-msg--user{background:var(--brand-600);color:#fff;border-bottom-right-radius:5px;align-self:flex-end}
.bot-msg a{text-decoration:underline}
.bot-quick{display:flex;flex-wrap:wrap;gap:7px;padding:0 16px 12px;background:var(--surface-muted)}
.bot-quick button{padding:6px 12px;border-radius:var(--r-full);border:1px solid var(--brand-300);
  background:var(--surface-raised);color:var(--brand-700);font-size:.75rem;font-weight:700;
  transition:all var(--t-fast)}
.bot-quick button:hover{background:var(--brand-600);color:#fff;border-color:var(--brand-600)}
.bot-panel__foot{padding:11px 13px;border-top:1px solid var(--line-soft);display:flex;gap:8px;
  background:var(--surface-raised);flex-shrink:0}
.bot-card{display:flex;gap:10px;padding:9px;border:1px solid var(--line-soft);border-radius:var(--r-md);
  background:var(--surface-raised);margin-top:7px;transition:border-color var(--t-fast)}
.bot-card:hover{border-color:var(--brand-400)}
.bot-card .lw-cover{width:64px;height:40px;border-radius:var(--r-sm);flex-shrink:0}
.bot-card .t{font-size:.75rem;font-weight:700;line-height:1.35}
.bot-card .p{font-size:.6875rem;color:var(--brand-700);font-weight:800;margin-top:2px}
.bot-typing{display:flex;gap:4px;padding:12px 14px;align-self:flex-start}
.bot-typing span{width:7px;height:7px;border-radius:50%;background:var(--text-muted);
  animation:typing 1.3s infinite ease-in-out}
.bot-typing span:nth-child(2){animation-delay:.18s}
.bot-typing span:nth-child(3){animation-delay:.36s}
@keyframes typing{0%,60%,100%{opacity:.28;transform:translateY(0)}30%{opacity:1;transform:translateY(-4px)}}

/* --------------------------------------------------- footer --------------- */
.footer{background:var(--ink-900);color:var(--ink-200);margin-top:auto}
.footer a{color:var(--ink-200)}
.footer a:hover{color:#fff;text-decoration:underline;text-underline-offset:2px}
.footer h4{color:#fff;font-size:.8125rem;text-transform:uppercase;letter-spacing:.07em;margin-bottom:13px}
.footer__grid{display:grid;grid-template-columns:1.4fr repeat(4,1fr);gap:32px;
  padding-block:44px;border-bottom:1px solid rgba(255,255,255,.1)}
@media (max-width:960px){.footer__grid{grid-template-columns:repeat(2,1fr);gap:28px}}
@media (max-width:540px){.footer__grid{grid-template-columns:1fr}}
.footer__links{display:flex;flex-direction:column;gap:9px;font-size:.875rem}
.footer__bottom{display:flex;align-items:center;justify-content:space-between;gap:16px;
  padding-block:20px;font-size:.8125rem;color:var(--ink-400);flex-wrap:wrap}
.footer__social{display:flex;gap:8px}
.footer__social a{width:34px;height:34px;border-radius:var(--r-md);display:grid;place-items:center;
  background:rgba(255,255,255,.08);transition:background var(--t-fast)}
.footer__social a:hover{background:var(--brand-600);color:#fff}

/* --------------------------------------------------- auth ----------------- */
.auth{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);min-height:100vh}
@media (max-width:940px){.auth{grid-template-columns:1fr}.auth__aside{display:none}}
.auth__form{display:grid;place-items:center;padding:32px 20px;background:var(--surface)}
.auth__card{width:100%;max-width:420px}
.auth__aside{position:relative;overflow:hidden;color:#fff;padding:48px;display:flex;
  flex-direction:column;justify-content:center;
  background:linear-gradient(140deg,var(--brand-900),var(--brand-700) 48%,var(--brand-500))}
.auth__aside::after{content:"";position:absolute;inset:0;
  background:radial-gradient(30rem 20rem at 78% 18%,rgba(255,255,255,.2),transparent 60%)}
.auth__aside>*{position:relative;z-index:1}
.auth__aside h2{color:#fff}

/* --------------------------------------------------- prose ---------------- */
.prose{color:var(--text-soft);font-size:.9375rem;line-height:1.72;max-width:72ch}
/* Wider, but not unbounded: a line of eighteen words is a line nobody
   finishes. The description used to run the full column — around 150
   characters — which is why it read like a wall. */
.prose.prose-wide{max-width:86ch}
.prose>*+*{margin-top:1.05em}
.prose h2{font-size:1.125rem;margin-top:1.9em;color:var(--text);letter-spacing:-.01em}
.prose h3{font-size:1rem;margin-top:1.5em;color:var(--text)}
.prose h4{font-size:.9375rem;margin-top:1.3em;color:var(--text)}
.prose h2:first-child,.prose h3:first-child,.prose h4:first-child{margin-top:0}
.prose ul{list-style:disc;padding-left:1.35em}
.prose ol{list-style:decimal;padding-left:1.35em}
.prose li+li{margin-top:.45em}
.prose li::marker{color:var(--text-muted)}
.prose a{color:var(--brand);font-weight:600;text-decoration:underline;text-underline-offset:2px}
.prose blockquote{border-left:3px solid var(--brand-400);padding:.6em 0 .6em 1.1em;
  font-style:italic;color:var(--text-muted);background:var(--surface-muted);border-radius:0 var(--r-md) var(--r-md) 0}
.prose img{border-radius:var(--r-lg);margin-block:1.5em}
.prose pre{background:var(--ink-900);color:var(--ink-100);padding:16px;border-radius:var(--r-lg);
  overflow-x:auto;font-size:.8125rem;border:0}
.prose pre code{background:none;border:0;padding:0;color:inherit}
.prose table{font-size:.875rem;margin-block:1.5em}
.prose th,.prose td{border:1px solid var(--line);padding:9px 12px;text-align:left}
.prose th{background:var(--surface-muted);font-weight:700}
.prose hr{margin-block:2em}

/* --------------------------------------------------- certificate ---------- */
/* --------------------------------------------------- certificates --------- */
/* The certificate on screen is the same file that downloads — one drawing,
   served as an image — so what a learner shares is exactly what they saw. */
.certificate-sheet{margin:0;border-radius:var(--r-lg);overflow:hidden;background:#fffdf8;
  border:1px solid var(--line);box-shadow:var(--sh-xl)}
.certificate-sheet img{display:block;width:100%;height:auto}

.cert-actions{margin-top:22px}
.cert-actions__row{display:flex;flex-wrap:wrap;gap:10px;align-items:center}
.cert-actions__label{margin:20px 0 9px;font-size:.6875rem;font-weight:800;letter-spacing:.1em;
  text-transform:uppercase;color:var(--text-muted)}

/* One chip per destination. They colour to the network on hover rather than
   sitting there in brand colours, which would read as six live buttons. */
.share-chip{display:inline-flex;align-items:center;gap:8px;padding:9px 15px;border-radius:var(--r-full);
  border:1px solid var(--line);background:var(--surface-raised);color:var(--text);
  font-size:.8125rem;font-weight:700;line-height:1;cursor:pointer;white-space:nowrap;
  transition:transform var(--t-fast),box-shadow var(--t-fast),background var(--t-fast),
             border-color var(--t-fast),color var(--t-fast)}
.share-chip:hover{transform:translateY(-1px);box-shadow:var(--sh-md);border-color:transparent;color:#fff}
.share-chip:focus-visible{outline:2px solid var(--brand-500);outline-offset:2px}
.share-chip:hover{background:var(--ink-800)}
.share-chip--whatsapp:hover{background:#1faf54}
.share-chip--facebook:hover{background:#1877f2}
.share-chip--linkedin:hover{background:#0a66c2}
.share-chip--x:hover{background:#000}
.share-chip--email:hover{background:var(--brand-600)}

@media print{
  .certificate-sheet{border:0;border-radius:0;box-shadow:none}
  .cert-actions{display:none!important}
}

/* --------------------------------------------------- 11. utilities -------- */
.hide{display:none!important}
@media (max-width:640px){.hide-sm{display:none!important}}
@media (max-width:860px){.hide-md{display:none!important}}
@media (max-width:1080px){.hide-lg{display:none!important}}
@media (min-width:641px){.only-sm{display:none!important}}
@media (min-width:861px){.only-md{display:none!important}}
@media (min-width:1081px){.only-lg{display:none!important}}

.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
  clip:rect(0,0,0,0);white-space:nowrap;border:0}
.skip-link{position:absolute;left:-9999px;top:0;z-index:999;padding:11px 18px;
  background:var(--brand-600);color:#fff;font-weight:700;border-radius:0 0 var(--r-md) 0}
.skip-link:focus{left:0}

.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}
.w-full{width:100%}.h-full{height:100%}
.mt-0{margin-top:0}.mt-1{margin-top:4px}.mt-2{margin-top:8px}.mt-3{margin-top:12px}
.mt-4{margin-top:16px}.mt-5{margin-top:20px}.mt-6{margin-top:24px}.mt-8{margin-top:32px}.mt-10{margin-top:40px}
.mb-0{margin-bottom:0}.mb-1{margin-bottom:4px}.mb-2{margin-bottom:8px}.mb-3{margin-bottom:12px}
.mb-4{margin-bottom:16px}.mb-5{margin-bottom:20px}.mb-6{margin-bottom:24px}.mb-8{margin-bottom:32px}
.p-0{padding:0}.p-2{padding:8px}.p-3{padding:12px}.p-4{padding:16px}.p-5{padding:20px}.p-6{padding:24px}
.ml-auto{margin-left:auto}.mr-auto{margin-right:auto}.mx-auto{margin-inline:auto}

.fs-xs{font-size:.75rem}.fs-sm{font-size:.8125rem}.fs-md{font-size:.875rem}
.fs-base{font-size:.9375rem}.fs-lg{font-size:1.0625rem}.fs-xl{font-size:1.25rem}
.fw-500{font-weight:500}.fw-600{font-weight:600}.fw-700{font-weight:700}.fw-800{font-weight:800}
.tnum{font-variant-numeric:tabular-nums}
.nowrap{white-space:nowrap}
.rounded{border-radius:var(--r-md)}.rounded-lg{border-radius:var(--r-lg)}
.rounded-xl{border-radius:var(--r-xl)}.rounded-full{border-radius:var(--r-full)}
.border{border:1px solid var(--line-soft)}
.border-t{border-top:1px solid var(--line-soft)}
.border-b{border-bottom:1px solid var(--line-soft)}
.bg-muted{background:var(--surface-muted)}
.bg-raised{background:var(--surface-raised)}
.shadow{box-shadow:var(--sh-md)}
.overflow-hidden{overflow:hidden}
.relative{position:relative}
.pointer{cursor:pointer}
.scroll-x{display:flex;gap:10px;overflow-x:auto;scrollbar-width:none;padding-bottom:4px}
.scroll-x::-webkit-scrollbar{display:none}

.text-brand{color:var(--brand)}
.text-green{color:var(--green-600)}
.text-red{color:var(--red-600)}
.text-amber{color:var(--accent-600)}

.animate-in{animation:fade-up .42s var(--ease) both}
@keyframes fade-up{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}

@media print{
  .header,.footer,.topbar,.bot-launcher,.bot-panel,.dash-side,.dash-top,.no-print{display:none!important}
  body{background:#fff}
  .container{max-width:none}
}

/* ------------------------------------------------ affiliate asset picker --- */
/* A catalogue tile that can be ticked. The checkbox sits over the artwork, so
   the whole tile reads as the thing being chosen rather than a caption with a
   box beside it. */
.asset-card{position:relative;overflow:hidden;padding:0;
  transition:border-color var(--t-fast),box-shadow var(--t-fast)}
.asset-card:hover{border-color:var(--line);box-shadow:var(--sh-md)}
.asset-card.is-picked{border-color:var(--brand-500);box-shadow:0 0 0 3px var(--ring)}
.asset-card .lw-cover{width:100%;border-radius:0}
.asset-card__pick{position:absolute;top:10px;left:10px;z-index:2;display:grid;place-items:center;
  width:30px;height:30px;border-radius:var(--r-sm);background:var(--surface-raised);
  box-shadow:var(--sh-sm);cursor:pointer}
.asset-card__pick input{appearance:none;width:18px;height:18px;margin:0;cursor:pointer;
  border:1.5px solid var(--line);border-radius:var(--r-xs);background:var(--surface-raised);
  position:relative;transition:all var(--t-fast)}
.asset-card__pick input:checked{background:var(--brand-600);border-color:var(--brand-600)}
.asset-card__pick input:checked::after{content:'';position:absolute;left:5px;top:1px;width:5px;
  height:10px;border:solid #fff;border-width:0 2px 2px 0;transform:rotate(45deg)}
.asset-card__pick input:focus-visible{outline:none;box-shadow:0 0 0 3px var(--ring)}

/* Sticks to the bottom of the window while scrolling a long catalogue, because
   the courses being ticked and the button that acts on them are rarely both on
   screen at once. */
.promote-bar{position:sticky;bottom:12px;z-index:30;display:flex;align-items:center;gap:10px;
  flex-wrap:wrap;margin-bottom:16px;padding:10px 14px;border-radius:var(--r-lg);
  background:var(--surface-raised);border:1px solid var(--line);box-shadow:var(--sh-lg)}
.promote-bar[hidden]{display:none}
@media (max-width:560px){.promote-bar{bottom:0;border-radius:var(--r-md)}}


/* ------------------------------------------------------ 24. refer a friend */
.refer-hero{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:28px;align-items:center;
  padding:26px 28px;border-radius:var(--r-lg);border:1px solid var(--accent-200);
  background:linear-gradient(135deg,var(--amber-50),var(--surface-raised) 62%)}
[data-theme="dark"] .refer-hero{background:linear-gradient(135deg,rgba(245,158,11,.12),
  var(--surface-raised) 62%);border-color:rgba(245,158,11,.28)}
.refer-hero__title{font-size:1.75rem;letter-spacing:-.025em;margin-top:4px}
.refer-hero__blurb{color:var(--text-soft);font-size:.9375rem;margin-top:8px;max-width:56ch}
.refer-hero__art{display:grid;place-items:center}
@media (max-width:820px){
  .refer-hero{grid-template-columns:minmax(0,1fr)}
  .refer-hero__art{display:none}
}
.refer-link{display:grid;grid-template-columns:minmax(0,1fr) auto auto;gap:8px}
.refer-link .input{font-family:var(--font-mono,ui-monospace,monospace);font-size:.875rem}
@media (max-width:640px){.refer-link{grid-template-columns:minmax(0,1fr)}}
.refer-channels{display:flex;gap:8px;flex-wrap:wrap}
.refer-steps{display:flex;flex-direction:column;gap:14px;counter-reset:step}
.refer-steps li{display:grid;grid-template-columns:26px minmax(0,1fr);gap:12px;
  align-items:start;font-size:.875rem;line-height:1.6;color:var(--text-soft)}
.refer-steps__n{display:grid;place-items:center;width:26px;height:26px;border-radius:50%;
  background:var(--brand-100);color:var(--brand-700);font-weight:800;font-size:.75rem}
[data-theme="dark"] .refer-steps__n{background:rgba(123,66,255,.2);color:var(--brand-300)}

/* --------------------------------------------------------- 25. the 99 mark */
.logo-mark{display:inline-grid;place-items:center;width:var(--lm-size,44px);
  height:var(--lm-size,44px);color:#fff;line-height:0}
.logo-mark img{width:100%;height:100%;display:block}
.logo-mark--plate{border-radius:calc(var(--lm-size,44px) * .225);
  background:linear-gradient(135deg,#fbb30f,#e08c00);padding:calc(var(--lm-size,44px) * .13);
  box-shadow:0 10px 30px rgba(224,140,0,.35)}

/* The reveal: a sweep across the mark, then a settle. Two nines drawn by a
   single wipe reads as one gesture, which is what the artwork is. */
.logo-mark.is-animated img{
  animation:lm-rise 900ms cubic-bezier(.16,1,.3,1) both;
  -webkit-mask-image:linear-gradient(105deg,#000 40%,rgba(0,0,0,.25) 52%,#000 64%);
  mask-image:linear-gradient(105deg,#000 40%,rgba(0,0,0,.25) 52%,#000 64%);
  -webkit-mask-size:280% 100%;mask-size:280% 100%;
  animation:lm-rise 900ms cubic-bezier(.16,1,.3,1) both,
            lm-sheen 2600ms 700ms ease-in-out infinite;
}
.logo-mark.is-animated.logo-mark--plate{animation:lm-plate 900ms cubic-bezier(.16,1,.3,1) both}
@keyframes lm-rise{
  from{opacity:0;transform:scale(.82) translateY(10px)}
  60%{opacity:1;transform:scale(1.04) translateY(0)}
  to{opacity:1;transform:scale(1) translateY(0)}
}
@keyframes lm-plate{
  from{opacity:0;transform:scale(.86) rotate(-6deg);box-shadow:0 0 0 rgba(224,140,0,0)}
  to{opacity:1;transform:scale(1) rotate(0);box-shadow:0 10px 30px rgba(224,140,0,.35)}
}
@keyframes lm-sheen{
  0%,100%{-webkit-mask-position:120% 0;mask-position:120% 0}
  45%,55%{-webkit-mask-position:-20% 0;mask-position:-20% 0}
}
@media (prefers-reduced-motion:reduce){
  .logo-mark.is-animated img,.logo-mark.is-animated.logo-mark--plate{animation:none;
    -webkit-mask-image:none;mask-image:none}
}


/* The header mark gets the same entrance the app's launch screen gives it —
   the site and the app should open the same way. Once, on load, then still;
   a logo that keeps moving while somebody reads is an irritation. */
.brand__logo,.brand__mark{animation:lm-rise 760ms cubic-bezier(.16,1,.3,1) both}
.brand:hover .brand__logo{
  -webkit-mask-image:linear-gradient(105deg,#000 40%,rgba(0,0,0,.35) 52%,#000 64%);
  mask-image:linear-gradient(105deg,#000 40%,rgba(0,0,0,.35) 52%,#000 64%);
  -webkit-mask-size:280% 100%;mask-size:280% 100%;
  animation:lm-sheen 1600ms ease-in-out;
}
@media (prefers-reduced-motion:reduce){
  .brand__logo,.brand__mark,.brand:hover .brand__logo{animation:none;
    -webkit-mask-image:none;mask-image:none}
}
