/* ============================================================================
   site_aleks.css — the blocks that only /aleks-initial-knowledge-check has.

   Loaded AFTER site_landing.css, which supplies everything shared: the palette
   (the logo's coral-to-plum and nothing else), the header, the footer, the
   buttons, the FAQ accordion and the three how-it-works films. Nothing here
   invents a hue — every colour below is one of that file's custom properties.

   Also loaded after igni_chatbox.css, because this page embeds the real app input
   box from /main. The overrides for it are at the bottom and are the one place in
   this file that reaches into another component's markup; they are commented
   individually, since each one exists to beat an inline style set by the React
   bundle.

   Namespaced `ak-`. Where a block already exists on `/` it is reused by its
   `lp-` name rather than restyled here — a second visual language for the same
   thing is how two pages drift apart.

   Section grounds alternate, the same rule the landing page keeps: no two
   neighbouring sections share a background, and where two fills are close the
   boundary carries a hairline rule.

       hero  warm paper + grid
       why no answers  page fill
       what it covers  white
       try a problem   plum tint
       how it works    white            (.lp-how, from site_landing.css)
       when to use     plum tint
       FAQ             page fill        (.lp-faq)
       close           warm paper       (.lp-start)
       related         white
       footer          ink              (.lp-footer)
   ========================================================================== */

/* ── Hero ─────────────────────────────────────────────────────────────────────
   Two columns: the claim on the left, the working input box on the right. The
   box is the page's primary action and it is above the fold at every width, so
   the hero is deliberately NOT the one-screen `.lp-hero` from `/` — that shape
   is built around a film whose height has to be solved for, and there is no film
   here.
   ------------------------------------------------------------------------- */

.ak-hero {
    position: relative;
    background: var(--lp-paper);
    /* The same graph paper as the app and as `/`'s hero: two grids, 20px and
       100px, in the flame's coral. */
    background-image:
        linear-gradient(rgba(234, 116, 85, 0.08) 1px, transparent 1px),
        linear-gradient(90deg, rgba(234, 116, 85, 0.08) 1px, transparent 1px),
        linear-gradient(rgba(234, 116, 85, 0.04) 1px, transparent 1px),
        linear-gradient(90deg, rgba(234, 116, 85, 0.04) 1px, transparent 1px);
    background-size: 20px 20px, 20px 20px, 100px 100px, 100px 100px;
    padding: clamp(32px, 5vw, 64px) 0 clamp(44px, 6vw, 80px);
    overflow: hidden;
}

.ak-hero-inner {
    display: grid;
    grid-template-columns: minmax(0, 1.02fr) minmax(0, 0.98fr);
    align-items: center;
    gap: clamp(30px, 4.5vw, 56px);
    max-width: 1180px;          /* as the split hero on `/`: 1120 ran edge to edge */
}

.ak-hero-copy { text-align: left; }

/* `.lp-h1` is centred by the hero it normally lives in and capped for a two-line
   break it does not have here. */
.ak-h1 {
    font-size: clamp(2.05rem, 4.2vw, 3.1rem);
    margin-bottom: 16px;
}

/* `.lp-sub` centres itself with `margin: 0 auto`. In a left column it has to
   start at the same left edge as the headline. */
.ak-sub {
    margin: 0 0 24px;
    max-width: 40ch;
}

.ak-hero-points {
    margin: 0;
    padding: 0;
    list-style: none;
    display: grid;
    gap: 9px;
    font-size: 0.98rem;
    color: var(--lp-ink-2);
}
.ak-hero-points li {
    display: flex;
    align-items: flex-start;
    gap: 11px;
}
/* The same drawn tick as `.lp-start-points`: a glyph ✓ renders at a different
   weight and baseline in every font on the fallback stack, so it is a mask. */
.ak-hero-points li::before {
    content: "";
    width: 18px;
    height: 18px;
    margin-top: 0.22em;
    flex: 0 0 auto;
    border-radius: 50%;
    background: var(--lp-plum);
    -webkit-mask: no-repeat center/10px url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M2 6.3 4.6 9 10 3.2' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
    mask: no-repeat center/10px url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M2 6.3 4.6 9 10 3.2' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}

/* ── The input box's card ─────────────────────────────────────────────────────
   There is exactly one of these on the page: chatTextField.bundle.js mounts on a
   single #chat-box, so a second box would be dead markup. Every other call to
   action on the page scrolls here instead (see .ak-jump in static/js/site_aleks.js).
   ------------------------------------------------------------------------- */

.ak-solve {
    background: var(--lp-card);
    border: 1px solid var(--lp-line);
    border-radius: var(--lp-radius-lg);
    box-shadow: var(--lp-shadow-lg);
    padding: clamp(20px, 2.6vw, 28px);
    /* The scroll target for every other CTA. Without this the sticky header
       covers the card's top edge on arrival. */
    scroll-margin-top: calc(var(--lp-header-h) + 20px);
}

.ak-solve-title {
    margin: 0 0 6px;
    font-size: 1.22rem;
    font-weight: 700;
    letter-spacing: -0.015em;
    color: var(--lp-ink);
}
.ak-solve-sub {
    margin: 0 0 18px;
    font-size: 0.93rem;
    line-height: 1.55;
    color: var(--lp-muted);
}

.ak-solve-btn {
    width: 100%;
    margin-top: 16px;
}

.ak-solve-error {
    margin: 10px 0 0;
    font-size: 0.86rem;
    font-weight: 600;
    color: #B3261E;
    text-align: center;
}

/* The three reassurances under the button. `.lp-start-points` is centred for the
   closing band; in a narrow card it reads better as a tighter row. */
.ak-solve-points {
    margin-top: 16px;
    gap: 8px 18px;
    font-size: 0.82rem;
}

/* ── A section of prose ─────────────────────────────────────────────────────── */

/* ── Section grounds ─────────────────────────────────────────────────────────
   A page is a list of blocks and each one declares its ground in
   src/aleks_content.py, which refuses at import to let two neighbouring blocks
   share one. Three grounds, and the hairline is on all of them: `page` and
   `white` are only a few percent apart, so without a rule the seam between them
   reads as a rendering fault rather than a change of subject.

   `.lp-how` brings its own white background from site_landing.css; these rules
   are in a later stylesheet at equal specificity, so the ground wins when the
   films block is asked to sit on the tint instead. */
.ak-band {
    padding: clamp(50px, 7vw, 92px) 0;
}
.ak-ground-page  { background: var(--lp-bg); border-top: 1px solid var(--lp-line); }
.ak-ground-white { background: var(--lp-card); border-top: 1px solid var(--lp-line); }
.ak-ground-tint  { background: var(--lp-tint); border-top: 1px solid var(--lp-line); }
/* The films block keeps its own vertical rhythm but takes the ground above. */
.lp-how.ak-ground-tint { border-bottom-color: var(--lp-line); }

/* `.lp-h2` is written for a centred section head; the prose column is left-set. */
.ak-h2 {
    margin-bottom: 22px;
    font-size: clamp(1.7rem, 3.4vw, 2.5rem);
}

.ak-prose { text-align: left; }
.ak-prose p {
    margin: 0 0 18px;
    font-size: 1.04rem;
    line-height: 1.68;
    color: var(--lp-ink-2);
    max-width: 62ch;
}
.ak-prose p:last-child { margin-bottom: 0; }
.ak-prose strong { color: var(--lp-ink); font-weight: 700; }

/* The three facts. A list rather than three divs: they are one set of three
   statements about the same thing, and a screen reader should hear that. */
.ak-facts {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 14px;
    margin: 28px 0 30px;
    padding: 0;
    list-style: none;
}
.ak-fact {
    padding: 18px 20px;
    background: var(--lp-card);
    border: 1px solid var(--lp-line);
    border-radius: var(--lp-radius);
}
.ak-fact b {
    display: block;
    margin-bottom: 5px;
    font-size: 1.55rem;
    font-weight: 700;
    line-height: 1.1;
    letter-spacing: -0.02em;
    color: var(--lp-plum);
}
.ak-fact span {
    font-size: 0.9rem;
    line-height: 1.5;
    color: var(--lp-muted);
}

/* The one place on the page that raises its voice: a coral wash and a coral rule,
   because "copying backfires" is the argument the whole page is built on. Coral is
   2.9:1 on white and never carries text — it is the rule and the fill only, and
   the type inside stays ink. */
.ak-callout {
    margin: 26px 0;
    padding: 18px 22px;
    background: var(--lp-tint-warm);
    border-left: 4px solid var(--lp-coral);
    border-radius: 0 var(--lp-radius) var(--lp-radius) 0;
}
.ak-callout p {
    margin: 0;
    color: var(--lp-ink-2);
    max-width: 60ch;
}
.ak-callout strong { color: var(--lp-ink); }

/* ── Shared section head ────────────────────────────────────────────────────── */

.ak-section-head {
    max-width: 680px;
    margin: 0 auto clamp(28px, 4vw, 44px);
    text-align: center;
}
.ak-section-head .ak-h2 { margin-bottom: 14px; }
.ak-section-sub {
    margin: 0;
    font-size: 1rem;
    line-height: 1.62;
    color: var(--lp-muted);
}

/* ── What it covers ─────────────────────────────────────────────────────────── */

.ak-topics {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: clamp(16px, 2vw, 22px);
    margin: 0;
    padding: 0;
    list-style: none;
}

.ak-topic {
    display: flex;
    flex-direction: column;
    padding: 22px;
    background: var(--lp-bg);
    border: 1px solid var(--lp-line);
    border-radius: var(--lp-radius);
}
.ak-topic h3 {
    margin: 0 0 8px;
    font-size: 1.08rem;
    font-weight: 700;
    letter-spacing: -0.012em;
    color: var(--lp-ink);
}
.ak-topic > p {
    margin: 0 0 14px;
    font-size: 0.93rem;
    line-height: 1.55;
    color: var(--lp-muted);
    flex: 1;          /* the example and the link line up across the row */
}

/* The sample expression. Set on white with a hairline so it reads as a specimen
   of the thing rather than as another sentence, and in a serif with real math
   glyphs — the sans stack renders a lone `x` as a letter in a word. */
.ak-topic-ex {
    /* `.ak-topic > p { flex: 1 }` above matches this element too — it is also a
       direct child <p> — so without this the example box grows to fill the card
       alongside the body copy, and a card with no diagram ends up with a 185px
       tall box holding one line of maths. Only the body paragraph should absorb
       the slack that keeps the examples and the links aligned across a row. */
    flex: 0 0 auto;
    margin: 0 0 14px;
    padding: 9px 12px;
    background: var(--lp-card);
    border: 1px solid var(--lp-line);
    border-radius: 10px;
    font-family: "Cambria Math", Cambria, Georgia, serif;
    font-size: 1rem;
    color: var(--lp-ink);
}
.ak-topic-ex sup { font-size: 0.72em; }

.ak-topic-cta {
    align-self: flex-start;
    font-size: 0.92rem;
    font-weight: 700;
    color: var(--lp-plum-deep);
    text-decoration: none;
}
.ak-topic-cta:hover { text-decoration: underline; }

/* While a problem with a figure is being drawn and handed over. Only those take
   this path, and the click costs a round trip — the picture goes to
   /process_image to be classified and cached for the model — so the control has
   to say so rather than look dead. The two shapes it can be: a text link in a
   topic card, and the button under the worked proof. */
.ak-topic-cta.is-working,
.ak-prose .lp-btn.is-working {
    cursor: progress;
    opacity: 0.72;
}

/* ── Try a typical problem ──────────────────────────────────────────────────── */

.ak-sample-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: clamp(16px, 2vw, 22px);
    margin: 0;
    padding: 0;
    list-style: none;
}

.ak-sample {
    display: flex;
    flex-direction: column;
    gap: 14px;
    padding: 24px;
    background: var(--lp-card);
    border: 1px solid var(--lp-line);
    border-radius: var(--lp-radius);
    box-shadow: var(--lp-shadow);
}
.ak-sample-tag {
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.07em;
    text-transform: uppercase;
    color: var(--lp-muted);
}
.ak-sample-q {
    margin: 0;
    flex: 1;
    font-family: "Cambria Math", Cambria, Georgia, serif;
    font-size: 1.16rem;
    line-height: 1.45;
    color: var(--lp-ink);
}
.ak-sample-q sup { font-size: 0.72em; }
.ak-sample-btn { align-self: flex-start; }

/* ── When to use igni, and when not ─────────────────────────────────────────── */

.ak-phases {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: clamp(16px, 2vw, 22px);
    margin: 0;
    padding: 0;
    list-style: none;
}

.ak-phase {
    padding: 22px;
    background: var(--lp-card);
    border: 1px solid var(--lp-line);
    border-radius: var(--lp-radius);
}
/* The middle card is the "not during the check" one and has to read as the odd
   one out at a glance, before any of it is read. It is drawn back rather than
   drawn red: this is a rule, not an error. */
.ak-phase.is-no {
    background: var(--lp-bg);
    border-style: dashed;
}
.ak-phase h3 {
    margin: 0 0 8px;
    font-size: 1.1rem;
    font-weight: 700;
    letter-spacing: -0.012em;
    color: var(--lp-ink);
}
.ak-phase-body {
    margin: 0;
    font-size: 0.94rem;
    line-height: 1.58;
    color: var(--lp-muted);
}

.ak-phase-label {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 0 0 10px;
    font-size: 0.74rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
}
.ak-phase.is-yes .ak-phase-label { color: var(--lp-plum-deep); }
.ak-phase.is-no  .ak-phase-label { color: var(--lp-muted); }
/* Drawn marks, for the same reason as the ticks above: ✓ and ✕ are not reliably
   the same size or baseline across the fallback stack, and these two sit beside
   each other where any mismatch shows. */
.ak-phase-label::before {
    content: "";
    width: 16px;
    height: 16px;
    flex: 0 0 auto;
    border-radius: 50%;
    background: currentColor;
    -webkit-mask: no-repeat center/9px var(--ak-mark);
    mask: no-repeat center/9px var(--ak-mark);
}
.ak-phase.is-yes .ak-phase-label {
    --ak-mark: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M2 6.3 4.6 9 10 3.2' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}
.ak-phase.is-no .ak-phase-label {
    --ak-mark: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M3 3l6 6M9 3l-6 6' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E");
}

/* ── The close, and what follows it ─────────────────────────────────────────── */

.ak-start-aside {
    margin: 26px auto 0;
    max-width: 46ch;
    font-size: 0.93rem;
    color: var(--lp-ink-2);
}
.ak-start-aside a { color: var(--lp-plum-deep); font-weight: 600; }

.ak-related {
    padding: clamp(46px, 6vw, 80px) 0;
    background: var(--lp-card);
    border-top: 1px solid var(--lp-line);
}

.ak-related-grid {
    display: grid;
    /* auto-fit, because the hub lists four cards and the guides list three. A
       hard three would strand the fourth on a row of its own. */
    grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
    gap: clamp(16px, 2vw, 22px);
    margin: 0;
    padding: 0;
    list-style: none;
}
.ak-related-grid a {
    display: flex;
    flex-direction: column;
    height: 100%;
    padding: 22px;
    background: var(--lp-bg);
    border: 1px solid var(--lp-line);
    border-radius: var(--lp-radius);
    text-decoration: none;
    transition: transform 0.18s ease, box-shadow 0.18s ease, border-color 0.18s ease;
}
.ak-related-grid a:hover {
    transform: translateY(-2px);
    border-color: rgba(163, 58, 151, 0.3);
    box-shadow: var(--lp-shadow);
}
.ak-related-tag {
    display: block;
    margin-bottom: 6px;
    font-size: 0.7rem;
    font-weight: 700;
    letter-spacing: 0.07em;
    text-transform: uppercase;
    color: var(--lp-plum-deep);
}
.ak-related-grid h3 {
    margin: 0 0 8px;
    font-size: 1.05rem;
    font-weight: 700;
    letter-spacing: -0.012em;
    color: var(--lp-ink);
}
.ak-related-grid p {
    margin: 0 0 14px;
    flex: 1;
    font-size: 0.92rem;
    line-height: 1.55;
    color: var(--lp-muted);
}
.ak-related-go {
    font-size: 0.88rem;
    font-weight: 700;
    color: var(--lp-plum-deep);
}

/* The trademark line. Required — see rule 1 in src/aleks_content.py. Sits above
   the footer's bottom row, quieter than the links but not hidden. */
.ak-trademark {
    max-width: 78ch;
    margin: 30px 0 0;
    padding-top: 22px;
    border-top: 1px solid rgba(255, 255, 255, 0.12);
    font-size: 0.78rem;
    line-height: 1.6;
    color: rgba(255, 255, 255, 0.5);
}

/* ── Breadcrumbs ─────────────────────────────────────────────────────────────
   Four guides under a hub, so a visitor landing from search needs to see where
   they are and that there is a level above. Quiet by design: the trail is
   orientation, not a call to action. */

.ak-crumbs {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
    margin-bottom: 22px;
    font-size: 0.84rem;
    color: var(--lp-muted);
}
.ak-crumbs a { color: var(--lp-muted); text-decoration: none; }
.ak-crumbs a:hover { color: var(--lp-plum); text-decoration: underline; }
.ak-crumbs span[aria-current] { color: var(--lp-ink-2); }

/* ── The four moments (hub) ──────────────────────────────────────────────────
   An ordered list, because the four are a sequence a student moves through —
   placement, then the first check, then topics, then progress checks — and the
   numbers are the content, not decoration. */

.ak-moments {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: clamp(14px, 1.8vw, 20px);
    margin: 0;
    padding: 0;
    list-style: none;
}
.ak-moment {
    display: flex;
    flex-direction: column;
    padding: 22px;
    background: var(--lp-card);
    border: 1px solid var(--lp-line);
    border-radius: var(--lp-radius);
}
.ak-moment-num {
    display: grid;
    place-items: center;
    width: 30px;
    height: 30px;
    margin-bottom: 12px;
    border-radius: 50%;
    background: var(--lp-brand-grad);
    color: #fff;
    font-size: 0.9rem;
    font-weight: 700;
}
.ak-moment h3 {
    margin: 0 0 8px;
    font-size: 1.03rem;
    font-weight: 700;
    letter-spacing: -0.012em;
    color: var(--lp-ink);
}
.ak-moment p {
    margin: 0 0 14px;
    flex: 1;
    font-size: 0.91rem;
    line-height: 1.55;
    color: var(--lp-muted);
}
.ak-moment a {
    font-size: 0.9rem;
    font-weight: 700;
    color: var(--lp-plum-deep);
    text-decoration: none;
}
.ak-moment a:hover { text-decoration: underline; }

/* ── Diagrams ────────────────────────────────────────────────────────────────
   Inline SVG inside a topic card. `currentColor` carries the card's own ink, and
   the `--lp-plum` in the markup resolves here the same as in any other element —
   a custom property inherits into inline SVG, which is what keeps the tick marks
   on the brand's accent without a second hard-coded hue. */

.ak-diagram {
    margin: 0 0 14px;
    padding: 10px;
    border-radius: 12px;
    background: var(--lp-card);
    border: 1px solid var(--lp-line);
    color: var(--lp-ink-2);
}
.ak-ground-white .ak-diagram { background: var(--lp-bg); }
.ak-diagram svg {
    display: block;
    width: 100%;
    height: auto;
    max-height: 170px;
    margin: 0 auto;
}
.ak-diagram text {
    font-family: "Cambria Math", Cambria, Georgia, serif;
    font-size: 15px;
    fill: var(--lp-ink);
}
/* The unknown, and the angle labels: the one thing in the figure the student is
   being asked about. */
.ak-diagram .ak-dim {
    font-family: inherit;
    font-size: 13px;
    font-weight: 700;
    fill: var(--lp-plum-deep);
}
.ak-diagram-wide { max-width: 440px; margin-inline: auto; }

/* ── Comparison table ────────────────────────────────────────────────────────
   A real table: the argument is that two assessments answer the same four
   questions differently, and only a table puts those answers side by side. */

.ak-compare {
    width: 100%;
    margin: 0;
    border-collapse: collapse;
    background: var(--lp-bg);
    border: 1px solid var(--lp-line);
    border-radius: var(--lp-radius);
    overflow: hidden;
    font-size: 0.95rem;
    text-align: left;
}
.ak-compare th,
.ak-compare td {
    padding: 13px 15px;
    border-bottom: 1px solid var(--lp-line);
    vertical-align: top;
    color: var(--lp-ink-2);
}
.ak-compare thead th {
    background: var(--lp-tint);
    color: var(--lp-plum-deep);
    font-size: 0.8rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
}
.ak-compare tbody th {
    width: 1%;
    white-space: nowrap;
    color: var(--lp-ink);
    font-weight: 700;
}
.ak-compare tbody tr:last-child th,
.ak-compare tbody tr:last-child td { border-bottom: 0; }

/* ── Two-column proof ────────────────────────────────────────────────────────
   The page's worked example. The two blank rows are the point of it, so they are
   marked rather than left to be noticed. */

.ak-proof {
    width: 100%;
    margin: 0 0 18px;
    border-collapse: collapse;
    font-size: 0.95rem;
    text-align: left;
}
.ak-proof th,
.ak-proof td {
    padding: 9px 12px;
    border: 1px solid var(--lp-line);
    vertical-align: top;
    color: var(--lp-ink-2);
}
.ak-proof thead th {
    background: var(--lp-tint);
    color: var(--lp-plum-deep);
    font-size: 0.8rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
}
.ak-proof-blank {
    background: var(--lp-tint-warm);
    color: var(--lp-ink-2);
    font-style: italic;
}

/* ── Sticky phone CTA ─────────────────────────────────────────────────────────
   Shown only on a phone, and only between the hero box and the closing band, so
   it never covers either of the two things it points at. `hidden` is on the
   element in the markup and removed by the script, which means a failed script
   leaves nothing floating over the page rather than a permanent bar.
   ------------------------------------------------------------------------- */

.ak-sticky {
    position: fixed;
    left: 12px;
    right: 12px;
    bottom: calc(12px + env(safe-area-inset-bottom));
    z-index: 90;
    display: none;
}
.ak-sticky .lp-btn {
    width: 100%;
    box-shadow: 0 10px 28px rgba(163, 58, 151, 0.4);
}
@media (max-width: 760px) {
    .ak-sticky.is-on { display: block; }
}

/* ── The embedded app input box ───────────────────────────────────────────────
   Everything below reaches into markup owned by chatTextField.bundle.js and
   igni_qr_image_upload.js. Several rules need `!important` because the bundle
   sets those properties as inline styles, and no stylesheet rule beats an inline
   style without it — the same technique igni_chatbox.css already uses for the
   app's own width. The alternative is a bundle rebuild for a layout tweak.
   ------------------------------------------------------------------------- */

.ak-input-container { position: relative; }

/* ── Giving the field a width ─────────────────────────────────────────────────
   Every width inside the React tree is a percentage:

       #chat-box                       flex item, content-sized
         div                           width: 100%
           div                         width: 100%
             FormControl fullWidth     width: 100%
               .chat-input-wrapper     width: fit-content   (igni_chatbox.css)
                 div                   width: <data-landing-width>, max-width: 95%
                   math-field          width: 100%

   so the chain only resolves if ONE ancestor is definite. On /main that one is
   `data-landing-width="min(800px, calc(100vw - 64px))"` — an absolute length,
   which the shrink-to-fit ancestors then size themselves around.

   This page cannot use a length: the card is a grid column and its width is not
   knowable in advance. So the definite ancestor is the card itself, and every
   step between it and the field is pinned to 100% here. Leaving any one of them
   out makes the percentages circular, and a circular percentage resolves to
   min-content — which is an empty math field, i.e. the ~165px square this
   rendered as before the chain was complete.

   `min-width: 0` on the flex items because a flex item defaults to
   `min-width: auto` and would refuse to shrink below a long expression, pushing
   the card wider than its column instead of scrolling inside it (the bundle's
   own inner div already has `overflow: hidden` for that case). */
.ak-input-container .chat-box-input-flex-container {
    width: 100%;
    min-width: 0;
}
.ak-input-container #chat-box {
    width: 100%;
    min-width: 0;
}
.ak-input-container .chat-input-wrapper { width: 100%; }
.ak-input-container .chat-input-wrapper > div {
    width: 100% !important;
    /* The bundle caps this at 95%, which insets the field from the card for no
       reason once the card is the measure. */
    max-width: 100% !important;
}

/* 30px is the app's own input size, set for a full-width tutoring column. In a
   440px card it fits about four characters. The placeholder overlay is matched by
   its colour because the bundle styles it inline — same selector igni_chatbox.css
   uses for the /main mobile case. */
.ak-input-container .chat-box.landing-chat {
    font-size: 17px;
    --chat-font-size: 17px;
    padding: 10px 12px;
    border-radius: 14px;
    border: 1px solid var(--lp-line);
    /* The card already carries the elevation; a second shadow inside it reads as
       a box inside a box, and the hover lift belongs to a standalone hero box,
       not to a field sitting in a panel. */
    box-shadow: inset 0 1px 2px rgba(22, 24, 29, 0.05);
}
.ak-input-container .chat-box.landing-chat:hover {
    box-shadow: inset 0 1px 2px rgba(22, 24, 29, 0.05);
    transform: none;
    border-color: rgba(163, 58, 151, 0.35);
}
.ak-input-container .chat-box.landing-chat math-field { font-size: 17px !important; }
.ak-input-container .chat-box.landing-chat [style*="rgba(0,0,0,0.35)"] { font-size: 17px !important; }

/* The scan spinner. These rules live on /main as an inline <style> block rather
   than in a shared stylesheet, so they are restated here rather than imported
   from somewhere that does not exist. */
.landing-image-status {
    margin-top: 10px;
    text-align: center;
}
.landing-image-status.hidden { display: none; }

.image-processing-indicator {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: 10px;
    padding: 6px 14px;
    border-radius: 999px;
    background: var(--lp-bg);
    border: 1px solid var(--lp-line);
}
.indicator-ring {
    width: 16px;
    height: 16px;
    border-radius: 50%;
    border: 2px solid rgba(163, 58, 151, 0.2);
    border-top-color: var(--lp-plum);
    animation: ak-spin 0.9s linear infinite;
}
.indicator-core {
    position: absolute;
    left: 12px;
    width: 5px;
    height: 5px;
    border-radius: 50%;
    background: var(--lp-plum);
    animation: ak-pulse 1.1s ease-in-out infinite;
}
.indicator-text {
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--lp-ink-2);
}
@keyframes ak-spin  { to { transform: rotate(360deg); } }
@keyframes ak-pulse { 0%, 100% { transform: scale(0.7); opacity: 0.5; } 50% { transform: scale(1); opacity: 1; } }

/* The thumbnail strip, written into #scan-preview-strip by
   igni_qr_image_upload.js once a photo has been taken or pasted. */
.scan-preview-strip {
    display: inline-flex;
    align-items: center;
    margin-top: 12px;
}
.scan-preview-strip.hidden { display: none; }
.scan-preview-thumb-wrap {
    position: relative;
    display: inline-block;
    line-height: 0;
}
.scan-preview-thumb {
    height: 56px;
    border-radius: 10px;
    border: 1px solid var(--lp-line);
    box-shadow: var(--lp-shadow);
    object-fit: cover;
    cursor: zoom-in;
}
/* The remove badge sits on the thumbnail's corner, so it is reachable without
   covering the picture it removes. */
.scan-preview-delete {
    position: absolute;
    top: -8px;
    right: -8px;
    width: 22px;
    height: 22px;
    padding: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    border: 1px solid #fff;
    background: var(--lp-ink);
    color: #fff;
    font-size: 1rem;
    line-height: 1;
    cursor: pointer;
    transition: background-color 0.15s ease;
}
.scan-preview-delete:hover { background: #000; }

/* Full-size view of the attached photo, injected by static/js/site_aleks.js. */
#img-lightbox {
    display: none;
    position: fixed;
    inset: 0;
    z-index: 9999;
    align-items: center;
    justify-content: center;
    background: rgba(22, 24, 29, 0.88);
}
#img-lightbox.open { display: flex; }
#img-lightbox-img {
    max-width: 90%;
    max-height: 88vh;
    border-radius: 10px;
    object-fit: contain;
}
#img-lightbox-close {
    position: absolute;
    top: 14px;
    right: 18px;
    padding: 4px 10px;
    border: none;
    background: none;
    color: #fff;
    font-size: 2rem;
    line-height: 1;
    cursor: pointer;
}

/* ── Responsive ──────────────────────────────────────────────────────────────
   The breakpoints are site_landing.css's own (980 and 760), so the two pages
   change shape at the same widths rather than at two sets of numbers that
   nearly agree.
   ------------------------------------------------------------------------- */

@media (max-width: 980px) {
    /* Stacked, in source order: the headline first, the box under it. Putting the
       box first was tried and is wrong for this page — a visitor arriving from
       "aleks initial knowledge check answers" has to meet the sentence that
       answers them before they meet a control, and on a phone an `order` swap puts
       the <h1> below the fold. The copy block is short enough that the box's top
       edge still peeks into the first screen, which reads as "there is something
       below" rather than as a hidden call to action. */
    .ak-hero-inner { grid-template-columns: minmax(0, 1fr); }
    .ak-hero-copy  { text-align: center; }
    .ak-solve      { max-width: 560px; margin: 0 auto; width: 100%; }
    .ak-sub { margin-inline: auto; }
    /* Centred as a block, left-aligned inside it. `justify-items: center` centres
       each row on its own, which leaves three ragged lines of different lengths. */
    .ak-hero-points { width: max-content; max-width: 100%; margin-inline: auto; text-align: left; }

    .ak-topics,
    .ak-phases,
    .ak-moments { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 760px) {
    .ak-h1 { font-size: clamp(1.95rem, 8.4vw, 2.6rem); }

    /* One column everywhere. The facts row is the exception worth noting: three
       big figures stacked read as three separate claims, which is what they are,
       so they stay as rows rather than being shrunk to fit side by side. */
    .ak-facts,
    .ak-topics,
    .ak-sample-grid,
    .ak-phases,
    .ak-moments,
    .ak-related-grid { grid-template-columns: minmax(0, 1fr); }

    /* The comparison table restacks: each row becomes a block under its own
       heading, with the column header repeated from data-label, so the pairing
       survives for anyone reading it without seeing the columns. */
    .ak-compare thead { display: none; }
    .ak-compare,
    .ak-compare tbody,
    .ak-compare tr,
    .ak-compare th,
    .ak-compare td { display: block; width: auto; }
    .ak-compare tr {
        margin-bottom: 12px;
        border: 1px solid var(--lp-line);
        border-radius: var(--lp-radius);
        overflow: hidden;
        background: var(--lp-card);
    }
    .ak-compare tbody th {
        /* `width: auto` above does not reach this: the desktop
           `.ak-compare tbody th { width: 1% }` is one element more specific and
           survives into the stacked layout, squeezing every heading to one word
           per line. */
        width: auto;
        white-space: normal;
        padding: 13px 15px 8px;
        border-bottom: 0;
        background: var(--lp-tint);
    }
    .ak-compare tbody td { padding: 0 15px 12px; border-bottom: 0; }
    .ak-compare tbody td:first-of-type { padding-top: 12px; }
    .ak-compare tbody td::before {
        content: attr(data-label);
        display: block;
        margin-bottom: 3px;
        font-size: 0.68rem;
        font-weight: 700;
        letter-spacing: 0.07em;
        text-transform: uppercase;
        color: var(--lp-muted);
    }
    .ak-compare tbody tr:last-child td:last-child { padding-bottom: 14px; }

    .ak-prose p { font-size: 1rem; }
    .ak-sample-btn { align-self: stretch; }

    /* Room for the sticky bar, so the last thing on the page is not permanently
       under it. */
    .lp-footer { padding-bottom: calc(76px + env(safe-area-inset-bottom)); }
}

@media (prefers-reduced-motion: reduce) {
    .indicator-ring,
    .indicator-core { animation: none; }
    .ak-related-grid a:hover { transform: none; }
}
