+
+ mdi-card-account-details-outline
+ Use these values
-
- mdi-information-outline
- {{ activeLesson.whyItMatters }}
-
-
- mdi-lightbulb-on-outline
- {{ hint }}
-
-
-
mdi-information-outline
- {{ info }}
+
+
+ {{ entry.label }}
+ {{ entry.value }}
+ {{ entry.note }}
+
-
+
+
mdi-lightbulb-on-outline
+
+ Response pattern
+ {{ primaryLessonHint }}
+
+
+
-
-
-
{{ entry.label }}
-
{{ entry.value }}
+
+
+ mdi-shield-check-outline
+ {{ activeLesson.standard }}
+
+
{{ activeLesson.whyItMatters }}
+
+
+
+ {{ entry.label }}
+ {{ entry.value }}
+
@@ -3348,6 +3369,54 @@ const clozeGroups = computed
(() => {
const lessonInfo = computed(() => (activeLesson.value && scenario.value ? activeLesson.value.info(scenario.value) : []))
+type LessonValue = {
+ label: string
+ value: string
+ note?: string
+ isCallsign?: boolean
+}
+
+function splitLessonInfo(info: string): { label: string; value: string } | null {
+ const separator = info.indexOf(':')
+ if (separator <= 0) return null
+ const label = info.slice(0, separator).trim()
+ const value = info.slice(separator + 1).trim()
+ if (!label || !value || value.length > 80) return null
+ return { label, value }
+}
+
+const lessonHasCallsign = computed(() => Boolean(activeLesson.value?.fields.some(field =>
+ field.label.trim().toLowerCase() === 'callsign' || field.key.toLowerCase().includes('callsign')
+)))
+
+const lessonEssentialValues = computed(() => {
+ if (!activeLesson.value || !scenario.value) return []
+ const entries: LessonValue[] = []
+ if (lessonHasCallsign.value) {
+ entries.push({
+ label: 'Your callsign',
+ value: scenario.value.radioCall,
+ note: `Flight ID ${scenario.value.callsign}`,
+ isCallsign: true,
+ })
+ }
+ for (const info of lessonInfo.value) {
+ const parsed = splitLessonInfo(info)
+ if (!parsed || entries.some(entry => entry.label.toLowerCase() === parsed.label.toLowerCase())) continue
+ entries.push(parsed)
+ }
+ return entries
+})
+
+const primaryLessonHint = computed(() => activeLesson.value?.hints[0] ?? '')
+
+const additionalLessonNotes = computed(() => {
+ if (!activeLesson.value) return []
+ const extraHints = activeLesson.value.hints.slice(1)
+ const additionalInfo = lessonInfo.value.filter(info => !splitLessonInfo(info))
+ return Array.from(new Set([...extraHints, ...additionalInfo]))
+})
+
const lessonReference = computed(() => {
if (!activeLesson.value || !scenario.value) return []
const lesson = activeLesson.value
@@ -3386,6 +3455,23 @@ const lessonReference = computed(() => {
}
return entries
})
+
+const lessonReferenceDetails = computed(() => {
+ const visibleLabels = new Set(
+ lessonEssentialValues.value.map(entry => entry.label.replace(/\s*ยท.*$/, '').trim().toLowerCase())
+ )
+ return lessonReference.value.filter(entry => {
+ const label = entry.label.trim().toLowerCase()
+ return !visibleLabels.has(label) && !['callsign', 'radio call', 'flight identification'].includes(label)
+ })
+})
+
+const hasLessonDetails = computed(() => Boolean(
+ activeLesson.value?.standard
+ || activeLesson.value?.whyItMatters
+ || additionalLessonNotes.value.length
+ || lessonReferenceDetails.value.length
+))
const showScenarioPracticeHint = computed(() => {
if (!current.value || !activeLesson.value) return false
const index = modules.value.findIndex(module => module.id === current.value?.id)
@@ -3558,6 +3644,7 @@ const previousActionLabel = computed(() => {
const hasPreviousAction = computed(() => Boolean(prevLessonMeta.value || prevMissionMeta.value))
watch(activeLesson, lesson => {
+ referenceOpen.value = false
if (lesson) {
if (moduleStage.value === 'lessons') {
rollScenario(true)
@@ -6751,10 +6838,107 @@ onMounted(() => {
color: color-mix(in srgb, var(--accent) 78%, var(--text));
}
+.lesson-values {
+ margin-top: 14px;
+}
+
+.lesson-values-title {
+ display: flex;
+ align-items: center;
+ gap: 7px;
+ margin-bottom: 7px;
+ color: color-mix(in srgb, var(--accent) 82%, var(--text));
+ font-size: 11px;
+ font-weight: 750;
+ letter-spacing: .1em;
+ text-transform: uppercase;
+}
+
+.lesson-values-grid {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 6px;
+}
+
+.lesson-value {
+ flex: 0 1 auto;
+ min-width: 0;
+ padding: 7px 10px;
+ border: 1px solid color-mix(in srgb, var(--text) 10%, transparent);
+ border-radius: 10px;
+ background: color-mix(in srgb, var(--text) 6%, transparent);
+}
+
+.lesson-value span,
+.lesson-value strong,
+.lesson-value small {
+ display: block;
+}
+
+.lesson-value span {
+ margin-bottom: 3px;
+ color: var(--t3);
+ font-size: 10px;
+ font-weight: 700;
+ letter-spacing: .08em;
+ text-transform: uppercase;
+}
+
+.lesson-value strong {
+ overflow-wrap: anywhere;
+ color: var(--text);
+ font-size: 14px;
+ line-height: 1.3;
+}
+
+.lesson-value small {
+ margin-top: 3px;
+ color: var(--t3);
+ font-size: 10px;
+ line-height: 1.35;
+}
+
+.lesson-value.is-callsign {
+ flex: 1 1 185px;
+ max-width: 260px;
+ border: 1px solid color-mix(in srgb, var(--accent) 24%, transparent);
+ background: color-mix(in srgb, var(--accent) 11%, transparent);
+}
+
+.lesson-guidance {
+ display: flex;
+ align-items: flex-start;
+ gap: 9px;
+ margin-top: 10px;
+ padding: 10px 12px;
+ color: var(--t2);
+ font-size: 12px;
+ line-height: 1.45;
+}
+
+.lesson-guidance .v-icon {
+ flex: 0 0 auto;
+ margin-top: 1px;
+ color: var(--accent);
+}
+
+.lesson-guidance strong,
+.lesson-guidance span {
+ display: block;
+}
+
+.lesson-guidance strong {
+ margin-bottom: 2px;
+ color: var(--text);
+ font-size: 11px;
+ letter-spacing: .06em;
+ text-transform: uppercase;
+}
+
.reference-section {
- margin-top: 8px;
+ margin-top: 2px;
border-top: 1px solid var(--b2, rgba(255, 255, 255, 0.08));
- padding-top: 6px;
+ padding-top: 8px;
}
.reference-toggle {
@@ -6789,6 +6973,10 @@ onMounted(() => {
line-height: 1.6;
}
+.reference-row {
+ display: contents;
+}
+
.reference-label {
color: var(--t2, rgba(255, 255, 255, 0.6));
white-space: nowrap;
@@ -6799,6 +6987,44 @@ onMounted(() => {
font-family: var(--font-mono, monospace);
}
+.lesson-details {
+ padding: 8px 0 4px 20px;
+ color: var(--t2);
+ font-size: 12px;
+ line-height: 1.55;
+}
+
+.lesson-details p {
+ margin: 7px 0;
+}
+
+.lesson-details ul {
+ margin: 7px 0;
+ padding-left: 18px;
+}
+
+.lesson-detail-standard {
+ display: flex;
+ align-items: flex-start;
+ gap: 6px;
+ color: color-mix(in srgb, var(--accent) 78%, var(--text));
+}
+
+@media (max-width: 640px) {
+ .lesson-values-grid {
+ gap: 6px;
+ }
+
+ .lesson-value.is-callsign {
+ flex-basis: 100%;
+ max-width: none;
+ }
+
+ .lesson-details {
+ padding-left: 0;
+ }
+}
+
.audio-blur {
filter: blur(8px);
pointer-events: none;