/* Landing. A pinned WebGL flight through the curriculum, then the machines, the free tools, the subjects and the price.
   Above the flight the copy is plain. Below it every card is a lit surface: a fill tinted by what the card is about (its
   subject's hue, or the plan's violet), an inset top highlight and bottom shade, the page's soft shadow, faint starlight, and a
   halo in its hue on hover. Surfaces are separated by tone, shade and spacing, never by a border. The recipe is shared by
   .machines, .toolrow, .subjectrow and .priceline (the glass rules below). */
.story { position: relative; height: 460dvh; color: var(--text); background: var(--bg); }
.story.is-static { height: auto; }
.story__pin { position: sticky; top: 0; height: 100dvh; min-height: 560px; overflow: hidden; }
.story.is-static .story__pin { position: relative; height: auto; min-height: 0; padding: var(--sp-9) 0 var(--sp-8); }
.story__canvas { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; transition: opacity 1.4s var(--ease); }
.story.is-live .story__canvas { opacity: 1; }
.story.is-static .story__canvas, .story.is-static .story__names, .story.is-static .story__scroll, .story.is-static .story__end { display: none; }
.story__veil { position: absolute; inset: auto 0 0 0; height: 62%; pointer-events: none; background: linear-gradient(to top, color-mix(in srgb, var(--bg) 92%, transparent) 0%, color-mix(in srgb, var(--bg) 64%, transparent) 44%, transparent 100%); }

.story__names span { position: absolute; transform: translate(-50%, 0); font: 500 clamp(1.05rem, .9rem + .7vw, 1.5rem)/1 var(--font-display); letter-spacing: .01em; color: var(--tag, var(--text)); paint-order: stroke; -webkit-text-stroke: 4px var(--bg); white-space: nowrap; opacity: 0; transition: opacity .3s; pointer-events: none; }
.story__names span[data-dom="mth"] { --tag: var(--dom-mth); } .story__names span[data-dom="phy"] { --tag: var(--dom-phy); } .story__names span[data-dom="aiml"] { --tag: var(--dom-aiml); }

.story__hero, .story__caps, .story__end { position: absolute; left: max(var(--sp-5), calc((100vw - var(--shell)) / 2)); right: var(--sp-5); bottom: clamp(var(--sp-6), 11dvh, 120px); }
.story.is-static .story__hero { position: static; margin-inline: auto; width: min(100% - 2 * var(--sp-5), var(--shell)); }
.story__hero h1 { position: relative; max-width: 11ch; font-size: clamp(3.1rem, 1rem + 8vw, 8.4rem); line-height: .92; letter-spacing: -.035em; margin: 0 0 var(--sp-5); font-weight: 500; }
/* The sweep: a light band travels across the headline once every 7 s. It is a layer over the words (the same text, drawn
   in the band only), so nothing moves in the layout. It waits for the words to have risen (.is-in), and stops under reduced motion. */
.story__hero h1::after {
  content: attr(data-text) / "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  color: transparent;
  -webkit-text-fill-color: transparent;
  background: linear-gradient(105deg, transparent 40%, color-mix(in srgb, var(--lit-hi) 70%, transparent) 50%, transparent 60%) no-repeat;
  background-size: 250% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  animation: display-sheen 7s var(--ease) infinite;
}
.js-display .story__hero h1:not(.is-in)::after { display: none; }
@keyframes display-sheen {
  0% { background-position: 100% 0; }
  22% { background-position: 0% 0; }
  100% { background-position: 0% 0; }
}
@media (prefers-reduced-motion: reduce) { .story__hero h1::after { display: none; animation: none; } }
.story__sub { max-width: 34ch; margin: 0 0 var(--sp-5); color: var(--text-2); font-size: clamp(1.05rem, .95rem + .45vw, 1.35rem); line-height: 1.45; }
.story__cta { display: flex; flex-wrap: wrap; gap: var(--sp-3); align-items: center; }

.story__caps { list-style: none; margin: 0; padding: 0; pointer-events: none; }
.story__caps li { position: absolute; left: 0; bottom: 0; max-width: 14ch; font: 500 clamp(2.4rem, 1rem + 5.2vw, 5.6rem)/.98 var(--font-display); letter-spacing: -.03em; opacity: 0; will-change: opacity, transform; text-wrap: balance; }
.story__caps small { display: block; margin-top: var(--sp-3); font: 400 clamp(.95rem, .9rem + .3vw, 1.15rem)/1.4 var(--font-ui); letter-spacing: 0; color: var(--text-2); max-width: 32ch; }
.story.is-static .story__caps { position: static; margin: var(--sp-7) auto 0; width: min(100% - 2 * var(--sp-5), var(--shell)); display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: var(--sp-5); }
.story.is-static .story__caps li { position: static; opacity: 1; font-size: clamp(1.4rem, 1rem + 1.4vw, 2rem); }

.story__end { opacity: 0; pointer-events: none; }
.story__end h2 { max-width: 11ch; font-size: clamp(2.6rem, 1rem + 6vw, 6.4rem); line-height: .94; letter-spacing: -.03em; margin: 0 0 var(--sp-5); font-weight: 500; }
.story__end.is-on { pointer-events: auto; }
.story__scroll { position: absolute; left: 50%; bottom: var(--sp-4); transform: translateX(-50%); margin: 0; color: var(--text-3); font-size: .85rem; letter-spacing: .04em; transition: opacity .4s; }

@media (max-width: 720px) {
  .story { height: 520dvh; }
  .story__hero h1 { max-width: 9ch; }
  .story__veil { height: 70%; }
}
@media (prefers-reduced-motion: reduce) { .story__canvas { transition: none; } }

/* ---- Lit glass: the card recipe of the lower landing. --tint is what the card is about (a subject's hue; the price card sets the
   plan's violet). The fill is a vertical gradient of surface tones tinted by --tint; the highlight and the shade are inset shadows;
   the page's soft shadow lifts the card off the ground. The faint starlight sits in ::before, under the card's content. */
.machines .glass, .toolrow .glass, .subjectrow .glass, .priceline .glass {
  --glass-top: color-mix(in srgb, var(--tint, var(--surface-2)) 16%, var(--surface-2));
  --glass-bottom: color-mix(in srgb, var(--tint, var(--bg-raised)) 5%, var(--bg-raised));
  --glass-lit: color-mix(in srgb, var(--text) 14%, transparent);
  --glass-shade: color-mix(in srgb, var(--bg) 70%, transparent);
  --glass-dust: color-mix(in srgb, var(--text) 22%, transparent);
  position: relative;
  isolation: isolate;
  display: block;
  color: var(--text);
  text-decoration: none;
  border-radius: var(--r-lg);
  background-image: linear-gradient(180deg, var(--glass-top), var(--glass-bottom));
  /* one layer here (the star dust is the ::before): reset the shared .glass tiling, or the gradient repeats every 180px */
  background-size: auto;
  background-repeat: no-repeat;
  box-shadow: inset 0 1px 0 var(--glass-lit), inset 0 -22px 30px -24px var(--glass-shade), var(--shadow-1);
  transition: transform .3s var(--ease), box-shadow .3s var(--ease);
}
.machines .glass::before, .toolrow .glass::before, .subjectrow .glass::before, .priceline .glass::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  pointer-events: none;
  background-image:
    radial-gradient(circle at 18px 24px, var(--glass-dust) 0 .8px, transparent 1.2px),
    radial-gradient(circle at 62px 12px, var(--glass-dust) 0 .6px, transparent 1px),
    radial-gradient(circle at 104px 30px, var(--glass-dust) 0 .9px, transparent 1.3px),
    radial-gradient(circle at 150px 18px, var(--glass-dust) 0 .7px, transparent 1.1px),
    radial-gradient(circle at 36px 70px, var(--glass-dust) 0 .6px, transparent 1px),
    radial-gradient(circle at 88px 66px, var(--glass-dust) 0 .8px, transparent 1.2px),
    radial-gradient(circle at 132px 78px, var(--glass-dust) 0 .6px, transparent 1px),
    radial-gradient(circle at 170px 62px, var(--glass-dust) 0 .9px, transparent 1.3px),
    radial-gradient(circle at 10px 112px, var(--glass-dust) 0 .7px, transparent 1.1px),
    radial-gradient(circle at 58px 120px, var(--glass-dust) 0 .6px, transparent 1px),
    radial-gradient(circle at 112px 108px, var(--glass-dust) 0 .8px, transparent 1.2px),
    radial-gradient(circle at 146px 126px, var(--glass-dust) 0 .6px, transparent 1px);
  background-size: 180px 180px;
}
.toolrow a.glass:hover, .toolrow a.glass:focus-visible, .subjectrow a.glass:hover, .subjectrow a.glass:focus-visible,
.machines .machine:hover .glass, .machines .machine:focus-visible .glass {
  transform: translateY(-2px);
  box-shadow: inset 0 1px 0 var(--glass-lit), inset 0 -22px 30px -24px var(--glass-shade), var(--shadow-1), 0 0 14px -5px color-mix(in srgb, var(--tint, var(--cyan)) 70%, transparent);
}
/* One glint crosses a tool or subject card on hover (as the primary button does): a light band, tinted by the card's hue. */
.toolrow a.glass, .subjectrow a.glass { overflow: hidden; }
.toolrow a.glass::after, .subjectrow a.glass::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background: linear-gradient(100deg, transparent 36%, color-mix(in srgb, var(--tint, var(--text)) 22%, transparent) 50%, transparent 64%);
  transform: translateX(-120%);
}
.toolrow a.glass:hover::after, .toolrow a.glass:focus-visible::after, .subjectrow a.glass:hover::after, .subjectrow a.glass:focus-visible::after { animation: card-glint .9s var(--ease) both; }
@keyframes card-glint { to { transform: translateX(120%); } }
@media (prefers-reduced-motion: reduce) {
  .machines .glass, .toolrow .glass, .subjectrow .glass, .priceline .glass { transition: none; }
  .toolrow a.glass:hover, .toolrow a.glass:focus-visible, .subjectrow a.glass:hover, .subjectrow a.glass:focus-visible,
  .machines .machine:hover .glass, .machines .machine:focus-visible .glass { transform: none; }
  .toolrow a.glass::after, .subjectrow a.glass::after { display: none; }
}
:root[data-theme="light"] .machines .glass, :root[data-theme="light"] .toolrow .glass, :root[data-theme="light"] .subjectrow .glass, :root[data-theme="light"] .priceline .glass {
  --glass-top: color-mix(in srgb, var(--tint, var(--surface-2)) 10%, var(--surface));
  --glass-bottom: color-mix(in srgb, var(--tint, var(--surface-2)) 3%, var(--surface-2));
  --glass-lit: color-mix(in srgb, var(--surface) 92%, transparent);
  --glass-shade: color-mix(in srgb, var(--text) 9%, transparent);
  --glass-dust: transparent;
}
:root[data-theme="light"] .machines .glass::before, :root[data-theme="light"] .toolrow .glass::before, :root[data-theme="light"] .subjectrow .glass::before, :root[data-theme="light"] .priceline .glass::before {
  background-image: none;
}

/* The art: glyphs, galaxies, machine pictures and the small check and arrow. Every stroke is currentColor (the hue it sits in). */
.art { fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; overflow: visible; }
.art .f { fill: currentColor; stroke: none; }
.art .fade { opacity: .5; }
.art .soft { opacity: .42; }
.art .thin { stroke-width: 1.2; }
.art .bold { stroke-width: 3; }
.art .dash { stroke-dasharray: 3 3; }
.art .ghost { fill: currentColor; fill-opacity: .24; stroke: none; }
.art .bone { fill: var(--bone); stroke: none; }
.art .plate { fill: color-mix(in srgb, var(--text) 6%, transparent); stroke: color-mix(in srgb, var(--text-3) 45%, transparent); stroke-width: 1.2; }
.art .body { fill: color-mix(in srgb, var(--text) 9%, transparent); stroke-width: 1.5; }
.art .teeth { fill: none; }
.art .orbit { stroke-width: 1.2; opacity: .6; }
.galaxy .disc { fill: currentColor; fill-opacity: .09; stroke: none; }
.galaxy .arm { stroke-width: 3.2; stroke-dasharray: 0 3.6; }
.galaxy .core { fill: var(--bone); stroke: none; }

/* Machines: the figure in a glass stage, its caption under it. Until a machine mounts, its static picture fills the stage. */
.machines { padding: var(--sp-9) 0 var(--sp-8); }
.machines h2 { font-size: clamp(2rem, 1rem + 3vw, 3.6rem); margin: 0 0 var(--sp-6); max-width: 14ch; letter-spacing: -.025em; }
.machines__grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--sp-4); }
.machines .machine { gap: var(--sp-4); }
.machines .machine__stage { padding: var(--sp-3); }
.machines a.machine .machine__cap { opacity: 1; padding: 0 var(--sp-2); }
.machine__poster { display: block; width: 100%; height: 100%; color: var(--tint); }
@media (max-width: 720px) { .machines__grid { grid-template-columns: minmax(0, 1fr); gap: var(--sp-5); } }

/* Free tools: a grid of cards, four across. The subject order keeps each subject in one run: mathematics (eight) and AI & ML
   (eight) fill two rows each; physics has two tools, each spanning two columns, so the grid never leaves a hole. */
.toolrow { padding: var(--sp-8) 0 var(--sp-7); }
.toolrow__head { display: flex; justify-content: space-between; align-items: baseline; gap: var(--sp-4); margin-bottom: var(--sp-5); }
.toolrow__head h2 { margin: 0; font-size: clamp(1.8rem, 1rem + 2.4vw, 3rem); letter-spacing: -.025em; }
.toolrow__head a { font-weight: 600; }
.toolgrid { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--sp-3); }
.toolgrid__item { display: flex; min-width: 0; }
.toolgrid__item[data-dom="phy"] { grid-column: span 2; }
.toolrow .tool { display: flex; align-items: center; gap: var(--sp-4); width: 100%; padding: var(--sp-3) var(--sp-4) var(--sp-3) var(--sp-3); }
.tool__glyph { flex: none; display: grid; place-items: center; width: 64px; height: 64px; border-radius: var(--r-lg); color: var(--tint); background: color-mix(in srgb, var(--tint) 14%, var(--bg-raised)); }
.tool__glyph .art { width: 40px; height: 40px; }
.tool__text { display: grid; gap: var(--sp-1); min-width: 0; }
.tool__name { font: 500 clamp(1.05rem, .95rem + .35vw, 1.22rem)/1.2 var(--font-display); color: var(--text); }
.toolgrid__item[data-dom="phy"] .tool__glyph { width: 84px; height: 84px; }
.toolgrid__item[data-dom="phy"] .tool__glyph .art { width: 52px; height: 52px; }
.toolgrid__item[data-dom="phy"] .tool__name { font-size: clamp(1.2rem, 1rem + .6vw, 1.5rem); }
@media (max-width: 1000px) {
  .toolgrid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .toolgrid__item[data-dom="phy"] { grid-column: auto; }
}
@media (max-width: 600px) {
  .toolgrid { gap: var(--sp-2); }
  .toolrow .tool { flex-direction: column; align-items: flex-start; gap: var(--sp-3); padding: var(--sp-4); }
  .tool__glyph, .toolgrid__item[data-dom="phy"] .tool__glyph { width: 52px; height: 52px; }
  .tool__glyph .art, .toolgrid__item[data-dom="phy"] .tool__glyph .art { width: 32px; height: 32px; }
  .toolgrid__item[data-dom="phy"] .tool__name, .tool__name { font-size: 1rem; }
}

/* Subjects: one galaxy tile per subject. The name carries the hue, the line says what the subject is for, the size (administrators
   only) and the arrow sit in the corners. */
.subjectrow { padding: var(--sp-7) 0 var(--sp-8); }
.subjectrow__grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--sp-4); }
.subjectrow .subject { position: relative; display: grid; gap: var(--sp-3); align-content: start; min-height: 100%; padding: var(--sp-5); }
.subject__mark { display: block; width: 116px; height: 116px; color: var(--tint); }
.subject__mark .art { display: block; width: 100%; height: 100%; }
.subject__text { display: grid; gap: var(--sp-2); }
.subject__name { font: 500 clamp(1.6rem, 1.2rem + 1vw, 2.3rem)/1.05 var(--font-display); letter-spacing: -.02em; color: var(--tint); }
.subject__line { color: var(--text-2); font-size: 1rem; line-height: 1.45; max-width: 30ch; }
.subject__count { position: absolute; top: var(--sp-5); right: var(--sp-5); font-size: .95rem; color: var(--text-2); }
.subject__go { position: absolute; right: var(--sp-5); bottom: var(--sp-5); color: var(--tint); }
.subject__go .art { display: block; width: 22px; height: 22px; }
@media (max-width: 900px) {
  .subjectrow__grid { grid-template-columns: minmax(0, 1fr); }
  .subjectrow .subject { grid-template-columns: 96px minmax(0, 1fr); align-items: center; gap: var(--sp-4); padding-right: var(--sp-6); }
  .subject__mark { width: 96px; height: 96px; }
}

/* Price: the free account against the full workspace, the figures in the plan's violet, one action. */
.priceline { padding: var(--sp-6) 0 var(--sp-6); }
.priceline .priceline__card { display: grid; gap: var(--sp-5); padding: var(--sp-6); --tint: var(--violet); }
.priceline .priceline__card h2 { margin: 0; max-width: 20ch; font: 500 clamp(1.8rem, 1.1rem + 2.4vw, 3rem)/1.05 var(--font-display); letter-spacing: -.025em; }
.plans { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--sp-3); }
.plan { display: grid; align-content: start; gap: var(--sp-4); padding: var(--sp-5); border-radius: var(--r-lg); }
.plan--free { background: color-mix(in srgb, var(--bg) 46%, transparent); }
.plan--plan { background: color-mix(in srgb, var(--violet) 16%, var(--surface)); }
.plan__name { margin: 0; font: 500 clamp(1.2rem, 1rem + .6vw, 1.5rem)/1.2 var(--font-display); color: var(--text); }
.plan--plan .plan__name { color: var(--violet-text); }
.plan__price { margin: 0; font: 500 clamp(1.6rem, 1.1rem + 1.6vw, 2.4rem)/1 var(--font-display); letter-spacing: -.02em; color: var(--text); }
.plan__list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--sp-3); }
.plan__list li { display: grid; grid-template-columns: 18px minmax(0, 1fr); gap: var(--sp-3); align-items: start; color: var(--text-2); line-height: 1.4; }
.plan__list .art { width: 18px; height: 18px; margin-top: 2px; color: var(--green); }
.plan--plan .plan__list .art { color: var(--violet-text); }
.priceline .btn { justify-self: start; }
@media (max-width: 640px) { .plans { grid-template-columns: minmax(0, 1fr); } }
