{"id":5051,"date":"2026-08-29T13:44:52","date_gmt":"2026-08-29T18:44:52","guid":{"rendered":"https:\/\/mosesaviation.com\/?page_id=5051"},"modified":"2026-09-07T17:25:31","modified_gmt":"2026-09-07T22:25:31","slug":"aircraft-squawks","status":"publish","type":"page","link":"https:\/\/mosesaviation.com\/index.php\/aircraft-squawks\/","title":{"rendered":"Aircraft Squawks"},"content":{"rendered":"\n<style>\n  \/* Hides this WordPress site's global header \u2014 scoped to just this page,\n     because this <style> tag only loads as part of this page's content. *\/\n  header.wp-block-template-part,\n  .wp-site-blocks > header,\n  body > header,\n  #masthead,\n  .site-header,\n  #tophead {\n    display: none !important;\n  }\n<\/style>\n<!doctype html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n<title>Moses Aviation \u2014 Squawk Log<\/title>\n<link rel=\"preconnect\" href=\"https:\/\/fonts.googleapis.com\">\n<link href=\"https:\/\/fonts.googleapis.com\/css2?family=Space+Grotesk:wght@500;600;700&#038;family=Inter:wght@400;500;600;700&#038;family=IBM+Plex+Mono:wght@500;600&#038;display=swap\" rel=\"stylesheet\">\n<script src=\"https:\/\/cdn.jsdelivr.net\/npm\/@supabase\/supabase-js@2\/dist\/umd\/supabase.min.js\"><\/script>\n<style>\n  :root{\n    --ink:#12213A;\n    --ink-soft:#3C4A63;\n    --paper:#EEF1F0;\n    --panel:#FFFFFF;\n    --line:#CBD2D6;\n    --line-soft:#DEE3E5;\n    --taxiway:#F5B700;\n    --taxiway-ink:#5C4400;\n    --critical:#C1272D;\n    --critical-bg:#FBE7E7;\n    --open:#E07A0E;\n    --open-bg:#FCEBD9;\n    --progress:#2A6FB0;\n    --progress-bg:#E2EDF7;\n    --resolved:#2E7D5B;\n    --resolved-bg:#E1F0E8;\n    --radius:10px;\n    --shadow:0 1px 2px rgba(18,33,58,.06), 0 6px 20px -8px rgba(18,33,58,.15);\n  }\n  *{box-sizing:border-box;}\n  html,body{margin:0;padding:0;}\n  body{\n    background:var(--paper);\n    color:var(--ink);\n    font-family:'Inter',system-ui,sans-serif;\n    -webkit-font-smoothing:antialiased;\n    line-height:1.45;\n  }\n  .app{max-width:1440px;margin:0 auto;padding:0 20px 64px;}\n\n  \/* ---------- Masthead ---------- *\/\n  .masthead{\n    background:#002147;\n    color:#fff;\n    padding:22px 20px;\n    margin-bottom:0;\n    position:relative;\n    overflow:hidden;\n  }\n  .masthead::after{\n    content:\"\";\n    position:absolute; inset:auto 0 0 0; height:6px;\n    background:repeating-linear-gradient(90deg,var(--taxiway) 0 26px, transparent 26px 40px);\n    opacity:.9;\n  }\n  .masthead-inner{max-width:1440px;margin:0 auto;display:flex;align-items:flex-end;justify-content:space-between;gap:18px;flex-wrap:wrap;}\n  .masthead-id{display:flex;align-items:baseline;gap:12px;}\n  .masthead-id .tail{\n    font-family:'IBM Plex Mono',monospace;\n    font-weight:600;\n    font-size:13px;\n    letter-spacing:.14em;\n    color:var(--taxiway);\n    border:1px solid rgba(245,183,0,.5);\n    padding:3px 8px;\n    border-radius:4px;\n  }\n  .masthead h1{\n    font-family:'Space Grotesk',sans-serif;\n    font-weight:700;\n    font-size:clamp(24px,4vw,32px);\n    letter-spacing:-.01em;\n    margin:6px 0 2px;\n    color:#fff !important;\n  }\n  .masthead p{margin:0;color:#B9C3D6;font-size:13.5px;}\n  .masthead-stats{display:flex;gap:22px;}\n  .mstat{text-align:right;}\n  .mstat .n{font-family:'Space Grotesk',sans-serif;font-size:24px;font-weight:700;line-height:1;}\n  .mstat .l{font-size:10.5px;letter-spacing:.08em;text-transform:uppercase;color:#8FA0BE;margin-top:3px;}\n  .mstat.warn .n{color:var(--taxiway);}\n\n  \/* ---------- Tabs ---------- *\/\n  .tabs{\n    display:flex;gap:2px;background:#0E1A2E;padding:0 20px;\n  }\n  .tabs-inner{max-width:1440px;margin:0 auto;display:flex;gap:2px;}\n  .tab{\n    font-family:'Space Grotesk',sans-serif;\n    font-weight:600;font-size:13.5px;letter-spacing:.02em;\n    color:#9FB0CB;background:transparent;border:none;\n    padding:12px 18px;cursor:pointer;\n    border-bottom:3px solid transparent;\n  }\n  .tab:hover{color:#fff;}\n  .tab.active{color:#fff;border-bottom-color:var(--taxiway);}\n\n  \/* ---------- Toolbar ---------- *\/\n  .toolbar{\n    display:flex;gap:10px;flex-wrap:wrap;align-items:center;\n    margin:20px 0 16px;\n  }\n  .toolbar input[type=text], .toolbar select{\n    font-family:'Inter',sans-serif;font-size:13.5px;\n    border:1px solid var(--line);border-radius:8px;\n    background:var(--panel);color:var(--ink);\n    height:38px;padding:0 12px;box-sizing:border-box;\n  }\n  .toolbar input[type=text]{min-width:220px;flex:1;position:relative;top:2px;}\n  .toolbar select{cursor:pointer;}\n  .btn{\n    font-family:'Space Grotesk',sans-serif;font-weight:600;font-size:13.5px;\n    border-radius:8px;border:1px solid var(--ink);\n    height:38px;padding:0 16px;box-sizing:border-box;\n    display:inline-flex;align-items:center;justify-content:center;\n    cursor:pointer;background:var(--ink);color:#fff;\n    white-space:nowrap;\n  }\n  .btn:hover{background:#0B1626;}\n  .btn.secondary{background:transparent;color:var(--ink);border-color:var(--line);}\n  .btn.secondary:hover{border-color:var(--ink);}\n  .btn.ghost{background:transparent;color:var(--ink-soft);border-color:transparent;padding:0 10px;}\n  .spacer{flex:1;}\n\n  .filter-inline{display:contents;}\n  .filter-inline.collapsed{display:none;}\n  .filter-inline select{\n    font-family:'Inter',sans-serif;font-size:13.5px;\n    border:1px solid var(--line);border-radius:8px;\n    background:var(--panel);color:var(--ink);\n    height:38px;padding:0 12px;box-sizing:border-box;cursor:pointer;\n  }\n  #filters-arrow{display:inline-block;font-size:10px;margin-left:4px;transition:transform .15s ease;}\n  #btn-toggle-filters.open #filters-arrow{transform:rotate(180deg);}\n  #filters-count{\n    display:inline-flex;align-items:center;justify-content:center;\n    min-width:16px;height:16px;padding:0 5px;margin-left:6px;\n    background:var(--taxiway);color:var(--taxiway-ink);\n    border-radius:20px;font-size:10.5px;font-weight:700;\n  }\n  #filters-count:empty{display:none;}\n\n  \/* ---------- Table ---------- *\/\n  .log-wrap{background:var(--panel);border:1px solid var(--line-soft);border-radius:var(--radius);overflow:hidden;box-shadow:var(--shadow);}\n  .table-scroll{overflow-x:auto;-webkit-overflow-scrolling:touch;}\n  table{width:100%;border-collapse:collapse;font-size:13px;}\n  thead th{\n    text-align:left;font-family:'Space Grotesk',sans-serif;font-weight:600;font-size:11px;\n    letter-spacing:.06em;text-transform:uppercase;color:var(--ink-soft);\n    background:#F5F6F4;padding:11px 12px;border-bottom:1px solid var(--line-soft);\n    cursor:pointer;user-select:none;white-space:normal;\n    max-width:120px;line-height:1.35;vertical-align:bottom;\n  }\n  thead th:hover{color:var(--ink);}\n  thead th .arrow{opacity:.4;font-size:10px;margin-left:3px;}\n  tbody tr{border-bottom:1px solid var(--line-soft);cursor:pointer;}\n  tbody tr:last-child{border-bottom:none;}\n  tbody tr:hover{background:#F8F9F7;}\n  tbody tr.grounded{box-shadow:inset 3px 0 0 var(--critical);}\n  tbody tr.open-status{box-shadow:inset 3px 0 0 var(--open);}\n  tbody tr.progress-status{box-shadow:inset 3px 0 0 var(--progress);}\n  tbody tr.closed-status{box-shadow:inset 3px 0 0 var(--resolved);}\n  td{padding:11px 12px;vertical-align:top;}\n  td.mono{font-family:'IBM Plex Mono',monospace;font-size:12.5px;white-space:nowrap;}\n  td.desc{max-width:260px;}\n  td.desc .cat{display:block;font-size:11px;color:var(--ink-soft);margin-top:2px;}\n  .badge{\n    display:inline-flex;align-items:center;gap:5px;\n    font-family:'Space Grotesk',sans-serif;font-weight:600;font-size:11px;letter-spacing:.03em;\n    padding:3px 8px;border-radius:20px;white-space:nowrap;\n  }\n  .badge.sev-Minor{background:#EEF0EE;color:var(--ink-soft);}\n  .badge.sev-Major{background:var(--open-bg);color:var(--open);}\n  .badge.sev-Critical{background:var(--critical-bg);color:var(--critical);}\n  .badge.st-Open{background:var(--open-bg);color:var(--open);}\n  .badge.st-In-Progress{background:var(--progress-bg);color:var(--progress);}\n  .badge.st-Closed{background:var(--resolved-bg);color:var(--resolved);}\n  .ground-flag{\n    display:inline-flex;align-items:center;justify-content:center;\n    font-family:'Space Grotesk',sans-serif;font-weight:700;font-size:10.5px;letter-spacing:.05em;\n    padding:3px 8px;border-radius:4px;\n    background:repeating-linear-gradient(45deg,var(--taxiway) 0 6px,#141414 6px 12px);\n    color:#fff;text-shadow:0 1px 2px rgba(90,90,90,.7);\n    -webkit-text-stroke:0.4px #000;\n  }\n  .no-ground{color:var(--ink-soft);font-size:12px;}\n  .empty{padding:48px 20px;text-align:center;color:var(--ink-soft);}\n  .empty b{display:block;font-family:'Space Grotesk',sans-serif;color:var(--ink);font-size:16px;margin-bottom:4px;}\n\n  \/* ---------- Drawer ---------- *\/\n  .overlay{position:fixed;inset:0;background:rgba(18,33,58,.45);opacity:0;pointer-events:none;transition:opacity .18s;z-index:40;}\n  .overlay.show{opacity:1;pointer-events:auto;}\n  .drawer{\n    position:fixed;top:0;right:0;height:100%;width:min(480px,100%);\n    background:var(--panel);z-index:41;box-shadow:-12px 0 30px rgba(18,33,58,.2);\n    transform:translateX(100%);transition:transform .22s ease;\n    display:flex;flex-direction:column;\n  }\n  .drawer.show{transform:translateX(0);}\n  .drawer-head{padding:18px 22px;border-bottom:1px solid var(--line-soft);display:flex;justify-content:space-between;align-items:center;}\n  .drawer-head h2{font-family:'Space Grotesk',sans-serif;font-size:17px;margin:0;}\n  .drawer-head .tag{font-family:'IBM Plex Mono',monospace;font-size:11.5px;color:var(--ink-soft);}\n  .drawer-close{background:none;border:none;font-size:20px;cursor:pointer;color:var(--ink-soft);line-height:1;padding:4px;}\n  .drawer-body{padding:20px 22px;overflow-y:auto;flex:1;}\n  .field{margin-bottom:14px;}\n  .field label{display:block;font-family:'Space Grotesk',sans-serif;font-weight:600;font-size:11.5px;letter-spacing:.04em;text-transform:uppercase;color:var(--ink-soft);margin-bottom:5px;}\n  .field input, .field select, .field textarea{\n    width:100%;font-family:'Inter',sans-serif;font-size:14px;\n    border:1px solid var(--line);border-radius:7px;padding:9px 11px;background:#fff;color:var(--ink);\n  }\n  .field textarea{min-height:70px;resize:vertical;font-family:'Inter',sans-serif;}\n  .field-row{display:flex;gap:12px;}\n  .field-row .field{flex:1;}\n  .drawer-foot{padding:16px 22px;border-top:1px solid var(--line-soft);display:flex;gap:10px;justify-content:space-between;}\n\n  \/* ---------- Dashboard ---------- *\/\n  .grid-stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:12px;margin:20px 0;}\n  .stat-card{background:var(--panel);border:1px solid var(--line-soft);border-radius:var(--radius);padding:16px 18px;box-shadow:var(--shadow);}\n  .stat-card .n{font-family:'Space Grotesk',sans-serif;font-size:30px;font-weight:700;}\n  .stat-card .l{font-size:11.5px;color:var(--ink-soft);letter-spacing:.03em;text-transform:uppercase;margin-top:2px;}\n  .stat-card.crit .n{color:var(--critical);}\n  .stat-card.warn .n{color:var(--open);}\n  .panel-2{display:grid;grid-template-columns:1.3fr 1fr;gap:16px;margin-top:6px;}\n  @media (max-width:820px){.panel-2{grid-template-columns:1fr;}}\n  .panel{background:var(--panel);border:1px solid var(--line-soft);border-radius:var(--radius);padding:18px 20px;box-shadow:var(--shadow);}\n  .panel h3{font-family:'Space Grotesk',sans-serif;font-size:14px;margin:0 0 14px;letter-spacing:.02em;}\n  .bar-row{display:flex;align-items:center;gap:10px;margin-bottom:10px;font-size:12.5px;}\n  .bar-row .lbl{width:130px;flex-shrink:0;color:var(--ink-soft);}\n  .bar-track{flex:1;height:9px;background:#EEF0EE;border-radius:5px;overflow:hidden;}\n  .bar-fill{height:100%;background:var(--progress);border-radius:5px;}\n  .bar-row .val{width:22px;text-align:right;font-family:'IBM Plex Mono',monospace;}\n  .alert-list{display:flex;flex-direction:column;gap:10px;}\n  .alert-item{display:flex;align-items:center;gap:10px;padding:10px 12px;background:var(--critical-bg);border-radius:8px;}\n  .alert-item .tail{font-family:'IBM Plex Mono',monospace;font-weight:600;font-size:13px;}\n  .alert-item .desc{font-size:12px;color:var(--ink-soft);flex:1;}\n  .no-alerts{color:var(--resolved);font-size:13px;display:flex;align-items:center;gap:8px;}\n\n  \/* ---------- Aircraft list ---------- *\/\n  .fleet-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(240px,1fr));gap:14px;margin-top:20px;}\n  .fleet-card{background:var(--panel);border:1px solid var(--line-soft);border-radius:var(--radius);padding:16px 18px;box-shadow:var(--shadow);}\n  .fleet-card.grounded{box-shadow:var(--shadow),inset 0 0 0 1.5px var(--critical);}\n  .fleet-card.clear{box-shadow:var(--shadow),inset 0 0 0 1.5px var(--resolved);}\n  .fleet-top{display:flex;justify-content:space-between;align-items:flex-start;margin-bottom:8px;}\n  .fleet-tail{font-family:'IBM Plex Mono',monospace;font-weight:600;font-size:16px;}\n  .fleet-type{font-size:12px;color:var(--ink-soft);margin-top:2px;}\n  .fleet-open{font-size:12.5px;color:var(--ink-soft);margin-top:8px;}\n  .fleet-open b{color:var(--ink);}\n  .add-fleet{border:1px dashed var(--line);border-radius:var(--radius);padding:16px 18px;display:flex;align-items:center;justify-content:center;color:var(--ink-soft);font-family:'Space Grotesk',sans-serif;font-weight:600;font-size:13px;cursor:pointer;background:transparent;}\n  .add-fleet:hover{border-color:var(--ink);color:var(--ink);}\n\n  footer.note{margin-top:30px;font-size:11.5px;color:var(--ink-soft);text-align:center;}\n\n  footer.note-row{\n    margin-top:30px;position:relative;min-height:30px;\n    display:flex;align-items:center;justify-content:center;\n  }\n  .note-row .note-text{font-size:11.5px;color:var(--ink-soft);text-align:center;}\n\n  #btn-new-tail{\n    position:absolute;left:0;top:50%;transform:translateY(-50%);\n    font-family:'Inter',sans-serif;font-weight:500;font-size:11.5px;\n    color:var(--ink-soft);background:#EDEFEA;\n    border:1px solid var(--line);border-radius:6px;\n    padding:6px 12px;cursor:pointer;white-space:nowrap;\n    transition:color .15s ease, border-color .15s ease, background .15s ease;\n  }\n  #btn-new-tail:hover{color:var(--ink);border-color:var(--ink-soft);background:#E4E7E1;}\n  @media (max-width:640px){\n    footer.note-row{flex-direction:column;gap:10px;}\n    #btn-new-tail{position:static;transform:none;}\n  }\n\n  \/* ---------- Auth gate ---------- *\/\n  #auth-screen{\n    min-height:100vh;display:flex;align-items:center;justify-content:center;\n    background:var(--ink);padding:20px;\n  }\n  .auth-card{\n    background:var(--panel);border-radius:12px;width:100%;max-width:380px;\n    padding:30px 28px;box-shadow:0 20px 50px rgba(0,0,0,.35);position:relative;overflow:hidden;\n  }\n  .auth-card::before{\n    content:\"\";position:absolute;top:0;left:0;right:0;height:5px;\n    background:repeating-linear-gradient(90deg,var(--taxiway) 0 18px, #14202f 18px 28px);\n  }\n  .auth-card .tail{font-family:'IBM Plex Mono',monospace;font-weight:600;font-size:11.5px;letter-spacing:.14em;color:var(--ink-soft);}\n  .auth-card h1{font-size:20px;margin:6px 0 4px;}\n  .auth-card p.sub{font-size:12.5px;color:var(--ink-soft);margin:0 0 20px;}\n  .auth-card .field{margin-bottom:12px;}\n  .auth-card .btn{width:100%;justify-content:center;margin-top:6px;}\n  .auth-error{background:var(--critical-bg);color:var(--critical);font-size:12.5px;padding:9px 11px;border-radius:7px;margin-bottom:12px;display:none;}\n  .auth-note{font-size:11.5px;color:var(--ink-soft);margin-top:16px;text-align:center;}\n\n  .sync-dot{display:inline-block;width:7px;height:7px;border-radius:50%;background:#5FBF83;margin-right:6px;box-shadow:0 0 0 3px rgba(95,191,131,.25);}\n  .sync-dot.off{background:#C1272D;box-shadow:0 0 0 3px rgba(193,39,45,.25);}\n  .sync-wrap{display:flex;align-items:center;font-size:11px;color:#9FB0CB;letter-spacing:.04em;text-transform:uppercase;font-family:'Space Grotesk',sans-serif;}\n  .who{font-size:11.5px;color:#9FB0CB;display:flex;align-items:center;gap:10px;margin-top:6px;}\n  .who button{background:none;border:none;color:var(--taxiway);cursor:pointer;font-family:'Space Grotesk',sans-serif;font-weight:600;font-size:11.5px;padding:0;}\n\n  \/* mobile table -> cards *\/\n  @media (max-width:760px){\n    thead{display:none;}\n    table, tbody, tr, td{display:block;width:100%;}\n    tbody tr{padding:12px 14px;box-shadow:inset 3px 0 0 var(--line);}\n    tbody tr.grounded{box-shadow:inset 3px 0 0 var(--critical);}\n    tbody tr.open-status{box-shadow:inset 3px 0 0 var(--open);}\n    tbody tr.progress-status{box-shadow:inset 3px 0 0 var(--progress);}\n    tbody tr.closed-status{box-shadow:inset 3px 0 0 var(--resolved);}\n    td{padding:3px 0;border:none;}\n    td.desc{max-width:100%;}\n    td::before{content:attr(data-label);display:block;font-family:'Space Grotesk',sans-serif;font-size:10px;letter-spacing:.06em;text-transform:uppercase;color:var(--ink-soft);margin-top:6px;}\n    td:first-child::before{margin-top:0;}\n  }\n  @media (max-width:600px){\n    .masthead-stats{display:none;}\n    .toolbar{flex-direction:column;align-items:stretch;}\n    .toolbar input[type=text], .toolbar select, .toolbar .btn{width:100%;}\n    .filter-inline select, .filter-inline .btn{width:100%;}\n  }\n<\/style>\n<\/head>\n<body>\n\n<!-- AUTH GATE -->\n<div id=\"auth-screen\">\n  <div class=\"auth-card\">\n    <div class=\"tail\">MAINTENANCE RECORD \u00b7 SIGN IN<\/div>\n    <h1>Moses Aviation Squawk Log<\/h1>\n    <p class=\"sub\">Shared, live maintenance log. Sign in with the account your admin set up for you.<\/p>\n    <div class=\"auth-error\" id=\"auth-error\"><\/div>\n    <div class=\"field\"><label>Email<\/label><input type=\"email\" id=\"auth-email\" autocomplete=\"username\"><\/div>\n    <div class=\"field\"><label>Password<\/label><input type=\"password\" id=\"auth-password\" autocomplete=\"current-password\"><\/div>\n    <button class=\"btn\" id=\"btn-signin\">Sign In<\/button>\n    <p class=\"auth-note\">Don't have an account? Ask your maintenance admin to add your email in Supabase.<\/p>\n  <\/div>\n<\/div>\n\n<div id=\"app-root\" style=\"display:none;\">\n\n<div class=\"masthead\">\n  <div class=\"masthead-inner\">\n    <div>\n      <div class=\"masthead-id\">\n        <span class=\"tail\">MAINTENANCE RECORD<\/span>\n        <span class=\"sync-wrap\"><span class=\"sync-dot\" id=\"sync-dot\"><\/span><span id=\"sync-label\">Live<\/span><\/span>\n      <\/div>\n      <h1>Moses Aviation \u2014 Squawk Log<\/h1>\n      <p>Live discrepancy tracking for the fleet, shared across everyone signed in.<\/p>\n      <div class=\"who\"><span id=\"who-email\"><\/span> \u00b7 <button id=\"btn-signout\">Sign out<\/button><\/div>\n    <\/div>\n    <div class=\"masthead-stats\">\n      <div class=\"mstat warn\"><div class=\"n\" id=\"ms-grounded\">0<\/div><div class=\"l\">Grounded<\/div><\/div>\n      <div class=\"mstat\"><div class=\"n\" id=\"ms-open\">0<\/div><div class=\"l\">Open Squawks<\/div><\/div>\n      <div class=\"mstat\"><div class=\"n\" id=\"ms-fleet\">0<\/div><div class=\"l\">Aircraft<\/div><\/div>\n    <\/div>\n  <\/div>\n<\/div>\n\n<div class=\"tabs\">\n  <div class=\"tabs-inner\">\n    <button class=\"tab active\" data-view=\"log\">Squawk Log<\/button>\n    <button class=\"tab\" data-view=\"fleet\">Aircraft List<\/button>\n    <button class=\"tab\" data-view=\"dash\">Dashboard<\/button>\n  <\/div>\n<\/div>\n\n<div class=\"app\">\n\n  <!-- SQUAWK LOG VIEW -->\n  <section id=\"view-log\">\n    <div class=\"toolbar\">\n      <input type=\"text\" id=\"search\" placeholder=\"Search description, tail #, reported by\u2026\">\n      <span class=\"filter-inline collapsed\" id=\"filter-row\">\n        <select id=\"f-tail\"><option value=\"\">All aircraft<\/option><\/select>\n        <select id=\"f-status\">\n          <option value=\"\">All statuses<\/option>\n          <option selected>Open<\/option><option>In Progress<\/option><option>Closed<\/option>\n        <\/select>\n        <select id=\"f-severity\">\n          <option value=\"\">All severities<\/option>\n          <option>Minor<\/option><option>Major<\/option><option>Critical<\/option>\n        <\/select>\n        <select id=\"f-grounding\">\n          <option value=\"\">Grounding: any<\/option>\n          <option value=\"Yes\">Grounding only<\/option>\n          <option value=\"No\">Non-grounding<\/option>\n        <\/select>\n        <button class=\"btn ghost\" id=\"btn-clear-filters\">Clear filters<\/button>\n      <\/span>\n      <button class=\"btn secondary\" id=\"btn-toggle-filters\">Filters <span class=\"arrow\" id=\"filters-arrow\">\u25be<\/span><span id=\"filters-count\"><\/span><\/button>\n      <div class=\"spacer\"><\/div>\n      <button class=\"btn secondary\" id=\"btn-export\">Export CSV<\/button>\n      <button class=\"btn\" id=\"btn-new\">+ New Squawk<\/button>\n    <\/div>\n\n    <div class=\"log-wrap\">\n      <div class=\"table-scroll\">\n      <table id=\"log-table\">\n        <thead>\n          <tr>\n            <th data-sort=\"id\">Squawk #<\/th>\n            <th data-sort=\"dateReported\">Reported<\/th>\n            <th data-sort=\"tail\">Tail #<\/th>\n            <th data-sort=\"desc\">Discrepancy<\/th>\n            <th data-sort=\"severity\">Severity<\/th>\n            <th data-sort=\"grounding\">Grounding<\/th>\n            <th data-sort=\"status\">Status<\/th>\n            <th data-sort=\"daysOpen\">Days Open<\/th>\n            <th data-sort=\"action\">Corrective<br>Action Taken<\/th>\n            <th data-sort=\"resolvedBy\">Resolved By<br>A&amp;P<\/th>\n            <th data-sort=\"rts\">Return to<br>Service<\/th>\n          <\/tr>\n        <\/thead>\n        <tbody id=\"log-body\"><\/tbody>\n      <\/table>\n      <\/div>\n      <div class=\"empty\" id=\"log-empty\" style=\"display:none;\">\n        <b>No squawks match these filters<\/b>\n        Adjust the filters above or log a new squawk to get started.\n      <\/div>\n    <\/div>\n  <\/section>\n\n  <!-- FLEET VIEW -->\n  <section id=\"view-fleet\" style=\"display:none;\">\n    <div class=\"toolbar\">\n      <div><strong style=\"font-family:'Space Grotesk',sans-serif;font-size:15px;\">Aircraft on file<\/strong><\/div>\n    <\/div>\n    <div class=\"fleet-grid\" id=\"fleet-grid\"><\/div>\n  <\/section>\n\n  <!-- DASHBOARD VIEW -->\n  <section id=\"view-dash\" style=\"display:none;\">\n    <div class=\"grid-stats\" id=\"dash-stats\"><\/div>\n    <div class=\"panel-2\">\n      <div class=\"panel\">\n        <h3>Open squawks by system<\/h3>\n        <div id=\"dash-bars\"><\/div>\n      <\/div>\n      <div class=\"panel\">\n        <h3>Grounded aircraft<\/h3>\n        <div class=\"alert-list\" id=\"dash-alerts\"><\/div>\n      <\/div>\n    <\/div>\n  <\/section>\n\n  <footer class=\"note-row\">\n    <button id=\"btn-new-tail\" title=\"Add or modify an aircraft\">+ Add \/ Modify Aircraft<\/button>\n    <span class=\"note-text\">Moses Aviation Squawk Log \u00b7 shared live log \u00b7 exported as needed via CSV<\/span>\n  <\/footer>\n<\/div>\n\n<\/div><!-- \/app-root -->\n\n<!-- DRAWER -->\n<div class=\"overlay\" id=\"overlay\"><\/div>\n<div class=\"drawer\" id=\"drawer\">\n  <div class=\"drawer-head\">\n    <div>\n      <h2 id=\"drawer-title\">New Squawk<\/h2>\n      <div class=\"tag\" id=\"drawer-tag\"><\/div>\n    <\/div>\n    <button class=\"drawer-close\" id=\"drawer-close\">&times;<\/button>\n  <\/div>\n  <div class=\"drawer-body\">\n    <div class=\"field-row\">\n      <div class=\"field\"><label>Date Reported<\/label><input type=\"date\" id=\"in-dateReported\"><\/div>\n      <div class=\"field\"><label>Tail Number<\/label><input type=\"text\" id=\"in-tail\" list=\"tail-list\" placeholder=\"N46696\"><\/div>\n    <\/div>\n    <datalist id=\"tail-list\"><\/datalist>\n    <div class=\"field\"><label>Reported By<\/label><input type=\"text\" id=\"in-reportedBy\"><\/div>\n    <div class=\"field\"><label>Discrepancy \/ Squawk Description<\/label><textarea id=\"in-desc\" placeholder=\"Describe the discrepancy\u2026\"><\/textarea><\/div>\n    <div class=\"field-row\">\n      <div class=\"field\"><label>System \/ Category<\/label>\n        <select id=\"in-category\">\n          <option>Airframe<\/option><option>Powerplant<\/option><option>Avionics\/Electrical<\/option>\n          <option>Landing Gear<\/option><option>Interior<\/option><option>Other<\/option>\n        <\/select>\n      <\/div>\n      <div class=\"field\"><label>Severity<\/label>\n        <select id=\"in-severity\"><option>Minor<\/option><option>Major<\/option><option>Critical<\/option><\/select>\n      <\/div>\n    <\/div>\n    <div class=\"field-row\">\n      <div class=\"field\"><label>Grounding?<\/label>\n        <select id=\"in-grounding\"><option>No<\/option><option>Yes<\/option><\/select>\n      <\/div>\n      <div class=\"field\"><label>Status<\/label>\n        <select id=\"in-status\"><option>Open<\/option><option>In Progress<\/option><option>Closed<\/option><\/select>\n      <\/div>\n    <\/div>\n    <hr style=\"border:none;border-top:1px solid var(--line-soft);margin:18px 0;\">\n    <div class=\"field\"><label>Corrective Action Taken<\/label><textarea id=\"in-action\" placeholder=\"Describe the corrective action\u2026\"><\/textarea><\/div>\n    <div class=\"field-row\">\n      <div class=\"field\"><label>Return to Service<\/label><input type=\"date\" id=\"in-rts\"><\/div>\n    <\/div>\n    <div class=\"field\"><label>Resolved By \/ A&amp;P<\/label><input type=\"text\" id=\"in-resolvedBy\" placeholder=\"Name, cert #\"><\/div>\n    <div class=\"field\"><label>Maintenance Test Flight By<\/label><input type=\"text\" id=\"in-testFlightBy\" placeholder=\"Name, cert #\"><\/div>\n    <div class=\"field\"><label>Test Flight Date<\/label><input type=\"date\" id=\"in-testFlightDate\"><\/div>\n  <\/div>\n  <div class=\"drawer-foot\">\n    <button class=\"btn ghost\" id=\"btn-delete\" style=\"display:none;color:var(--critical);\">Delete squawk<\/button>\n    <div class=\"spacer\"><\/div>\n    <button class=\"btn secondary\" id=\"btn-cancel\">Cancel<\/button>\n    <button class=\"btn\" id=\"btn-save\">Save Squawk<\/button>\n  <\/div>\n<\/div>\n\n<script>\n(function(){\n  \"use strict\";\n\n  \/* =========================================================\n     SETUP \u2014 paste your Supabase project values here.\n     Project Settings \u2192 API \u2192 Project URL \/ anon public key.\n     ========================================================= *\/\n  var SUPABASE_URL = \"https:\/\/aznzzdlvwctiwsmipojv.supabase.co\";\n  var SUPABASE_ANON_KEY = \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImF6bnp6ZGx2d2N0aXdzbWlwb2p2Iiwicm9sZSI6ImFub24iLCJpYXQiOjE3ODgwMjM5OTIsImV4cCI6MjEwMzU5OTk5Mn0.zRYv2dCTzhprJWMWLxUwfkDc3WjOjWwWhwYjIbDgV2o\";\n  \/* ========================================================= *\/\n\n  var supabase = window.supabase.createClient(SUPABASE_URL, SUPABASE_ANON_KEY);\n  var todayISO = function(){ return new Date().toISOString().slice(0,10); };\n\n  var log = [];      \/\/ squawks, camelCase, mirrors the app's field names\n  var fleet = [];     \/\/ aircraft\n  var editingDbId = null; \/\/ numeric primary key of squawk being edited\n  var channel = null;\n\n  \/* ---------- row mapping: db (snake_case) <-> app (camelCase) ---------- *\/\n  function mapSquawkFromDb(r){\n    return {\n      dbId: r.id,\n      id: r.squawk_no,\n      dateReported: r.date_reported,\n      tail: r.tail,\n      reportedBy: r.reported_by || \"\",\n      desc: r.description,\n      category: r.category,\n      severity: r.severity,\n      grounding: r.grounding,\n      status: r.status,\n      mel: r.mel || \"\",\n      dateResolved: r.date_resolved || \"\",\n      resolvedBy: r.resolved_by || \"\",\n      action: r.action || \"\",\n      rts: r.rts || \"\",\n      testFlightBy: r.test_flight_by || \"\",\n      testFlightDate: r.test_flight_date || \"\"\n    };\n  }\n  function mapSquawkToDb(p){\n    return {\n      date_reported: p.dateReported,\n      tail: p.tail,\n      reported_by: p.reportedBy,\n      description: p.desc,\n      category: p.category,\n      severity: p.severity,\n      grounding: p.grounding,\n      status: p.status,\n      mel: p.mel,\n      date_resolved: p.dateResolved || null,\n      resolved_by: p.resolvedBy,\n      action: p.action,\n      rts: p.rts || null,\n      test_flight_by: p.testFlightBy,\n      test_flight_date: p.testFlightDate || null\n    };\n  }\n\n  function daysOpen(row){\n    if(!row.dateReported) return \"\";\n    var start = new Date(row.dateReported+\"T00:00:00\");\n    var end = row.status === \"Closed\" && row.dateResolved ? new Date(row.dateResolved+\"T00:00:00\") : new Date();\n    var diff = Math.round((end-start)\/86400000);\n    return Math.max(diff,0);\n  }\n  function fmtDate(s){\n    if(!s) return \"\u2014\";\n    var d = new Date(s+\"T00:00:00\");\n    if(isNaN(d)) return s;\n    return (d.getMonth()+1)+\"\/\"+d.getDate()+\"\/\"+d.getFullYear();\n  }\n  function escapeHtml(s){\n    return String(s||\"\").replace(\/[&<>\"]\/g, function(c){\n      return {\"&\":\"&amp;\",\"<\":\"&lt;\",\">\":\"&gt;\",'\"':\"&quot;\"}[c];\n    });\n  }\n\n  \/* ---------- data load \/ realtime ---------- *\/\n  function setSyncState(ok){\n    var dot = document.getElementById(\"sync-dot\");\n    var lbl = document.getElementById(\"sync-label\");\n    if(!dot) return;\n    dot.classList.toggle(\"off\", !ok);\n    lbl.textContent = ok ? \"Live\" : \"Offline\";\n  }\n\n  function fetchAll(){\n    return Promise.all([\n      supabase.from(\"squawks\").select(\"*\").order(\"date_reported\",{ascending:false}),\n      supabase.from(\"aircraft\").select(\"*\").order(\"tail\",{ascending:true})\n    ]).then(function(results){\n      var sqRes = results[0], acRes = results[1];\n      if(sqRes.error || acRes.error){\n        console.error(sqRes.error || acRes.error);\n        setSyncState(false);\n        return;\n      }\n      log = sqRes.data.map(mapSquawkFromDb);\n      fleet = acRes.data;\n      setSyncState(true);\n      renderAll();\n    });\n  }\n\n  function subscribeRealtime(){\n    if(channel) supabase.removeChannel(channel);\n    channel = supabase.channel(\"public:squawk-log\")\n      .on(\"postgres_changes\", {event:\"*\", schema:\"public\", table:\"squawks\"}, function(){ fetchAll(); })\n      .on(\"postgres_changes\", {event:\"*\", schema:\"public\", table:\"aircraft\"}, function(){ fetchAll(); })\n      .subscribe(function(status){\n        setSyncState(status === \"SUBSCRIBED\");\n      });\n  }\n\n  \/* ---------- filters state ---------- *\/\n  var state = { search:\"\", tail:\"\", status:\"Open\", severity:\"\", grounding:\"\", sortKey:\"dateReported\", sortDir:-1 };\n\n  function filteredRows(){\n    return log.filter(function(r){\n      if(state.tail && r.tail !== state.tail) return false;\n      if(state.status && r.status !== state.status) return false;\n      if(state.severity && r.severity !== state.severity) return false;\n      if(state.grounding && r.grounding !== state.grounding) return false;\n      if(state.search){\n        var s = state.search.toLowerCase();\n        var hay = [r.id,r.tail,r.desc,r.reportedBy,r.category,r.action].join(\" \").toLowerCase();\n        if(hay.indexOf(s)===-1) return false;\n      }\n      return true;\n    }).sort(function(a,b){\n      var k = state.sortKey, dir = state.sortDir;\n      var av, bv;\n      if(k===\"daysOpen\"){ av = daysOpen(a); bv = daysOpen(b); }\n      else { av = a[k]||\"\"; bv = b[k]||\"\"; }\n      if(av < bv) return -1*dir;\n      if(av > bv) return 1*dir;\n      return 0;\n    });\n  }\n\n  function statusClass(s){\n    if(s===\"Open\") return \"open-status\";\n    if(s===\"In Progress\") return \"progress-status\";\n    if(s===\"Closed\") return \"closed-status\";\n    return \"\";\n  }\n\n  function renderAll(){\n    renderTailFilter();\n    renderLog();\n    renderFleet();\n    renderDash();\n    renderMastheadStats();\n  }\n\n  function renderLog(){\n    var rows = filteredRows();\n    var body = document.getElementById(\"log-body\");\n    body.innerHTML = \"\";\n    document.getElementById(\"log-empty\").style.display = rows.length? \"none\":\"block\";\n    rows.forEach(function(r){\n      var tr = document.createElement(\"tr\");\n      tr.className = (r.grounding===\"Yes\" ? \"grounded \" : \"\") + statusClass(r.status);\n      tr.innerHTML =\n        '<td class=\"mono\" data-label=\"Squawk #\">'+r.id+'<\/td>'+\n        '<td data-label=\"Reported\">'+fmtDate(r.dateReported)+'<\/td>'+\n        '<td class=\"mono\" data-label=\"Tail #\">'+r.tail+'<\/td>'+\n        '<td class=\"desc\" data-label=\"Discrepancy\">'+escapeHtml(r.desc)+'<span class=\"cat\">'+r.category+'<\/span><\/td>'+\n        '<td data-label=\"Severity\"><span class=\"badge sev-'+r.severity+'\">'+r.severity+'<\/span><\/td>'+\n        '<td data-label=\"Grounding\">'+(r.grounding===\"Yes\" ? '<span class=\"ground-flag\">GROUNDED<\/span>' : '<span class=\"no-ground\">No<\/span>')+'<\/td>'+\n        '<td data-label=\"Status\"><span class=\"badge st-'+r.status.replace(\/\\s+\/g,\"-\")+'\">'+r.status+'<\/span><\/td>'+\n        '<td class=\"mono\" data-label=\"Days Open\">'+daysOpen(r)+'<\/td>'+\n        '<td class=\"desc\" data-label=\"Corrective Action Taken\">'+(r.action ? escapeHtml(r.action) : '<span class=\"no-ground\">\u2014<\/span>')+'<\/td>'+\n        '<td data-label=\"Resolved By \/ A&#038;P\">'+(r.resolvedBy ? escapeHtml(r.resolvedBy) : '<span class=\"no-ground\">\u2014<\/span>')+'<\/td>'+\n        '<td class=\"mono\" data-label=\"Return to Service\">'+fmtDate(r.rts)+'<\/td>';\n      tr.addEventListener(\"click\", function(){ openDrawer(r.dbId); });\n      body.appendChild(tr);\n    });\n    renderHeaderArrows();\n  }\n\n  function renderHeaderArrows(){\n    document.querySelectorAll(\"#log-table thead th\").forEach(function(th){\n      var existingArrow = th.querySelector(\".arrow\");\n      if(existingArrow) existingArrow.remove();\n      if(th.dataset.sort === state.sortKey){\n        var arrow = document.createElement(\"span\");\n        arrow.className = \"arrow\";\n        arrow.textContent = \" \" + (state.sortDir===1 ? \"\u25b2\" : \"\u25bc\");\n        th.appendChild(arrow);\n      }\n    });\n  }\n\n  function renderMastheadStats(){\n    document.getElementById(\"ms-open\").textContent = log.filter(function(r){return r.status!==\"Closed\";}).length;\n    document.getElementById(\"ms-grounded\").textContent = log.filter(function(r){return r.grounding===\"Yes\" && r.status!==\"Closed\";}).length;\n    document.getElementById(\"ms-fleet\").textContent = fleet.length;\n  }\n\n  function renderTailFilter(){\n    var sel = document.getElementById(\"f-tail\");\n    var current = sel.value;\n    sel.innerHTML = '<option value=\"\">All aircraft<\/option>' +\n      fleet.slice().sort(function(a,b){return a.tail.localeCompare(b.tail);})\n        .map(function(f){return '<option value=\"'+f.tail+'\">'+f.tail+'<\/option>';}).join(\"\");\n    sel.value = current;\n    var dl = document.getElementById(\"tail-list\");\n    dl.innerHTML = fleet.map(function(f){return '<option value=\"'+f.tail+'\">';}).join(\"\");\n  }\n\n  \/* ---------- Fleet view ---------- *\/\n  function renderFleet(){\n    var grid = document.getElementById(\"fleet-grid\");\n    grid.innerHTML = \"\";\n    fleet.slice().sort(function(a,b){return a.tail.localeCompare(b.tail);}).forEach(function(f){\n      var rows = log.filter(function(r){return r.tail===f.tail;});\n      var openRows = rows.filter(function(r){return r.status!==\"Closed\";});\n      var grounded = openRows.some(function(r){return r.grounding===\"Yes\";});\n      var card = document.createElement(\"div\");\n      card.className = \"fleet-card\"+(grounded?\" grounded\":\" clear\");\n      card.innerHTML =\n        '<div class=\"fleet-top\"><div><div class=\"fleet-tail\">'+f.tail+'<\/div>'+\n        '<div class=\"fleet-type\">'+(f.type? escapeHtml(f.type) : 'Type not set')+'<\/div><\/div>'+\n        (grounded ? '<span class=\"ground-flag\">GROUNDED<\/span>' : '')+'<\/div>'+\n        '<div class=\"fleet-open\"><b>'+openRows.length+'<\/b> open squawk'+(openRows.length===1?\"\":\"s\")+' \u00b7 <b>'+rows.length+'<\/b> total logged<\/div>';\n      card.addEventListener(\"click\", function(){\n        state.tail = f.tail; document.getElementById(\"f-tail\").value=f.tail;\n        switchView(\"log\"); renderLog();\n      });\n      grid.appendChild(card);\n    });\n  }\n\n  function addOrModifyAircraftPrompt(){\n    var tail = prompt(\"Tail number to add or modify (e.g. N12345):\");\n    if(!tail) return;\n    tail = tail.trim().toUpperCase();\n    if(!tail) return;\n\n    var existing = fleet.find(function(f){ return f.tail === tail; });\n\n    if(!existing){\n      var type = prompt(\"New aircraft \u2014 type\/model for \"+tail+\" (optional):\", \"\") || \"\";\n      supabase.from(\"aircraft\").insert({tail:tail, type:type}).then(function(res){\n        if(res.error){ alert(\"Couldn't add aircraft: \"+res.error.message); return; }\n        fetchAll();\n      });\n      return;\n    }\n\n    var input = prompt(\n      tail+\" is already on file (type: \"+(existing.type || \"not set\")+\").\\n\\n\"+\n      \"Enter a new type to update it, type DELETE to remove this aircraft, or Cancel to leave it as-is:\",\n      existing.type || \"\"\n    );\n    if(input === null) return; \/\/ cancelled\n\n    if(input.trim().toUpperCase() === \"DELETE\"){\n      var squawkCount = log.filter(function(r){ return r.tail === tail; }).length;\n      var warn = \"Delete \"+tail+\"?\";\n      if(squawkCount > 0){\n        warn += \" This aircraft has \"+squawkCount+\" squawk\"+(squawkCount===1?\"\":\"s\")+\" logged against it \u2014 deleting the aircraft will permanently delete \"+(squawkCount===1?\"that squawk\":\"all of those squawks\")+\" too.\";\n      }\n      warn += \" This cannot be undone.\";\n      if(!confirm(warn)) return;\n      supabase.from(\"aircraft\").delete().eq(\"tail\", tail).then(function(res){\n        if(res.error){ alert(\"Couldn't delete aircraft: \"+res.error.message); return; }\n        if(state.tail === tail){ state.tail = \"\"; document.getElementById(\"f-tail\").value = \"\"; }\n        fetchAll();\n      });\n      return;\n    }\n\n    supabase.from(\"aircraft\").update({type:input}).eq(\"tail\", tail).then(function(res){\n      if(res.error){ alert(\"Couldn't update aircraft: \"+res.error.message); return; }\n      fetchAll();\n    });\n  }\n\n\n  function ensureFleetHasTail(tail){\n    if(!tail) return Promise.resolve();\n    if(fleet.some(function(f){return f.tail.toUpperCase()===tail.toUpperCase();})) return Promise.resolve();\n    return supabase.from(\"aircraft\").insert({tail:tail.toUpperCase(), type:\"\"});\n  }\n\n  \/* ---------- Dashboard ---------- *\/\n  function renderDash(){\n    var openRows = log.filter(function(r){return r.status!==\"Closed\";});\n    var groundedRows = openRows.filter(function(r){return r.grounding===\"Yes\";});\n    var closedRows = log.filter(function(r){return r.status===\"Closed\" && r.dateResolved;});\n    var avgDays = closedRows.length ? Math.round(closedRows.reduce(function(s,r){return s+daysOpen(r);},0)\/closedRows.length) : 0;\n\n    var stats = [\n      {n: log.length, l:\"Total squawks logged\"},\n      {n: openRows.length, l:\"Currently open\", cls:\"warn\"},\n      {n: groundedRows.length, l:\"Grounding right now\", cls:\"crit\"},\n      {n: avgDays, l:\"Avg. days to close\"},\n      {n: fleet.length, l:\"Aircraft on file\"}\n    ];\n    document.getElementById(\"dash-stats\").innerHTML = stats.map(function(s){\n      return '<div class=\"stat-card '+(s.cls||\"\")+'\"><div class=\"n\">'+s.n+'<\/div><div class=\"l\">'+s.l+'<\/div><\/div>';\n    }).join(\"\");\n\n    var byCat = {};\n    openRows.forEach(function(r){ byCat[r.category] = (byCat[r.category]||0)+1; });\n    var catEntries = Object.keys(byCat).map(function(k){return [k,byCat[k]];}).sort(function(a,b){return b[1]-a[1];});\n    var maxCat = catEntries.length ? catEntries[0][1] : 1;\n    var barsEl = document.getElementById(\"dash-bars\");\n    barsEl.innerHTML = catEntries.length ? catEntries.map(function(e){\n      var pct = Math.round(e[1]\/maxCat*100);\n      return '<div class=\"bar-row\"><div class=\"lbl\">'+e[0]+'<\/div><div class=\"bar-track\"><div class=\"bar-fill\" style=\"width:'+pct+'%\"><\/div><\/div><div class=\"val\">'+e[1]+'<\/div><\/div>';\n    }).join(\"\") : '<p style=\"color:var(--ink-soft);font-size:13px;\">No open squawks \u2014 clean sheet.<\/p>';\n\n    var alertsEl = document.getElementById(\"dash-alerts\");\n    alertsEl.innerHTML = groundedRows.length ? groundedRows.map(function(r){\n      return '<div class=\"alert-item\"><span class=\"tail\">'+r.tail+'<\/span><span class=\"desc\">'+escapeHtml(r.desc)+'<\/span><\/div>';\n    }).join(\"\") : '<div class=\"no-alerts\">\u2713 No aircraft currently grounded.<\/div>';\n  }\n\n  \/* ---------- Views ---------- *\/\n  function switchView(view){\n    [\"log\",\"fleet\",\"dash\"].forEach(function(v){\n      document.getElementById(\"view-\"+v).style.display = (v===view) ? \"\" : \"none\";\n      document.querySelector('.tab[data-view=\"'+v+'\"]').classList.toggle(\"active\", v===view);\n    });\n  }\n\n  \/* ---------- Drawer ---------- *\/\n  var drawer = document.getElementById(\"drawer\");\n  var overlay = document.getElementById(\"overlay\");\n\n  function openDrawer(dbId){\n    editingDbId = dbId || null;\n    var r = dbId ? log.find(function(x){return x.dbId===dbId;}) : null;\n    document.getElementById(\"drawer-title\").textContent = r ? \"Edit Squawk\" : \"New Squawk\";\n    document.getElementById(\"drawer-tag\").textContent = r ? r.id : \"assigned automatically on save\";\n    document.getElementById(\"btn-delete\").style.display = r ? \"\" : \"none\";\n\n    setVal(\"in-dateReported\", r ? r.dateReported : todayISO());\n    setVal(\"in-tail\", r ? r.tail : \"\");\n    setVal(\"in-reportedBy\", r ? r.reportedBy : \"\");\n    setVal(\"in-desc\", r ? r.desc : \"\");\n    setVal(\"in-category\", r ? r.category : \"Airframe\");\n    setVal(\"in-severity\", r ? r.severity : \"Minor\");\n    setVal(\"in-grounding\", r ? r.grounding : \"No\");\n    setVal(\"in-status\", r ? r.status : \"Open\");\n    setVal(\"in-rts\", r ? r.rts : \"\");\n    setVal(\"in-resolvedBy\", r ? r.resolvedBy : \"\");\n    setVal(\"in-action\", r ? r.action : \"\");\n    setVal(\"in-testFlightBy\", r ? r.testFlightBy : \"\");\n    setVal(\"in-testFlightDate\", r ? r.testFlightDate : \"\");\n\n    overlay.classList.add(\"show\");\n    drawer.classList.add(\"show\");\n  }\n  function setVal(id,v){ document.getElementById(id).value = v||\"\"; }\n  function getVal(id){ return document.getElementById(id).value.trim(); }\n\n  function closeDrawer(){\n    overlay.classList.remove(\"show\");\n    drawer.classList.remove(\"show\");\n    editingDbId = null;\n  }\n\n  function saveDrawer(){\n    var tail = getVal(\"in-tail\").toUpperCase();\n    var desc = getVal(\"in-desc\");\n    if(!tail || !desc){ alert(\"Tail number and discrepancy description are required.\"); return; }\n\n    var existing = editingDbId ? log.find(function(x){return x.dbId===editingDbId;}) : null;\n    var status = getVal(\"in-status\");\n    \/\/ Date Resolved is no longer a manual field: stamp it automatically the\n    \/\/ moment a squawk is marked Closed, and keep that date if it's already closed.\n    var dateResolved = status === \"Closed\" ? (existing && existing.dateResolved ? existing.dateResolved : todayISO()) : \"\";\n\n    var payload = {\n      dateReported: getVal(\"in-dateReported\") || todayISO(),\n      tail: tail,\n      reportedBy: getVal(\"in-reportedBy\"),\n      desc: desc,\n      category: getVal(\"in-category\"),\n      severity: getVal(\"in-severity\"),\n      grounding: getVal(\"in-grounding\"),\n      status: status,\n      mel: existing ? existing.mel : \"\", \/\/ field removed from UI; carries over untouched\n      dateResolved: dateResolved,\n      rts: getVal(\"in-rts\"),\n      resolvedBy: getVal(\"in-resolvedBy\"),\n      action: getVal(\"in-action\"),\n      testFlightBy: getVal(\"in-testFlightBy\"),\n      testFlightDate: getVal(\"in-testFlightDate\")\n    };\n\n    var saveBtn = document.getElementById(\"btn-save\");\n    saveBtn.disabled = true; saveBtn.textContent = \"Saving\u2026\";\n\n    ensureFleetHasTail(tail).then(function(){\n      var dbPayload = mapSquawkToDb(payload);\n      var op = editingDbId\n        ? supabase.from(\"squawks\").update(dbPayload).eq(\"id\", editingDbId)\n        : supabase.from(\"squawks\").insert(dbPayload);\n      return op;\n    }).then(function(res){\n      saveBtn.disabled = false; saveBtn.textContent = \"Save Squawk\";\n      if(res.error){ alert(\"Couldn't save: \"+res.error.message); return; }\n      closeDrawer();\n      fetchAll();\n    }).catch(function(err){\n      saveBtn.disabled = false; saveBtn.textContent = \"Save Squawk\";\n      alert(\"Couldn't save: \"+err.message);\n    });\n  }\n\n  function deleteRow(){\n    if(!editingDbId) return;\n    var r = log.find(function(x){return x.dbId===editingDbId;});\n    if(!confirm(\"Delete \"+(r?r.id:\"this squawk\")+\"? This cannot be undone.\")) return;\n    supabase.from(\"squawks\").delete().eq(\"id\", editingDbId).then(function(res){\n      if(res.error){ alert(\"Couldn't delete: \"+res.error.message); return; }\n      closeDrawer();\n      fetchAll();\n    });\n  }\n\n  \/* ---------- CSV export ---------- *\/\n  function exportCsv(){\n    var cols = [\"id\",\"dateReported\",\"tail\",\"reportedBy\",\"desc\",\"category\",\"severity\",\"grounding\",\"status\",\"mel\",\"dateResolved\",\"resolvedBy\",\"action\",\"rts\",\"testFlightBy\",\"testFlightDate\"];\n    var headers = [\"Squawk #\",\"Date Reported\",\"Tail Number\",\"Reported By\",\"Discrepancy\",\"System\/Category\",\"Severity\",\"Grounding?\",\"Status\",\"MEL\/Placard Ref\",\"Date Resolved\",\"Resolved By\/A&P\",\"Corrective Action\",\"Return to Service\",\"Maintenance Test Flight By\",\"Test Flight Date\"];\n    var rows = filteredRows().map(function(r){\n      return cols.map(function(c){\n        var v = (c===\"dateReported\"||c===\"dateResolved\"||c===\"rts\"||c===\"testFlightDate\") ? fmtDate(r[c]) : (r[c]||\"\");\n        v = String(v).replace(\/\"\/g,'\"\"');\n        return '\"'+v+'\"';\n      }).join(\",\");\n    });\n    var csv = headers.map(function(h){return '\"'+h+'\"';}).join(\",\")+\"\\n\"+rows.join(\"\\n\");\n    var blob = new Blob([csv], {type:\"text\/csv\"});\n    var a = document.createElement(\"a\");\n    a.href = URL.createObjectURL(blob);\n    a.download = \"moses-aviation-squawk-log.csv\";\n    a.click();\n  }\n\n  \/* ---------- auth ---------- *\/\n  function showApp(session){\n    document.getElementById(\"auth-screen\").style.display = \"none\";\n    document.getElementById(\"app-root\").style.display = \"\";\n    document.getElementById(\"who-email\").textContent = session.user.email;\n    fetchAll().then(subscribeRealtime);\n  }\n  function showAuthScreen(){\n    document.getElementById(\"auth-screen\").style.display = \"flex\";\n    document.getElementById(\"app-root\").style.display = \"none\";\n    if(channel){ supabase.removeChannel(channel); channel = null; }\n  }\n\n  function signIn(){\n    var email = document.getElementById(\"auth-email\").value.trim();\n    var password = document.getElementById(\"auth-password\").value;\n    var errEl = document.getElementById(\"auth-error\");\n    errEl.style.display = \"none\";\n    if(!email || !password){ errEl.textContent = \"Enter your email and password.\"; errEl.style.display=\"block\"; return; }\n    var btn = document.getElementById(\"btn-signin\");\n    btn.disabled = true; btn.textContent = \"Signing in\u2026\";\n    supabase.auth.signInWithPassword({email:email, password:password}).then(function(res){\n      btn.disabled = false; btn.textContent = \"Sign In\";\n      if(res.error){ errEl.textContent = res.error.message; errEl.style.display = \"block\"; return; }\n      \/\/ onAuthStateChange handles the rest\n    });\n  }\n  function signOut(){\n    supabase.auth.signOut();\n  }\n\n  \/* ---------- events ---------- *\/\n  document.querySelectorAll(\".tab\").forEach(function(t){\n    t.addEventListener(\"click\", function(){ switchView(t.dataset.view); });\n  });\n  document.getElementById(\"search\").addEventListener(\"input\", function(e){ state.search=e.target.value; renderLog(); });\n  document.getElementById(\"f-tail\").addEventListener(\"change\", function(e){ state.tail=e.target.value; renderLog(); updateFiltersCount(); });\n  document.getElementById(\"f-status\").addEventListener(\"change\", function(e){ state.status=e.target.value; renderLog(); updateFiltersCount(); });\n  document.getElementById(\"f-severity\").addEventListener(\"change\", function(e){ state.severity=e.target.value; renderLog(); updateFiltersCount(); });\n  document.getElementById(\"f-grounding\").addEventListener(\"change\", function(e){ state.grounding=e.target.value; renderLog(); updateFiltersCount(); });\n\n  function updateFiltersCount(){\n    var n = [\"tail\",\"status\",\"severity\",\"grounding\"].filter(function(k){ return !!state[k]; }).length;\n    document.getElementById(\"filters-count\").textContent = n ? n : \"\";\n  }\n  function toggleFilters(forceOpen){\n    var row = document.getElementById(\"filter-row\");\n    var btn = document.getElementById(\"btn-toggle-filters\");\n    var open = forceOpen !== undefined ? forceOpen : row.classList.contains(\"collapsed\");\n    row.classList.toggle(\"collapsed\", !open);\n    btn.classList.toggle(\"open\", open);\n  }\n  document.getElementById(\"btn-toggle-filters\").addEventListener(\"click\", function(){ toggleFilters(); });\n  document.getElementById(\"btn-clear-filters\").addEventListener(\"click\", function(){\n    state.tail = state.status = state.severity = state.grounding = \"\";\n    document.getElementById(\"f-tail\").value = \"\";\n    document.getElementById(\"f-status\").value = \"\";\n    document.getElementById(\"f-severity\").value = \"\";\n    document.getElementById(\"f-grounding\").value = \"\";\n    updateFiltersCount();\n    renderLog();\n  });\n  document.querySelectorAll(\"#log-table thead th\").forEach(function(th){\n    th.addEventListener(\"click\", function(){\n      var k = th.dataset.sort;\n      if(state.sortKey===k) state.sortDir *= -1; else { state.sortKey=k; state.sortDir=1; }\n      renderLog();\n    });\n  });\n  document.getElementById(\"btn-new\").addEventListener(\"click\", function(){ openDrawer(null); });\n  document.getElementById(\"btn-new-tail\").addEventListener(\"click\", addOrModifyAircraftPrompt);\n  document.getElementById(\"btn-export\").addEventListener(\"click\", exportCsv);\n  document.getElementById(\"drawer-close\").addEventListener(\"click\", closeDrawer);\n  document.getElementById(\"btn-cancel\").addEventListener(\"click\", closeDrawer);\n  document.getElementById(\"btn-save\").addEventListener(\"click\", saveDrawer);\n  document.getElementById(\"btn-delete\").addEventListener(\"click\", deleteRow);\n  overlay.addEventListener(\"click\", closeDrawer);\n  document.addEventListener(\"keydown\", function(e){ if(e.key===\"Escape\") closeDrawer(); });\n  document.getElementById(\"btn-signin\").addEventListener(\"click\", signIn);\n  document.getElementById(\"auth-password\").addEventListener(\"keydown\", function(e){ if(e.key===\"Enter\") signIn(); });\n  document.getElementById(\"btn-signout\").addEventListener(\"click\", signOut);\n\n  \/* ---------- init ---------- *\/\n  supabase.auth.onAuthStateChange(function(event, session){\n    if(session) showApp(session); else showAuthScreen();\n  });\n  supabase.auth.getSession().then(function(res){\n    if(res.data.session) showApp(res.data.session); else showAuthScreen();\n  });\n})();\n<\/script>\n<\/body>\n<\/html>\n","protected":false},"excerpt":{"rendered":"<p>Moses Aviation \u2014 Squawk Log MAINTENANCE RECORD \u00b7 SIGN IN Moses Aviation Squawk Log Shared, live maintenance log. Sign in with the account your admin set up for you. Email Password Sign In Don&#8217;t have an account? Ask your maintenance admin to add your email in Supabase. MAINTENANCE RECORD Live Moses Aviation \u2014 Squawk Log [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-5051","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/mosesaviation.com\/index.php\/wp-json\/wp\/v2\/pages\/5051","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/mosesaviation.com\/index.php\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/mosesaviation.com\/index.php\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/mosesaviation.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/mosesaviation.com\/index.php\/wp-json\/wp\/v2\/comments?post=5051"}],"version-history":[{"count":46,"href":"https:\/\/mosesaviation.com\/index.php\/wp-json\/wp\/v2\/pages\/5051\/revisions"}],"predecessor-version":[{"id":5130,"href":"https:\/\/mosesaviation.com\/index.php\/wp-json\/wp\/v2\/pages\/5051\/revisions\/5130"}],"wp:attachment":[{"href":"https:\/\/mosesaviation.com\/index.php\/wp-json\/wp\/v2\/media?parent=5051"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}