/* ==========================================================================
   GLASS LAYOUT — structural rules. Load AFTER glass-theme.css.

   glass-theme.css changes how surfaces LOOK. This file changes how screens are
   ARRANGED: page frames, grid tracks, DOM order. Pair each block with the
   matching skeleton in markup/.

   These rules intentionally replace Tailwind layout utilities on the view
   roots. Strip the utilities from the elements you give these classes to —
   don't stack them (see README §"Tailwind utilities").
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. PAGE FRAME
   Every screen is a full-height flex column: header, body, footer strip.
   The body is the only thing that scrolls, so the header and the save-state
   strip never leave the viewport.
   -------------------------------------------------------------------------- */
.glass-view .g-screen {
  display: flex;
  flex-direction: column;
  gap: 16px;
  box-sizing: border-box;
  padding: 18px;
  min-height: 100vh;
}
.glass-view .g-screen__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  padding: 0 4px;
  flex: none;
}
.glass-view .g-screen__title { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.glass-view .g-screen__actions { display: flex; align-items: center; gap: 9px; flex: none; }
.glass-view .g-screen__body { flex: 1; min-height: 0; }
.glass-view .g-screen__foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  padding: 13px 18px;
  flex: none;
}

/* --------------------------------------------------------------------------
   2. APP SHELL — sidebar + content (workspace, dashboard)
   -------------------------------------------------------------------------- */
.glass-view .g-shell {
  display: grid;
  grid-template-columns: 216px minmax(0, 1fr);
  gap: 18px;
  box-sizing: border-box;
  padding: 18px;
  min-height: 100vh;
  align-items: start;
}
.glass-view .g-sidebar {
  display: flex;
  flex-direction: column;
  gap: 22px;
  padding: 20px 14px;
  min-height: calc(100vh - 36px);
  position: sticky;
  top: 18px;
}
.glass-view .g-sidebar__nav { display: flex; flex-direction: column; gap: 3px; }
.glass-view .g-sidebar__item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 10px 12px;
  border-radius: 11px;
  font: 500 13px var(--g-font-ui);
  color: var(--g-ink-soft);
  text-decoration: none;
}
.glass-view .g-sidebar__item[aria-current="page"] {
  background: var(--g-btn-bg);
  color: var(--g-btn-ink);
  font-weight: 600;
}
/* Pushes the save-state block to the bottom of the rail. */
.glass-view .g-sidebar__foot { margin-top: auto; display: flex; flex-direction: column; gap: 3px; padding: 0 8px; }
.glass-view .g-main { display: flex; flex-direction: column; gap: 16px; min-width: 0; }

/* --------------------------------------------------------------------------
   3. WORKSPACE CARD GRID
   Two equal work columns + a narrower status rail.
   -------------------------------------------------------------------------- */
.glass-view .g-work {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) 288px;
  gap: 16px;
  align-items: start;
}
.glass-view .g-work__col { display: flex; flex-direction: column; gap: 16px; min-width: 0; }
@media (max-width: 1180px) {
  .glass-view .g-work { grid-template-columns: minmax(0, 1fr) 288px; }
  .glass-view .g-work__col--rail { grid-column: 2; grid-row: 1 / span 2; }
}
@media (max-width: 900px) {
  .glass-view .g-shell { grid-template-columns: minmax(0, 1fr); }
  .glass-view .g-sidebar { position: static; min-height: 0; }
  .glass-view .g-work { grid-template-columns: minmax(0, 1fr); }
  .glass-view .g-work__col--rail { grid-column: auto; grid-row: auto; }
}

/* --------------------------------------------------------------------------
   4. SPLIT WORKBENCH — form left, live document right (RPH)
   The document pane sticks while the form scrolls: the whole point of the
   layout is that the minutes visibly total 60 as you type.
   -------------------------------------------------------------------------- */
.glass-view .g-split {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 384px;
  gap: 16px;
  align-items: start;
}
.glass-view .g-split__form { display: flex; flex-direction: column; gap: 14px; min-width: 0; }
.glass-view .g-split__doc {
  position: sticky;
  top: 18px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
@media (max-width: 1100px) {
  .glass-view .g-split { grid-template-columns: minmax(0, 1fr); }
  .glass-view .g-split__doc { position: static; order: -1; }
}

/* --------------------------------------------------------------------------
   5. STEP RAIL + CONTEXT STRIP (RPH header block)
   Replaces the tall metadata block with one scannable line.
   -------------------------------------------------------------------------- */
.glass-view .g-steps { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; }
.glass-view .g-step { display: flex; flex-direction: column; gap: 7px; }
.glass-view .g-step__bar { height: 4px; border-radius: 2px; background: var(--g-border-strong); }
.glass-view .g-step[data-state="done"] .g-step__bar { background: var(--g-teal); }
.glass-view .g-step[aria-current="step"] .g-step__bar { background: var(--g-accent); }
.glass-view .g-step__label { font: 400 11.5px var(--g-font-ui); color: var(--g-ink-faint); }
.glass-view .g-step[aria-current="step"] .g-step__label { font-weight: 600; color: var(--g-ink); }

.glass-view .g-context {
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
  padding-top: 12px;
  border-top: 1px solid var(--g-border);
}
.glass-view .g-context__cell { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.glass-view .g-context__rule { width: 1px; height: 26px; background: var(--g-border); flex: none; }
.glass-view .g-context__total { margin-left: auto; display: flex; align-items: baseline; gap: 6px; }

/* --------------------------------------------------------------------------
   6. PHASE LIST (RPH) — one expanded, the rest collapsed to budget rows
   -------------------------------------------------------------------------- */
.glass-view .g-phase__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 15px 20px;
  border-bottom: 1px solid var(--g-border);
}
.glass-view .g-phase__grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 14px;
  padding: 16px 20px;
}
.glass-view .g-phase__field { display: flex; flex-direction: column; gap: 7px; min-width: 0; }
.glass-view .g-phase__field textarea { min-height: 70px; resize: none; }
.glass-view .g-phase__rows { display: flex; flex-direction: column; gap: 7px; padding: 0 20px 16px; }
.glass-view .g-phase__row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 12px 16px;
  border-radius: var(--g-radius-control);
  background: var(--g-surface-inset);
  border: 1px solid var(--g-border);
}
.glass-view .g-phase__row[data-state="empty"] { border-style: dashed; border-color: rgba(5, 182, 197, 0.3); }
@media (max-width: 720px) {
  .glass-view .g-phase__grid { grid-template-columns: minmax(0, 1fr); }
}

/* --------------------------------------------------------------------------
   7. QUADRANT GRID (journal) — a real 2x2, equal heights
   -------------------------------------------------------------------------- */
.glass-view .g-quad {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  grid-template-rows: repeat(2, minmax(0, 1fr));
  gap: 14px;
  height: 100%;
  min-height: 0;
}
.glass-view .g-quad__cell {
  display: flex;
  flex-direction: column;
  gap: 11px;
  padding: 18px 20px;
  min-height: 0;
}
.glass-view .g-quad__head { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
/* The textarea absorbs the cell's spare height so all four stay equal. */
.glass-view .g-quad__cell textarea { flex: 1; min-height: 0; resize: none; }
.glass-view .g-quad__n {
  display: flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; border-radius: 7px; flex: none;
  background: var(--g-btn-bg); color: var(--g-btn-ink);
  font: 600 11px var(--g-font-mono);
}
.glass-view .g-quad__cell[data-state="empty"] textarea { border-style: dashed; }
@media (max-width: 900px) {
  .glass-view .g-quad { grid-template-columns: minmax(0, 1fr); grid-template-rows: none; }
  .glass-view .g-quad__cell textarea { min-height: 120px; }
}

/* Day selector — shared by journal and attendance */
.glass-view .g-days { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 7px; flex: 1; }
.glass-view .g-day {
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  padding: 11px 0; border-radius: 11px;
  background: var(--g-surface-inset); border: 1px solid var(--g-border);
  cursor: pointer;
}
.glass-view .g-day[data-state="done"] { background: rgba(47, 125, 106, 0.16); border-color: rgba(47, 125, 106, 0.32); }
.glass-view .g-day[aria-current="date"] { background: var(--g-btn-bg); border-color: transparent; }
.glass-view .g-day[aria-current="date"] * { color: var(--g-btn-ink); }

/* --------------------------------------------------------------------------
   8. LEDGER (attendance) — CSS-grid table, one track set on every row
   Change the track list in ONE place and header + rows stay aligned.
   test_attendance_hours.js covers the maths; this is layout only.
   -------------------------------------------------------------------------- */
.glass-view .g-ledger { display: flex; flex-direction: column; overflow: hidden; height: 100%; }
.glass-view .g-ledger__row {
  display: grid;
  grid-template-columns: 118px minmax(0, 1fr) minmax(0, 1fr) 84px minmax(0, 1fr) 92px;
  gap: 12px;
  align-items: center;
  padding: 13px 20px;
  border-bottom: 1px solid var(--g-border);
}
.glass-view .g-ledger__row--head { padding: 14px 20px; }
.glass-view .g-ledger__row[aria-current="date"] { background: var(--g-surface-inset); }
.glass-view .g-ledger__row:last-of-type { border-bottom: none; }
.glass-view .g-ledger__hours { text-align: right; font-variant-numeric: tabular-nums; }
.glass-view .g-ledger__status { justify-self: end; }
.glass-view .g-ledger__foot {
  margin-top: auto;
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  padding: 14px 20px;
  border-top: 1px solid var(--g-border);
}
/* Below ~1180px the tracks stop fitting. Scroll horizontally rather than
   reflowing to cards — a timesheet is read by column. */
@media (max-width: 1180px) {
  .glass-view .g-ledger__scroll { overflow-x: auto; }
  .glass-view .g-ledger { min-width: 1140px; }
}

/* Summary tiles */
.glass-view .g-tiles { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 14px; }
.glass-view .g-tile { display: flex; flex-direction: column; gap: 6px; padding: 18px 20px; }
.glass-view .g-tile__value { display: flex; align-items: baseline; gap: 7px; }
@media (max-width: 900px) { .glass-view .g-tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

/* --------------------------------------------------------------------------
   9. CENTRED ENTRY (login) — card centred in an ambient field
   Unscoped, unlike every other section here: #view-login never carries
   .glass-view (the colour migration deliberately kept the public page on
   its own body.no-shell/.lp-* mode mechanism), so a .glass-view prefix
   here would just never match. .g-field is reused unscoped by profile too.
   -------------------------------------------------------------------------- */
.g-entry {
  display: flex; flex-direction: column;
  box-sizing: border-box;
  min-height: 100vh;
  padding: 26px 30px 30px;
}
.g-entry__head { display: flex; align-items: center; justify-content: space-between; gap: 20px; flex: none; }
.g-entry__body {
  flex: 1; min-height: 0;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 22px; padding: 14px 0;
}
/* Headline sits ABOVE the card, not inside it. */
.g-entry__lede { margin: 0; max-width: 22ch; text-align: center; font-size: clamp(24px, 3.4vw, 31px); }
.g-entry__card {
  width: 100%; max-width: 428px; box-sizing: border-box;
  padding: 30px 30px 26px; border-radius: 26px;
  display: flex; flex-direction: column; gap: 18px;
}
.g-field { display: flex; flex-direction: column; gap: 6px; }
.g-field > input { padding: 13px 14px; }
.g-entry__row { display: flex; align-items: center; justify-content: space-between; gap: 14px; }
.g-entry__foot {
  padding-top: 14px; border-top: 1px solid var(--g-border);
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
}
@media (max-width: 480px) {
  .g-entry { padding: 12px 20px 26px; }
  .g-entry__card { padding: 24px 22px; border-radius: 24px; }
  /* style.css already forces 16px inputs on mobile to stop iOS zoom. Keep it. */
  .g-entry__card button { min-height: 52px; }
}

/* --------------------------------------------------------------------------
   10. SETTINGS SCREEN (profile) — form + section rail + live document
   Pair with markup/profile.html. Same split as .g-split, but the rail holds
   navigation AND the document, so it needs its own width.
   -------------------------------------------------------------------------- */
.glass-view .g-settings {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 340px;
  gap: 16px;
  align-items: start;
}
.glass-view .g-settings__form { display: flex; flex-direction: column; gap: 14px; min-width: 0; }
.glass-view .g-settings__rail {
  position: sticky;
  top: 18px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
@media (max-width: 1100px) {
  .glass-view .g-settings { grid-template-columns: minmax(0, 1fr); }
  .glass-view .g-settings__rail { position: static; }
}

/* Numbered section card */
.glass-view .g-section { padding: 0; overflow: hidden; }
.glass-view .g-section__head {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 15px 20px;
  border-bottom: 1px solid var(--g-border);
}
.glass-view .g-section__n {
  display: flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; border-radius: 7px; flex: none;
  background: var(--g-btn-bg); color: var(--g-btn-ink);
  font: 600 11px var(--g-font-mono);
}
.glass-view .g-section__title { margin: 0; font: 600 15px var(--g-font-ui); color: var(--g-ink); }
.glass-view .g-section__note { margin-left: auto; flex: none; }
.glass-view .g-section__body { padding: 18px 20px; }
.glass-view .g-section__grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 14px;
  padding: 18px 20px;
}
.glass-view .g-section__body .g-section__grid { padding: 0; }
.glass-view .g-field--wide { grid-column: span 2; }
.glass-view .g-field__pair { display: flex; gap: 10px; }
.glass-view .g-field__pair > input:first-child { flex: 1; min-width: 0; }
@media (max-width: 760px) {
  .glass-view .g-section__grid { grid-template-columns: minmax(0, 1fr); }
  .glass-view .g-field--wide { grid-column: auto; }
  .glass-view .g-field__pair { flex-direction: column; }
  .glass-view .g-field__pair > input { width: 100% !important; }
}

/* Completeness meter */
.glass-view .g-meter {
  display: flex; align-items: center; gap: 22px; flex-wrap: wrap;
  padding: 16px 20px;
}
.glass-view .g-meter__score { display: flex; align-items: center; gap: 14px; flex: 1 1 auto; min-width: 0; }
.glass-view .g-meter__dial {
  display: flex; align-items: center; justify-content: center;
  width: 52px; height: 52px; border-radius: 50%; flex: none;
  background: conic-gradient(var(--g-teal) 0 var(--g-pct, 0%), var(--g-border-strong) var(--g-pct, 0%));
}
.glass-view .g-meter__dial > span {
  display: flex; align-items: center; justify-content: center;
  width: 39px; height: 39px; border-radius: 50%;
  background: var(--g-bg); font-size: 13px;
}
.glass-view .g-meter__rule { width: 1px; height: 40px; background: var(--g-border); flex: none; }
.glass-view .g-meter__chips {
  display: flex; gap: 8px; flex-wrap: wrap; flex: 1; min-width: 0;
  list-style: none; margin: 0; padding: 0;
}

/* Chips (subjects, classes, materials) */
.glass-view .g-chips {
  display: flex; flex-wrap: wrap; gap: 6px; align-items: center;
  list-style: none; margin: 0;
  padding: 9px;
  min-height: 38px; box-sizing: border-box;
  border: 1px solid var(--g-border-strong);
  border-radius: var(--g-radius-control);
  background: var(--g-surface-inset);
}
.glass-view .g-chip {
  padding: 6px 11px; border-radius: 8px; border: none;
  background: var(--g-btn-bg); color: var(--g-btn-ink);
  font: 500 12px var(--g-font-ui);
}
.glass-view .g-chips--quiet .g-chip {
  padding: 5px 10px; font-size: 11px;
  background: var(--g-surface-raised); color: var(--g-ink);
}
.glass-view .g-chip--accent {
  background: rgba(5, 182, 197, 0.18); color: var(--g-cyan-pale);
  border: 1px solid rgba(5, 182, 197, 0.3);
}
.glass-view .g-chip--add {
  background: transparent; color: var(--g-ink-soft);
  border: 1px dashed var(--g-border-strong); cursor: pointer;
}

/* Logo dropzone */
.glass-view .g-dropzone {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 6px; height: 112px; padding: 8px; box-sizing: border-box;
  border: 1px dashed var(--g-border-strong); border-radius: 14px;
  text-align: center; cursor: pointer;
  font: 500 10.5px/1.35 var(--g-font-ui); color: var(--g-ink-soft);
}
.glass-view .g-dropzone--pending {
  border-color: rgba(5, 182, 197, 0.34);
  background: rgba(5, 182, 197, 0.06);
  color: var(--g-cyan-pale);
}
.glass-view .g-dropzone__icon {
  display: flex; align-items: center; justify-content: center;
  width: 26px; height: 26px; border-radius: 8px;
  background: rgba(5, 182, 197, 0.22);
  font: 600 13px var(--g-font-mono);
}

/* Derived-value readouts — show the maths, don't hide it */
.glass-view .g-derived {
  display: flex; align-items: center; gap: 18px;
  margin: 0; padding: 12px 16px;
}
.glass-view .g-derived div { display: flex; flex-direction: column; gap: 2px; }
.glass-view .g-derived dt { margin: 0; }
.glass-view .g-derived dd { margin: 0; font-size: 14px; }
.glass-view .g-derived__rule { width: 1px; height: 24px; background: var(--g-border); }
.glass-view .g-readout {
  display: flex; align-items: center; gap: 14px;
  flex: 1; min-width: 210px; margin: 0; padding: 12px 16px;
}

/* Three-up mini cards (data & backup) */
.glass-view .g-cards3 { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; }
.glass-view .g-minicard {
  display: flex; flex-direction: column; gap: 9px;
  padding: 15px; border-radius: 14px;
}
.glass-view .g-minicard h3 { margin: 0; font: 600 12.5px var(--g-font-ui); color: var(--g-ink); }
.glass-view .g-minicard p { margin: 0; flex: 1; font: 400 11px/1.5 var(--g-font-ui); color: var(--g-ink-soft); }
.glass-view .g-minicard--warn {
  background: rgba(5, 182, 197, 0.07);
  border: 1px solid rgba(5, 182, 197, 0.2);
}
@media (max-width: 860px) { .glass-view .g-cards3 { grid-template-columns: minmax(0, 1fr); } }

/* Section rail */
.glass-view .g-rail { display: flex; flex-direction: column; gap: 10px; padding: 16px 18px; }
.glass-view .g-rail ol { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 2px; }
.glass-view .g-rail a {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 10px; border-radius: 10px;
  font: 500 12px var(--g-font-ui); color: var(--g-ink-soft); text-decoration: none;
}
.glass-view .g-rail a[aria-current="true"] {
  background: var(--g-surface-raised); color: var(--g-ink); font-weight: 600;
}
.glass-view .g-rail a > .glass-num { font-size: 10px; color: var(--g-ink-faint); }
.glass-view .g-rail__dot {
  margin-left: auto; width: 6px; height: 6px; border-radius: 50%;
  background: var(--g-cyan);
}


/* --------------------------------------------------------------------------
   MODALS — onboarding wizard, user guide / FAQ, install guide
   The three modals owned by static/js/onboarding.js. The JS toggles Tailwind's
   .hidden / .flex on the root, so NEVER declare `display` on .g-modal —
   it would fight that toggle. Style alignment and scrim only.
   -------------------------------------------------------------------------- */
.app-modal.g-modal {
  align-items: center;
  justify-content: center;
  padding: 24px;
  backdrop-filter: blur(7px);
  -webkit-backdrop-filter: blur(7px);
}
body[data-glass-mode="dark"] .app-modal.g-modal { background: rgba(4, 6, 10, 0.62); }
body[data-glass-mode="light"] .app-modal.g-modal { background: rgba(11, 60, 104, 0.3); }

.g-modal__panel {
  width: 100%;
  max-width: 900px;
  max-height: calc(100vh - 48px);
  display: flex;
  flex-direction: column;
  border-radius: 26px;
  overflow: hidden;
  background: var(--g-surface-raised);
  border: 1px solid var(--g-border-strong);
  box-shadow: var(--g-shadow), var(--g-specular);
  backdrop-filter: var(--g-blur);
  -webkit-backdrop-filter: var(--g-blur);
}
/* Same as .drive-announce__card: iOS's 100vh ignores its visible toolbar, so a
   tall panel's footer sat under it. */
@supports (height: 100dvh) {
  .g-modal__panel { max-height: calc(100dvh - 48px); }
}
.g-modal__panel--narrow { max-width: 680px; }
.g-modal__head {
  display: flex;
  align-items: flex-start;
  gap: 20px;
  padding: 26px 30px 22px;
  border-bottom: 1px solid var(--g-border);
  flex: none;
}
.g-modal__title { display: flex; flex-direction: column; gap: 9px; min-width: 0; flex: 1; }
.g-modal__x {
  width: 34px; height: 34px; flex: none;
  border-radius: 11px;
  background: var(--g-surface-inset);
  border: 1px solid var(--g-border-strong);
  color: var(--g-ink-soft);
  cursor: pointer;
}
/* Only the body scrolls — same contract as .g-screen__body. */
.g-modal__body { flex: 1; min-height: 0; overflow-y: auto; }
.g-modal__foot {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  padding: 16px 30px;
  border-top: 1px solid var(--g-border);
  background: var(--g-surface-inset);
  flex: none;
}

/* Wizard: form left, "what this fills" right. The right column is the whole
   point — it is why a teacher finishes the form instead of skipping it. */
/* The wizard IS the panel's scrolling body — it replaces .g-modal__body
   rather than sitting inside one, so it has to carry that contract itself.
   Without `min-height: 0` a flex item refuses to shrink below its content,
   so the grid kept its full height, the panel's `overflow: hidden` clipped
   it, and on a 375px phone the last 500px — weekend radios, both dates and
   the Next button — could not be reached at all. */
.g-wizard {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 316px;
  min-height: 0;
  overflow-y: auto;
}
.g-wizard__form { padding: 24px 30px 26px; display: flex; flex-direction: column; gap: 18px; min-width: 0; }
.g-wizard__aside {
  padding: 24px 26px;
  border-left: 1px solid var(--g-border);
  background: var(--g-surface-inset);
  display: flex; flex-direction: column; gap: 14px;
}
.g-wizard__weeks { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 6px; }
/* Step dots. onboarding.js currently assigns Tailwind classNames here —
   change updateStepView() to set data-state instead (see modals.html). */
.g-progress { display: flex; align-items: center; gap: 6px; }
.g-progress__seg {
  height: 4px; width: 16px; border: none; padding: 0; border-radius: 99px;
  background: var(--g-border-strong);
  cursor: pointer;
  transition: all 0.25s ease;
}
.g-progress__seg[data-state="done"] { background: var(--g-accent); opacity: 0.5; }
.g-progress__seg[aria-current="step"] { width: 38px; background: var(--g-accent); opacity: 1; }

/* FAQ: questions become a left-hand nav, answer on the right.
   Four stacked blocks meant scrolling to find a question. */
.g-faq { display: grid; grid-template-columns: 296px minmax(0, 1fr); min-height: 328px; }
.g-faq__nav { padding: 20px; display: flex; flex-direction: column; gap: 8px; border-right: 1px solid var(--g-border); }
.g-faq__item {
  width: 100%; box-sizing: border-box; text-align: left;
  padding: 11px 13px; border-radius: 12px;
  background: var(--g-surface-inset);
  border: 1px solid var(--g-border);
  color: var(--g-ink-soft);
  font: 600 11.5px/1.35 var(--g-font-ui);
  cursor: pointer;
  transition: all 0.18s ease;
}
.g-faq__item[aria-selected="true"] {
  background: rgba(2, 132, 199, 0.1);
  border-color: rgba(2, 132, 199, 0.32);
  color: var(--g-ink);
}
.g-faq__panel { padding: 24px 30px; background: var(--g-surface-inset); display: flex; flex-direction: column; gap: 12px; }
/* Tailwind's .hidden has no !important in this build, so it loses to the
   display:flex above on equal specificity + source order — this two-class
   selector outranks both regardless of load order. */
.g-faq__panel.hidden { display: none; }

/* Install guide: numbered rows, not a paragraph of instructions. */
.g-steplist { display: flex; flex-direction: column; gap: 10px; padding: 0 28px 24px; }
.g-steplist__item {
  display: flex; gap: 14px;
  padding: 15px 16px; border-radius: 15px;
  background: var(--g-surface-inset);
  border: 1px solid var(--g-border);
}
.g-steplist__item--last { background: rgba(2, 132, 199, 0.08); border-color: rgba(2, 132, 199, 0.24); }
.g-steplist__n {
  width: 26px; height: 26px; flex: none;
  display: flex; align-items: center; justify-content: center;
  border-radius: 9px;
  background: var(--g-btn-bg); color: var(--g-btn-ink);
  font: 600 12px var(--g-font-mono);
}
.g-steplist__text { display: flex; flex-direction: column; gap: 4px; min-width: 0; }

@media (max-width: 860px) {
  .g-wizard,
  .g-faq { grid-template-columns: minmax(0, 1fr); }
  .g-wizard__aside { border-left: none; border-top: 1px solid var(--g-border); }
  .g-faq__nav { border-right: none; border-bottom: 1px solid var(--g-border); }
}

/* ==================================================================
   11. TOUCH TARGETS — the classes the base rule deliberately excludes
   The app-wide minimum lives in style.css, keyed on `pointer: coarse`.
   Its selector opts out of the controls meant to stay compact, and a few
   of those were genuinely too small to hit on an iPad: the BM/EN pills
   were 20px tall, the light/dark switch 26px, an FAQ question's
   <summary> 20px (only <summary> toggles a <details> — the card padding
   around it does not), and the calendar button beside a practicum date
   a 30px square. A mouse is precise and the compact chrome is deliberate
   there, so none of this applies to one.
   ================================================================== */
@media (pointer: coarse) {
  /* Height only. A 44px *width* on both pills plus both mode icons added
     ~50px to the header's right-hand group, which squeezed the brand from
     "Cikgu.cc" to "Cik…" at 375px. Height is the dimension a thumb misses
     on; these stay comfortably wide through their own padding. */
  .ready-header .lang-toggle__btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 44px;
  }
  .glass-seg__btn--icon { min-width: 40px; min-height: 44px; }
  .ready-theme .ui-btn--sm { min-height: 44px; }
  .ready-theme .ai-icon-button { width: 44px; height: 44px; }

  /* Plain <a>, so the base rule's `a[role="button"]` does not reach it. */
  .glass-view .g-rail a { min-height: 44px; }
  .glass-view .faq-item > summary { min-height: 44px; }

  .date-field__pick { width: 44px; height: 44px; right: 2px; }
  .date-field > input[type='text'] { padding-right: 3.25rem; }
}

/* The phone header carries four actions beside the brand. Keep its three
   segmented/labelled tools on one compact 36px rhythm; the generic 44px
   touch rule is intentionally reserved for roomier page controls. Tablets
   retain the larger targets above. */
@media (pointer: coarse) and (max-width: 639px) {
  .ready-header .lang-toggle__btn {
    min-height: 36px;
    padding: 3px 7px;
    font-size: 10.5px;
  }

  .ready-header .glass-seg--chrome {
    gap: 1px;
    padding: 2px;
  }

  .ready-header .glass-seg--chrome .glass-seg__btn--icon {
    min-width: 34px;
    min-height: 36px;
    padding: 5px;
  }

  body[data-glass-mode] .ready-header .ai-launch {
    min-height: 36px;
    padding: 0.3rem 0.55rem;
    border-radius: 9px;
    font-size: 0.68rem;
  }
}

/* ── Toasts above every dialog ───────────────────────────────────────────────
   The container's z-50 sat below every notice and confirm (z-60 to z-65), so a
   message raised while one was open — the .zip export's "Backup saved" counts
   under the maintenance notice, an error under the cloud-copy confirm — was
   painted beneath the dimmed overlay and faded out unseen. */
#toastContainer { z-index: 70; }

/* ── A floor for the smallest text ──────────────────────────────────────────
   The bottom navigation, the backup buttons, the week tracker and the
   Overview's small figures were set at 7.5–10px, in px, so they neither read
   comfortably on a phone nor grow with the browser's text-size setting. 11px
   in rem is still compact enough for every one of these slots. In this file
   because it loads last, so the rules below win over the component CSS that
   set the sizes without needing !important. */
#bottomNav .bottom-nav-btn,
.glass-view .ws-week__lbl,
.glass-view .ws-quad,
.glass-view .ws-backup-actions .ws-drop > span,
.ov-mini-lbl,
.text-\[7px\],
.text-\[7\.5px\],
.text-\[8px\],
.text-\[8\.5px\],
.text-\[9px\],
.text-\[9\.5px\] {
  font-size: 0.6875rem;
}
/* The one slot that cannot take 11px everywhere: six bottom-nav labels share a
   phone's width, and at 360px "Attendance" needs 66px of a 60px button. Below
   400px the labels drop to 10px with the side padding and a hair of tracking
   taken off — still larger than the 9.5px they were, and every label fits at
   360px in both languages. (At 320px "Attendance" truncates, as it already did
   at 9.5px.) */
/* Equal space between the tabs, not equal cells. Six equal cells centre each
   label in its own sixth, so the white space between "Muat Naik" and
   "Kehadiran" was half that between "Profil" and "Bantuan", and the right edge
   had more room than the left. The tabs keep a thumb-sized minimum. */
#bottomNav > .grid { display: flex; justify-content: space-evenly; align-items: stretch; }
#bottomNav > .grid > .bottom-nav-btn { flex: 0 1 auto; min-width: 3.25rem; padding: 0 0.3rem; }
@media (max-width: 399.98px) {
  #bottomNav .bottom-nav-btn { font-size: 0.625rem; letter-spacing: -0.01em; }
  #bottomNav .bottom-nav-btn span.truncate { padding-left: 0; padding-right: 0; }
}

/* Lesson-plan rows on a phone. Five always-visible actions took ~130px of a
   375px row and left the plan's title about 100px — a dozen characters. Below
   480px the actions wrap onto their own line under the title, so the title has
   the row's width; tapping the row still opens the plan. */
@media (max-width: 479.98px) {
  .glass-view .ws-rph-row { flex-wrap: wrap; row-gap: 6px; }
  .glass-view .ws-rph-row__actions { flex-basis: 100%; justify-content: flex-end; }
}


/* ── The smallest phones (≤359px: iPhone SE 1st gen, small Androids) ─────────
   Measured at 320px: the header's tools pushed sign-out past the screen edge,
   the week tracker's sixth column was cut by the card, and the Overview's
   heading row pushed "Minggu" off its card. The Tutorial button leaves the
   header here — Profile and Bantuan both open the tours. */
@media (max-width: 359.98px) {
  .ready-header #header-tutorial-btn { display: none; }
  .ready-header .max-w-7xl { padding-left: 0.5rem; padding-right: 0.5rem; }
  .ready-header .max-w-7xl > .flex { gap: 0.4rem; }
  .ready-header .max-w-7xl > .flex > .flex-shrink-0 > * + * { margin-left: 0.25rem !important; }
  .glass-view .glass-weeks { grid-template-columns: repeat(4, 1fr); }
  .glass-view .ov-page-head { flex-wrap: wrap; }
  .glass-view .ov-page-head__actions { flex-shrink: 1; flex-wrap: wrap; }
}

/* ── Touch targets the audit measured under 32px ────────────────────────────
   Hit area only: the visuals keep their size. */
@media (pointer: coarse) {
  .rph-head__back { width: 2.5rem; height: 2.5rem; margin-left: -0.75rem; }
  #login-remember { width: 1.25rem; height: 1.25rem; }
  label:has(> #login-remember) { min-height: 44px; }
  .glass-view .glass-seg__btn { min-height: 36px; }
  .glass-view a[href^="https://wa.me"], .glass-view a[href^="mailto:"] { min-height: 40px; }
}

/* ── Dark mode reaches the header and the bottom bar ─────────────────────────
   Both were the light chrome in every mode, so a dark page sat between a
   cream header and a cream nav. The switches in the header were styled for a
   light bar, so they turn too. */
body[data-glass-mode='dark'] .ready-header,
body[data-glass-mode='dark'] #bottomNav {
  background: rgba(8, 12, 20, 0.92) !important;
  border-color: rgba(255, 255, 255, 0.1) !important;
  box-shadow: none;
}
body[data-glass-mode='dark'] .ready-header #headerBrand > span:first-child { color: #f3f6fa !important; }
body[data-glass-mode='dark'] .ready-header .ai-launch { color: #9ff4fb; border-color: rgba(79, 216, 228, 0.4); }
body[data-glass-mode='dark'] .ready-header #headerBrand > span + span { color: rgba(243, 246, 250, 0.55); border-color: rgba(255, 255, 255, 0.18); }
body[data-glass-mode='dark'] .ready-header .lang-toggle { background: rgba(255, 255, 255, 0.08); }
body[data-glass-mode='dark'] .ready-header .lang-toggle__btn { color: rgba(243, 246, 250, 0.62); }
body[data-glass-mode='dark'] .ready-header .lang-toggle__btn--active { color: #062a3a; background: #e6f7fa; }
body[data-glass-mode='dark'] .glass-seg--chrome {
  --g-surface-inset: rgba(255, 255, 255, 0.07);
  --g-border-strong: rgba(255, 255, 255, 0.16);
  --g-ink: #f3f6fa;
  --g-ink-soft: rgba(243, 246, 250, 0.6);
  --g-btn-bg: #4fd8e4;
  --g-btn-ink: #062a3a;
}
body[data-glass-mode='dark'] .ready-header .tutorial-launch { background: rgba(255, 255, 255, 0.07); border-color: rgba(255, 255, 255, 0.16); color: #f3f6fa; }
body[data-glass-mode='dark'] #bottomNav .bottom-nav-btn { color: rgba(243, 246, 250, 0.6); }
body[data-glass-mode='dark'] #bottomNav .bottom-nav-btn.text-oum-blue { color: #4fd8e4; }
