x
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
<div class="tw:p-6 tw:max-w-7xl tw:mx-auto tw:space-y-8"> <div class="callout"> <p class="tw:mb-1 tw:text-sm tw:font-mono"> <strong>AI SEARCH RESULT CARD (4.1 · WIRE):</strong> the UI already exists in <code>projects/ai_search</code><br> <strong>SCAN-FED:</strong> Eligibility pill (D3) | "Why this fits" reason (D1·D3·D4) | Fit-tags (D4) </p> <p class="tw:mb-0 tw:text-sm"> <strong>Now wired:</strong> the eligibility pill is computed end-to-end (mock D3 rules + grades → <code>Scan::Eligibility.evaluate</code> → <code>Scan::EligibilityBadge</code>), the same path the course pages use. Still curated (would come from real D1/D4 in production): the "Why this fits" reason and the fit-tags. Honesty rule: only assert "grounded" when D2 provenance exists. </p> </div> <div class="tw:border-t tw:pt-6"> <h2 class="h4 tw:mb-4">Wired card — eligible</h2> <div class="tw:max-w-[760px] tw:space-y-3"> <article class="school-card tw:group"> <div class="school-card-body"> <div class="school-card-header school-card-header-stack"> <div class="school-card-identity"> <span class="school-card-initials" aria-hidden="true">GHS</span> <div class="school-card-heading"> <div class="tw:flex tw:items-center tw:flex-wrap tw:gap-x-2 tw:gap-y-1 tw:min-w-0"> <h3 class="school-card-name tw:flex tw:items-center tw:gap-1.5 tw:min-w-0"> <span class="tw:truncate">Greenford High School</span> <i class="fa-solid fa-circle-check school-card-verified tw:shrink-0" role="img" aria-label="Verified" title="Verified on ApplicaaOne"></i> </h3> <span class="badge-eligibility badge-eligibility-eligible"><i class="fa-light fa-circle-check tw:mr-1" aria-hidden="true"></i>Eligible</span> </div> <p class="school-card-meta">Lady Margaret Rd, Southall UB1 2GU · 1.2 mi away</p> </div> </div> <div class="school-card-metrics"> <span class="school-card-metric"> <span class="school-card-metric-line"> <i class="fa-solid fa-star tw:text-yellow-500" aria-hidden="true"></i> <span class="tw:text-body-s tw:leading-body-s tw:font-bold tw:text-neutral-900">4.5</span> </span> <span class="tw:text-body-xs tw:leading-body-xs tw:text-neutral-800">Rating</span> </span> <span class="school-card-metric"> <span class="school-card-metric-line"> <i class="fa-solid fa-thumbs-up tw:text-green-500" aria-hidden="true"></i> <span class="tw:text-body-s tw:leading-body-s tw:font-bold tw:text-neutral-900">89%</span> </span> <span class="tw:text-body-xs tw:leading-body-xs tw:text-neutral-800">Recommended</span> </span> <span class="school-card-metric"> <span class="school-card-metric-line"> <i class="fa-solid fa-calendar-check tw:text-link" aria-hidden="true"></i> <span class="tw:text-body-s tw:leading-body-s tw:font-bold tw:text-neutral-900">Accepting Now</span> </span> <span class="tw:text-body-xs tw:leading-body-xs tw:text-neutral-800 tw:font-normal">Until 23 Aug 2025</span> </span> </div> </div> <div class="tw:mt-2.5 tw:flex tw:flex-col tw:gap-2"> <p class="tw:mb-0 tw:text-body-s tw:leading-body-s tw:text-neutral-700"> <i class="fa-solid fa-sparkles tw:text-link tw:text-xs tw:mr-1.5 tw:align-middle" aria-hidden="true"></i><span class="tw:font-semibold tw:text-neutral-800">Why this fits</span> · Runs Maths, Physics & Economics as a single clash-free option block, has a small sixth-form cohort and a strong SEND team — and it’s close to home. </p> <div class="tw:flex tw:flex-wrap tw:gap-1.5"> <span class="badge badge-primary-subtle">Small cohort</span> <span class="badge badge-primary-subtle">SEND specialist</span> <span class="badge badge-primary-subtle">Pastoral focus</span> <span class="badge badge-primary-subtle">1:1 tutoring</span> </div> </div> <div class="school-card-courses"> <p class="school-card-courses-label">Top Available Courses</p> <div class="school-card-courses-list" data-controller="course-list" data-course-list-extra-value="9"> <span class="badge badge-chip badge-pill badge-outline-secondary badge-sm" data-course-list-target="chip">Maths A-Level</span> <span class="badge badge-chip badge-pill badge-outline-secondary badge-sm" data-course-list-target="chip">Physics A-Level</span> <span class="badge badge-chip badge-pill badge-outline-secondary badge-sm" data-course-list-target="chip">Economics A-Level</span> <span class="badge badge-chip badge-pill badge-outline-secondary badge-sm" data-course-list-target="chip">Chemistry A-Level</span> <span class="badge badge-chip badge-pill badge-outline-secondary badge-sm" data-course-list-target="chip">Biology A-Level</span> <span class="badge badge-chip badge-pill badge-outline-secondary badge-sm" data-course-list-target="chip">Further Maths A-Level</span> <span class="badge badge-chip badge-pill badge-outline-secondary badge-sm" data-course-list-target="chip">Business A-Level</span> <span class="badge badge-chip badge-pill badge-outline-secondary badge-sm" data-course-list-target="chip">Psychology A-Level</span> <span class="badge badge-chip badge-pill badge-outline-secondary badge-sm" data-course-list-target="chip">History A-Level</span> <span class="badge badge-chip badge-pill badge-outline-secondary badge-sm" data-course-list-target="chip">Computer Science A-Level</span> <span class="school-card-courses-more" data-course-list-target="more">+9 more</span> </div> </div> </div> <div class="school-card-actions"> <button type="button" class="school-card-bookmark" aria-label="Save Greenford High School" aria-pressed="false"><i class="fa-light fa-bookmark" aria-hidden="true"></i></button> </div> </article> </div> <div class="callout tw:mt-4"> <p class="tw:mb-0 tw:text-sm">Scan-fed elements: the <strong>Eligibility pill</strong> is now engine-computed (D3 → verdict → badge); the <strong>"Why this fits"</strong> line and <strong>fit-tags</strong> stay curated pending real D1/D4 feeds.</p> </div> </div> <div class="tw:border-t tw:pt-6"> <h2 class="h4 tw:mb-4">Eligibility states (D3-driven)</h2> <div class="callout tw:mb-4"> <p class="tw:mb-0 tw:text-sm"><strong>Mapping decided + wired.</strong> All four badges render from <code>Scan::EligibilityBadge</code> (shipped convention: Likely = amber, Worth aiming for = violet), now shared by the AI cards, classic cards and course pages.</p> </div> <div class="tw:flex tw:flex-wrap tw:gap-3 tw:items-center"> <span class="badge-eligibility badge-eligibility-eligible"><i class="fa-light fa-circle-check tw:mr-1" aria-hidden="true"></i>Eligible</span> <span class="badge-eligibility badge-eligibility-not-eligible"><i class="fa-light fa-arrow-trend-up tw:mr-1" aria-hidden="true"></i>Likely eligible</span> <span class="badge-eligibility badge-eligibility-info"><i class="fa-light fa-bullseye-arrow tw:mr-1" aria-hidden="true"></i>Worth aiming for</span> <span class="badge-eligibility badge-eligibility-unknown"><i class="fa-light fa-circle-question tw:mr-1" aria-hidden="true"></i>Requirements not published</span> </div> </div></div>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
<div class="tw:p-6 tw:max-w-7xl tw:mx-auto tw:space-y-8"> <div class="callout"> <p class="tw:mb-1 tw:text-sm tw:font-mono"> <strong>AI SEARCH RESULT CARD (4.1 · WIRE):</strong> the UI already exists in <code>projects/ai_search</code><br> <strong>SCAN-FED:</strong> Eligibility pill (D3) | "Why this fits" reason (D1·D3·D4) | Fit-tags (D4) </p> <p class="tw:mb-0 tw:text-sm"> <strong>Now wired:</strong> the eligibility pill is computed end-to-end (mock D3 rules + grades → <code>Scan::Eligibility.evaluate</code> → <code>Scan::EligibilityBadge</code>), the same path the course pages use. Still curated (would come from real D1/D4 in production): the "Why this fits" reason and the fit-tags. Honesty rule: only assert "grounded" when D2 provenance exists. </p> </div> <%# The badge is computed end-to-end: mock D3 rules + the student's grades → Scan::Eligibility.evaluate → verdict → Scan::EligibilityBadge (the same path the course pages use). GHS meets every rule here, so it resolves to :eligible. %> <% ghs_result = Scan::Eligibility.evaluate( Scan::CourseRequirements.new(course_id: 42, coded: true, rules: { min_gcse_passes: 5, min_grade: 4, english: 4, maths: 4 }), Scan::StudentProfile.new(gcse_passes: 8, english: 6, maths: 6) ) ghs_badge = Scan::EligibilityBadge.for(ghs_result.verdict) %> <div class="tw:border-t tw:pt-6"> <h2 class="h4 tw:mb-4">Wired card — eligible</h2> <div class="tw:max-w-[760px] tw:space-y-3"> <article class="school-card tw:group"> <div class="school-card-body"> <div class="school-card-header school-card-header-stack"> <div class="school-card-identity"> <span class="school-card-initials" aria-hidden="true">GHS</span> <div class="school-card-heading"> <div class="tw:flex tw:items-center tw:flex-wrap tw:gap-x-2 tw:gap-y-1 tw:min-w-0"> <h3 class="school-card-name tw:flex tw:items-center tw:gap-1.5 tw:min-w-0"> <span class="tw:truncate">Greenford High School</span> <i class="fa-solid fa-circle-check school-card-verified tw:shrink-0" role="img" aria-label="Verified" title="Verified on ApplicaaOne"></i> </h3> <span class="badge-eligibility <%= ghs_badge[:klass] %>"><i class="fa-light <%= ghs_badge[:icon] %> tw:mr-1" aria-hidden="true"></i><%= ghs_badge[:label] %></span> </div> <p class="school-card-meta">Lady Margaret Rd, Southall UB1 2GU · 1.2 mi away</p> </div> </div> <%# DS school-card-metrics component (fixed columns + hairline dividers) — replaces the ad-hoc triplet so this aligns with the design system. %> <div class="school-card-metrics"> <span class="school-card-metric"> <span class="school-card-metric-line"> <i class="fa-solid fa-star tw:text-yellow-500" aria-hidden="true"></i> <span class="tw:text-body-s tw:leading-body-s tw:font-bold tw:text-neutral-900">4.5</span> </span> <span class="tw:text-body-xs tw:leading-body-xs tw:text-neutral-800">Rating</span> </span> <span class="school-card-metric"> <span class="school-card-metric-line"> <i class="fa-solid fa-thumbs-up tw:text-green-500" aria-hidden="true"></i> <span class="tw:text-body-s tw:leading-body-s tw:font-bold tw:text-neutral-900">89%</span> </span> <span class="tw:text-body-xs tw:leading-body-xs tw:text-neutral-800">Recommended</span> </span> <span class="school-card-metric"> <span class="school-card-metric-line"> <i class="fa-solid fa-calendar-check tw:text-link" aria-hidden="true"></i> <span class="tw:text-body-s tw:leading-body-s tw:font-bold tw:text-neutral-900">Accepting Now</span> </span> <span class="tw:text-body-xs tw:leading-body-xs tw:text-neutral-800 tw:font-normal">Until 23 Aug 2025</span> </span> </div> </div> <div class="tw:mt-2.5 tw:flex tw:flex-col tw:gap-2"> <p class="tw:mb-0 tw:text-body-s tw:leading-body-s tw:text-neutral-700"> <i class="fa-solid fa-sparkles tw:text-link tw:text-xs tw:mr-1.5 tw:align-middle" aria-hidden="true"></i><span class="tw:font-semibold tw:text-neutral-800">Why this fits</span> · Runs Maths, Physics & Economics as a single clash-free option block, has a small sixth-form cohort and a strong SEND team — and it’s close to home. </p> <div class="tw:flex tw:flex-wrap tw:gap-1.5"> <span class="badge badge-primary-subtle">Small cohort</span> <span class="badge badge-primary-subtle">SEND specialist</span> <span class="badge badge-primary-subtle">Pastoral focus</span> <span class="badge badge-primary-subtle">1:1 tutoring</span> </div> </div> <div class="school-card-courses"> <p class="school-card-courses-label">Top Available Courses</p> <div class="school-card-courses-list" data-controller="course-list" data-course-list-extra-value="9"> <% ["Maths A-Level", "Physics A-Level", "Economics A-Level", "Chemistry A-Level", "Biology A-Level", "Further Maths A-Level", "Business A-Level", "Psychology A-Level", "History A-Level", "Computer Science A-Level"].each do |course| %> <span class="badge badge-chip badge-pill badge-outline-secondary badge-sm" data-course-list-target="chip"><%= course %></span> <% end %> <span class="school-card-courses-more" data-course-list-target="more">+9 more</span> </div> </div> </div> <div class="school-card-actions"> <button type="button" class="school-card-bookmark" aria-label="Save Greenford High School" aria-pressed="false"><i class="fa-light fa-bookmark" aria-hidden="true"></i></button> </div> </article> </div> <div class="callout tw:mt-4"> <p class="tw:mb-0 tw:text-sm">Scan-fed elements: the <strong>Eligibility pill</strong> is now engine-computed (D3 → verdict → badge); the <strong>"Why this fits"</strong> line and <strong>fit-tags</strong> stay curated pending real D1/D4 feeds.</p> </div> </div> <div class="tw:border-t tw:pt-6"> <h2 class="h4 tw:mb-4">Eligibility states (D3-driven)</h2> <div class="callout tw:mb-4"> <p class="tw:mb-0 tw:text-sm"><strong>Mapping decided + wired.</strong> All four badges render from <code>Scan::EligibilityBadge</code> (shipped convention: Likely = amber, Worth aiming for = violet), now shared by the AI cards, classic cards and course pages.</p> </div> <div class="tw:flex tw:flex-wrap tw:gap-3 tw:items-center"> <% %i[eligible likely reach unknown].each do |verdict| %> <% b = Scan::EligibilityBadge.for(verdict) %> <span class="badge-eligibility <%= b[:klass] %>"><i class="fa-light <%= b[:icon] %> tw:mr-1" aria-hidden="true"></i><%= b[:label] %></span> <% end %> </div> </div></div>No notes provided.
No params configured.