/* projects/dgexit/styles.css - the one stylesheet for the DG Exit Exam app.
 *
 * index.php (the introduction + course/set picker), practice.php (the practice
 * room) and answers.php (the answer key) all render into the same shell, so
 * every component class lives here rather than in three <style> blocks that
 * drift apart. Prefix is --dg- / .dg- throughout so nothing collides with the
 * shared site chrome.
 *
 * Palette is the maritime family already used by projects/colregs - deep navy
 * ink on ice, sea blue for action, port red / starboard green for wrong/right.
 */

:root{
  --dg-ink:#0b2239;
  --dg-ink-2:#41586e;
  --dg-sea:#12507e;
  --dg-sea-d:#0e416a;
  --dg-ice:#eef5fb;
  --dg-line:rgba(11,34,57,.13);
  /* --dg-line is a decorative hairline (1.30:1 on white) and that is fine for a
     card edge or a table rule. It is NOT enough for the boundary of a control:
     a .dg-btn, a .dg-opt, a .dg-dot and the answer key's .dg-search are white on
     white, so that hairline is the only thing that says "this is a control", and
     WCAG 1.4.11 wants 3:1 for exactly that. .5 alpha composites to #85909c =
     3.25:1 on white; anything under .48 alpha drops below 3:1, so that is the
     floor if this ever needs dialling back. */
  --dg-line-ui:rgba(11,34,57,.5);
  --dg-soft:rgba(18,80,126,.07);
  /* Starboard green was #00843d, which is only 4.26:1 on its own --dg-ok-bg
     tint — and the tint is where it actually lives ("Available now" on 15 course
     cards, "Correct" in the review list, the correct cells in the question
     grid). One step down in lightness, same hue: 5.17:1 on the tint, 5.84:1 on
     white, and the white-on-green key chip improves from 4.81 to 5.84. */
  --dg-ok:#007536;
  --dg-ok-bg:rgba(0,132,61,.09);
  --dg-bad:#c8102e;
  --dg-bad-bg:rgba(200,16,46,.08);
  /* Same story and the worst pair in the build: #b26a00 is 3.74:1 on its own
     --dg-warn-bg, which carries "Planned", "Held back", "Answer key only",
     "Flagged for review" and "Not answered". #9c5d00 is 4.66:1 there. */
  --dg-warn:#9c5d00;
  --dg-warn-bg:rgba(178,106,0,.10);
  --dg-card:#fff;
  --dg-shadow:0 6px 22px rgba(11,34,57,.09);
  --dg-shadow-lg:0 14px 40px rgba(11,34,57,.14);
  --dg-r:16px;
}

.dg-page{padding:12px 0 40px; color:var(--dg-ink)}
.dg-page *{box-sizing:border-box}

/* ---- generic surfaces ---------------------------------------------------- */
.dg-card{
  background:var(--dg-card); border:1px solid var(--dg-line);
  border-radius:var(--dg-r); box-shadow:var(--dg-shadow); padding:18px;
}
.dg-card + .dg-card{margin-top:14px}
.dg-muted{color:var(--dg-ink-2)}
.dg-center{text-align:center}
.dg-hide{display:none !important}
/* Visually hidden but still in the accessibility tree. `.dg-hide` is
   display:none, which removes a live region from the tree entirely and stops it
   being announced — the status nodes need this instead. */
.dg-sr{
  position:absolute !important; width:1px; height:1px; padding:0; margin:-1px;
  overflow:hidden; clip:rect(0 0 0 0); clip-path:inset(50%); white-space:nowrap; border:0;
}

/* ---- buttons ------------------------------------------------------------- */
.dg-btn{
  display:inline-flex; align-items:center; justify-content:center; gap:8px;
  border:1px solid var(--dg-line-ui); background:#fff; color:var(--dg-ink);
  border-radius:12px; padding:10px 16px; min-height:44px;
  font-family:inherit; font-weight:600; font-size:15px; line-height:1.2; cursor:pointer; text-decoration:none;
  white-space:nowrap; transition:background .15s,border-color .15s,transform .1s;
}
/* .34 alpha composites to 2.0:1, which is now LIGHTER than the resting border —
   hover has to read as more, not less. */
.dg-btn:hover{background:var(--dg-soft); border-color:rgba(18,80,126,.62)}
.dg-btn:active{transform:translateY(1px)}
/* A genuinely `disabled` control is exempt from the contrast minimums, so it can
   stay at .4. `.is-off` is NOT disabled — it is a live, focusable <button> that
   has merely been dimmed with opacity (#dgBack on question 1, #dgFinish once the
   paper is marked), so its label has to pass like any other label. At .4 the ink
   composited to #9da7b0 = 2.45:1; .62 gives #687684 = 4.65:1 and still reads as
   switched off next to its neighbours. */
.dg-btn[disabled]{opacity:.4; pointer-events:none}
.dg-btn.is-off{opacity:.62; pointer-events:none}
.dg-btn-main{background:var(--dg-sea); border-color:var(--dg-sea); color:#fff}
.dg-btn-main:hover{background:var(--dg-sea-d); border-color:var(--dg-sea-d); color:#fff}
.dg-btn-ghost{background:transparent}
.dg-btn-sm{min-height:36px; padding:7px 12px; font-size:14px; border-radius:10px}
.dg-btn-lg{min-height:52px; padding:14px 24px; font-size:17px; border-radius:14px}

/* ---- hero (index) -------------------------------------------------------- */
.dg-hero{
  background:linear-gradient(160deg,#0b2239 0%,#12507e 100%);
  color:#fff; border-radius:20px; padding:28px 24px; box-shadow:var(--dg-shadow-lg);
}
.dg-hero h1{margin:0 0 8px; font-size:clamp(24px,4.4vw,34px); line-height:1.18; font-weight:800}
.dg-hero p{margin:0 0 6px; opacity:.92; font-size:16px; line-height:1.55; max-width:62ch}
.dg-hero-kicker{
  display:inline-block; margin-bottom:12px; font-family:inherit; font-weight:700; font-size:12px; line-height:1;
  letter-spacing:.9px; text-transform:uppercase; opacity:.8;
  border:1px solid rgba(255,255,255,.3); border-radius:999px; padding:6px 11px;
}
.dg-hero-cta{display:flex; flex-wrap:wrap; gap:10px; margin-top:18px}
.dg-hero .dg-btn{border-color:rgba(255,255,255,.34); background:rgba(255,255,255,.12); color:#fff}
.dg-hero .dg-btn:hover{background:rgba(255,255,255,.22)}
.dg-hero .dg-btn-main{background:#fff; color:var(--dg-sea); border-color:#fff}
.dg-hero .dg-btn-main:hover{background:#eaf2f9; color:var(--dg-sea-d)}

/* result gate (practice/mock, guest) — a hero panel reused as the sign-in prompt
   shown in place of the score. .dg-hero styles its <h1>; the gate heading is an
   <h2> for document order, so it needs its own size here. */
.dg-gate{margin-top:14px; outline:none}
.dg-gate h2{margin:0 0 8px; font-size:clamp(22px,4vw,30px); line-height:1.2; font-weight:800}

/* stat strip under the hero */
.dg-stats{display:grid; grid-template-columns:repeat(auto-fit,minmax(140px,1fr)); gap:10px; margin-top:16px}
.dg-stat{background:var(--dg-card); border:1px solid var(--dg-line); border-radius:14px; padding:13px 14px; text-align:center}
.dg-stat b{display:block; font-size:22px; font-weight:800; color:var(--dg-sea); font-variant-numeric:tabular-nums}
.dg-stat span{display:block; font-size:12.5px; color:var(--dg-ink-2); margin-top:3px}

/* ---- section headings ---------------------------------------------------- */
.dg-h2{margin:26px 0 12px; font-size:20px; font-weight:800; display:flex; align-items:center; gap:9px}
.dg-h2::before{content:""; width:5px; height:20px; border-radius:3px; background:var(--dg-sea); flex:none}
.dg-h3{margin:0 0 10px; font-size:16px; font-weight:800}

/* ---- key facts table ----------------------------------------------------- */
.dg-facts{width:100%; border-collapse:collapse; font-size:14.5px}
.dg-facts th,.dg-facts td{padding:10px 12px; border-bottom:1px solid var(--dg-line); text-align:left; vertical-align:top}
.dg-facts th{width:44%; font-weight:700; color:var(--dg-ink-2)}
.dg-facts tr:last-child th,.dg-facts tr:last-child td{border-bottom:0}

/* ---- bullet list with ticks ---------------------------------------------- */
.dg-ticks{list-style:none; margin:0; padding:0}
.dg-ticks li{position:relative; padding:6px 0 6px 26px; font-size:14.5px; line-height:1.5}
.dg-ticks li::before{content:"\2713"; position:absolute; left:0; top:6px; color:var(--dg-ok); font-weight:800}

/* numbered steps ("how it works") */
.dg-steps{list-style:none; counter-reset:s; margin:0; padding:0; display:grid; gap:12px}
.dg-steps li{counter-increment:s; position:relative; padding-left:40px; font-size:14.5px; line-height:1.55}
.dg-steps li::before{
  content:counter(s); position:absolute; left:0; top:0; width:28px; height:28px;
  border-radius:9px; background:var(--dg-sea); color:#fff; font-family:inherit; font-weight:800; font-size:14px; line-height:28px; text-align:center;
}
.dg-steps b{display:block; font-size:15px; margin-bottom:2px}

/* ---- course / set picker grid ------------------------------------------- */
.dg-sets{display:grid; grid-template-columns:repeat(auto-fill,minmax(230px,1fr)); gap:12px}
.dg-set{
  display:block; text-decoration:none; color:inherit;
  background:var(--dg-card); border:1px solid var(--dg-line); border-radius:var(--dg-r);
  padding:16px; box-shadow:var(--dg-shadow); transition:transform .12s,box-shadow .12s,border-color .12s;
}
.dg-set:hover{transform:translateY(-2px); box-shadow:var(--dg-shadow-lg); border-color:rgba(18,80,126,.34)}
.dg-set-top{display:flex; align-items:baseline; justify-content:space-between; gap:8px}
.dg-set-name{font-weight:800; font-size:17px}
.dg-set-count{font-size:12.5px; color:var(--dg-ink-2); white-space:nowrap}
.dg-set-note{margin:6px 0 12px; font-size:13.5px; color:var(--dg-ink-2); line-height:1.45}
.dg-set-foot{display:flex; align-items:center; gap:8px; font-size:13px; font-weight:700; flex-wrap:wrap}
.dg-set.is-mock{background:linear-gradient(160deg,#12507e 0%,#0b2239 100%); color:#fff; border-color:transparent}
.dg-set.is-mock .dg-set-count,.dg-set.is-mock .dg-set-note{color:rgba(255,255,255,.82)}
.dg-set.is-mock .dg-bar{background:rgba(255,255,255,.2)}
/* Twelve of the 27 course cards sit here. `opacity` fades the words as well as
   the surface, and a faded <a href="#"> is still a real link — the WCAG "disabled
   control" exemption does not apply to it — so at .62 the note text composited to
   #8997a5 = 2.99:1 and failed. Lifting to .8 and letting the two muted spans use
   full --dg-ink lands them back on #3c4e61 (8.56:1), which is visually the same
   muted grey they were always meant to be. The card still reads as unavailable:
   the "Planned" / "Held back" pill says so in words.
   pointer-events:none stops the mouse and never stopped the keyboard, so these
   cards used to stay in the tab order and "activate" to href="#". index.php now
   renders a <div> rather than an <a> when the course is not live, so there is
   nothing to focus; this rule is the fade only. (.dg-set is display:block, so a
   <div> lays out identically.) */
.dg-set.is-soon{opacity:.8; pointer-events:none}
.dg-set.is-soon .dg-set-count,
.dg-set.is-soon .dg-set-note{color:var(--dg-ink)}

/* a thin score bar across the bottom of a set card */
.dg-bar{height:6px; border-radius:999px; background:var(--dg-soft); overflow:hidden; margin-top:10px}
.dg-bar i{display:block; height:100%; width:0; background:var(--dg-sea); border-radius:999px; transition:width .3s}
.dg-bar.is-pass i{background:var(--dg-ok)}
.dg-bar.is-fail i{background:var(--dg-bad)}

/* ---- pills / badges ------------------------------------------------------ */
.dg-pill{
  display:inline-flex; align-items:center; gap:5px; border-radius:999px;
  padding:4px 10px; font-family:inherit; font-weight:700; font-size:12px; line-height:1.4; background:var(--dg-soft); color:var(--dg-sea);
}
.dg-pill.is-ok{background:var(--dg-ok-bg); color:var(--dg-ok)}
.dg-pill.is-bad{background:var(--dg-bad-bg); color:var(--dg-bad)}
.dg-pill.is-warn{background:var(--dg-warn-bg); color:var(--dg-warn)}
.dg-set.is-mock .dg-pill{background:rgba(255,255,255,.18); color:#fff}

/* ---- practice room: sticky top bar -------------------------------------- */
.dg-bar-top{
  position:sticky; top:0; z-index:40; margin:12px 0 14px;
  background:rgba(255,255,255,.95); backdrop-filter:blur(10px);
  border:1px solid var(--dg-line); border-radius:var(--dg-r);
  box-shadow:var(--dg-shadow); padding:10px 12px;
  display:flex; align-items:center; gap:10px; flex-wrap:wrap;
}
/* This is the practice room's <h1>; margin:0 keeps the sticky bar's layout
   identical to when it was a <span>. */
.dg-bar-title{font-weight:800; font-size:15px; margin:0}
.dg-bar-prog{flex:1 1 140px; min-width:90px; display:flex; align-items:center; gap:8px}
.dg-bar-count{font-family:inherit; font-weight:700; font-size:13px; line-height:1; color:var(--dg-sea); font-variant-numeric:tabular-nums; white-space:nowrap}
.dg-bar-spacer{flex:1 1 auto}

/* ---- practice room: navigator ------------------------------------------- */
.dg-nav-grid{display:flex; flex-wrap:wrap; gap:6px; margin-top:10px}
.dg-dot{
  position:relative; width:34px; height:34px; border-radius:9px;
  border:1px solid var(--dg-line-ui); background:#fff; color:var(--dg-ink);
  font-family:inherit; font-weight:700; font-size:13px; line-height:1; cursor:pointer;
  display:inline-flex; align-items:center; justify-content:center;
  font-variant-numeric:tabular-nums; transition:transform .1s;
}
.dg-dot:hover{transform:translateY(-1px)}
/* The state borders used to be the token at .4 alpha, which composites to
   1.9-2.3:1 against both the cell fill and the white around it. A cell's STATE is
   exactly what WCAG 1.4.11 asks 3:1 for, so they go solid: 5.8:1 (ok) and
   5.9:1 (bad) against white. */
.dg-dot.is-done{background:var(--dg-soft); border-color:var(--dg-sea); color:var(--dg-sea)}
.dg-dot.is-ok{background:var(--dg-ok-bg); border-color:var(--dg-ok); color:var(--dg-ok)}
.dg-dot.is-bad{background:var(--dg-bad-bg); border-color:var(--dg-bad); color:var(--dg-bad)}
.dg-dot.is-cur{outline:2px solid var(--dg-sea); outline-offset:1px}
/* Right / wrong in the grid was green-vs-red and nothing else, which is the one
   pair of hues a red-green colour blind candidate cannot separate — and this is a
   *marked exam paper*. A tick and a cross in the corner of the cell say it
   without colour. The two-value `content` form gives the glyph its own alt text,
   so AT reads "correct" rather than "check mark"; the cell's aria-label still
   needs the same words, which is markup (A11Y.md §9 item 4). */
.dg-dot.is-ok::before,
.dg-dot.is-bad::before{
  position:absolute; left:3px; bottom:1px; font-size:9px; line-height:1;
  font-weight:800; pointer-events:none;
}
.dg-dot.is-ok::before{content:"\2713" / "correct"}
.dg-dot.is-bad::before{content:"\2715" / "wrong"}
.dg-dot.is-flag::after{
  content:""; position:absolute; top:3px; right:3px; width:7px; height:7px;
  border-radius:50%; background:var(--dg-warn);
}
.dg-legend{display:flex; gap:12px; flex-wrap:wrap; margin-top:12px; font-size:12.5px; color:var(--dg-ink-2)}
.dg-legend span{display:inline-flex; align-items:center; gap:5px}
.dg-legend i{width:12px; height:12px; border-radius:4px; border:1px solid var(--dg-line); display:inline-block}

/* ---- practice room: the question ---------------------------------------- */
.dg-q{background:var(--dg-card); border:1px solid var(--dg-line); border-radius:var(--dg-r); box-shadow:var(--dg-shadow); padding:20px 20px 18px}
.dg-q-head{display:flex; align-items:center; gap:10px; margin-bottom:12px; flex-wrap:wrap}
.dg-q-no{font-family:inherit; font-weight:800; font-size:13px; line-height:1; color:var(--dg-sea); background:var(--dg-soft); border-radius:999px; padding:6px 11px; white-space:nowrap}
.dg-q-text{margin:0 0 16px; font-size:18px; line-height:1.5; font-weight:700}

.dg-opts{display:grid; gap:9px}
.dg-opt{
  display:flex; align-items:flex-start; gap:11px; width:100%; text-align:left;
  border:1px solid var(--dg-line-ui); background:#fff; border-radius:13px;
  padding:13px 14px; font-family:inherit; font-weight:400; font-size:15.5px; line-height:1.5; color:var(--dg-ink);
  cursor:pointer; transition:background .13s,border-color .13s,transform .1s;
}
/* A marked option is aria-disabled, not `disabled`, so that it stays focusable
   and readable — see A11Y.md §9.3. It is therefore still a live <button> as far
   as :hover/:active are concerned, so the pointer affordances are excluded here
   rather than inherited. :not() keeps them off the locked ones without
   out-specifying .is-ok / .is-sel / .is-bad, which paint the marking. */
.dg-opt:not([aria-disabled="true"]):hover{background:var(--dg-soft); border-color:rgba(18,80,126,.62)}
.dg-opt:not([aria-disabled="true"]):active{transform:translateY(1px)}
.dg-opt-key{
  flex:none; width:27px; height:27px; border-radius:8px; background:var(--dg-ice);
  color:var(--dg-sea); font-family:inherit; font-weight:800; font-size:13px; line-height:27px; text-align:center;
}
.dg-opt.is-sel{border-color:var(--dg-sea); background:var(--dg-soft)}
.dg-opt.is-sel .dg-opt-key{background:var(--dg-sea); color:#fff}
/* .55 alpha composited to about 2.1-2.2:1 against both the tint inside and the
   white outside. The border here IS the state of the control, so 1.4.11's 3:1
   applies; the solid token gives 5.1-5.9:1. */
.dg-opt.is-ok{border-color:var(--dg-ok); background:var(--dg-ok-bg)}
.dg-opt.is-ok .dg-opt-key{background:var(--dg-ok); color:#fff}
.dg-opt.is-bad{border-color:var(--dg-bad); background:var(--dg-bad-bg)}
.dg-opt.is-bad .dg-opt-key{background:var(--dg-bad); color:#fff}
/* Marking an exam paper in green-vs-red and nothing else is the textbook
   colour-only cue. A tick / cross at the end of the row says it without hue, and
   the two-value `content` form gives the glyph real alternative text instead of
   letting a screen reader read out "check mark". `margin-left:auto` on the
   pseudo-element pushes it to the right edge of the flex row; `flex:none` keeps
   it off the text's wrapping. (The option's aria-label needs the same words —
   that is markup, A11Y.md §9 item 4.) */
.dg-opt.is-ok::after,
.dg-opt.is-bad::after{
  flex:none; margin-left:auto; align-self:center; padding-left:8px;
  font-size:17px; line-height:1; font-weight:800;
}
.dg-opt.is-ok::after{content:"\2713" / "Correct answer"; color:var(--dg-ok)}
.dg-opt.is-bad::after{content:"\2715" / "Your answer, wrong"; color:var(--dg-bad)}
.dg-opts.is-locked .dg-opt{cursor:default}

/* the explanation revealed after answering */
.dg-exp{
  margin-top:14px; border-left:4px solid var(--dg-sea); background:var(--dg-ice);
  border-radius:0 12px 12px 0; padding:12px 14px; font-size:14.5px; line-height:1.55;
}
.dg-exp b{display:block; margin-bottom:3px; color:var(--dg-sea); font-size:12.5px; text-transform:uppercase; letter-spacing:.4px}

.dg-q-foot{display:flex; align-items:center; gap:10px; margin-top:16px; flex-wrap:wrap}

/* ---- result sheet -------------------------------------------------------- */
.dg-score{display:flex; align-items:center; justify-content:center; gap:22px; flex-wrap:wrap; padding:8px 0 4px}
.dg-ring{
  --pct:0; position:relative; width:132px; height:132px; border-radius:50%; flex:none;
  background:conic-gradient(var(--dg-sea) calc(var(--pct)*1%), var(--dg-soft) 0);
  display:grid; place-items:center;
}
.dg-ring::after{content:""; position:absolute; inset:11px; border-radius:50%; background:var(--dg-card)}
.dg-ring.is-pass{background:conic-gradient(var(--dg-ok) calc(var(--pct)*1%), var(--dg-soft) 0)}
.dg-ring.is-fail{background:conic-gradient(var(--dg-bad) calc(var(--pct)*1%), var(--dg-soft) 0)}
.dg-ring i{position:relative; z-index:1; font-family:inherit; font-weight:800; font-size:30px; line-height:1; font-style:normal; font-variant-numeric:tabular-nums}
.dg-score-meta{min-width:0}
.dg-score-meta h3{margin:0 0 6px; font-size:22px; font-weight:800}

/* ---- answer key (answers.php) ------------------------------------------- */
.dg-key-q{border-bottom:1px solid var(--dg-line); padding:14px 0}
.dg-key-q:last-child{border-bottom:0}
.dg-key-q > p{margin:0 0 8px; font-weight:700; font-size:15.5px; line-height:1.5}
.dg-key-a{font-size:14.5px; line-height:1.55; color:var(--dg-ok); font-weight:700}
.dg-key-e{font-size:14px; line-height:1.55; color:var(--dg-ink-2); margin-top:4px}
.dg-key-o{list-style:none; margin:0 0 8px; padding:0; display:grid; gap:4px}
.dg-key-o li{font-size:14.5px; line-height:1.5; padding-left:26px; position:relative}
.dg-key-o li b{position:absolute; left:0; color:var(--dg-ink-2); font-weight:800}
.dg-key-o li.is-ok{color:var(--dg-ok); font-weight:700}
.dg-key-o li.is-ok b{color:var(--dg-ok)}
/* Green + bold was the whole signal for "this is the right one" in a list where
   every other line is also text. Bold alone is a weak cue and colour alone is no
   cue at all to a red-green colour blind reader, so the correct line gets a tick.
   Alt text is empty on purpose: the .dg-key-a line underneath already says
   "Answer: B - ..." in words, so announcing it twice is noise. */
.dg-key-o li.is-ok::after{content:" \2713" / ""; font-weight:800}

/* ---- misc ---------------------------------------------------------------- */
.dg-note{
  border:1px dashed var(--dg-line); border-radius:12px; padding:12px 14px;
  font-size:13.5px; line-height:1.55; color:var(--dg-ink-2); background:var(--dg-ice);
}
.dg-row{display:flex; gap:10px; flex-wrap:wrap; align-items:center}
.dg-grid-2{display:grid; grid-template-columns:repeat(auto-fit,minmax(280px,1fr)); gap:14px}
.dg-search{
  width:100%; border:1px solid var(--dg-line-ui); border-radius:12px; padding:11px 13px;
  font-family:inherit; font-weight:400; font-size:15px; line-height:1.3; color:var(--dg-ink); background:#fff; min-height:44px;
}
.dg-search:focus{outline:2px solid var(--dg-sea); outline-offset:1px; border-color:var(--dg-sea)}

/* ---- long tokens ---------------------------------------------------------
   These 5,368 questions come from a source with inconsistent punctuation, and a
   missing space after a comma turns a phrase into one unbreakable word:
   "Winches,Cranes,Derricks,Hatchcovers,Gangways" is 43 characters a browser
   cannot wrap, so it painted straight out of its card and pushed the whole
   answer key 58px sideways on a 360px phone. The build now inserts the missing
   spaces, but a bank of this size will produce another one, so the text
   containers say plainly that a word may break if it has to.

   `break-word`, not `break-all`: ordinary prose must still break only between
   words. Worth knowing for the next person who debugs this — the element's BOX
   is not oversized, so getBoundingClientRect() finds nothing wrong. It shows up
   only as `el.scrollWidth > el.clientWidth`. */
.dg-q-text, .dg-opt, .dg-exp, .dg-key-q, .dg-key-o li, .dg-key-a, .dg-key-e,
.dg-set-note, .dg-facts td, .dg-ticks li{ overflow-wrap:break-word }

/* ---- keyboard focus ------------------------------------------------------
   Every control here is a <button> or an <a>, and the practice room is fully
   keyboard-driven (1-4/A-D to answer, arrows to move), so the focused element
   has to be obvious. :focus-visible rather than :focus so a mouse click does
   not leave a ring behind, and the ring is drawn with outline + offset so it
   never reflows the layout the way a border change would. */
/* No `border-radius` here. The old rule forced 12px on everything it matched,
   which silently re-cut the corners of .dg-btn-sm (10px), .dg-btn-lg (14px),
   .dg-dot (9px, 11px on touch) and .dg-set (16px) for as long as they held focus
   — tabbing across the 30-cell grid visibly reshaped each cell in turn. An
   `outline` already follows the element's own radius. */
.dg-btn:focus-visible,
.dg-opt:focus-visible,
.dg-dot:focus-visible,
.dg-set:focus-visible,
.dg-page a:focus-visible,
.dg-search:focus-visible{
  outline:3px solid var(--dg-sea); outline-offset:2px;
}
/* On the hero the sea blue disappears into the gradient, so invert it there. */
.dg-hero .dg-btn:focus-visible{ outline-color:#fff }
/* ...except on the one hero button that is itself white, where a white ring
   dissolved into the button it was marking. A dark ring hugging the white button
   is 16:1 against it. */
.dg-hero .dg-btn-main:focus-visible{ outline-color:var(--dg-ink); outline-offset:0 }

/* ---- touch targets -------------------------------------------------------
   .dg-btn-sm (36px) and .dg-dot (34px) are comfortable with a mouse, and
   keeping the navigator's 30 dots compact means they stay on one or two rows on
   a desktop. A finger is not a mouse: both are under the 44px minimum, and the
   navigator is exactly the control a candidate jabs at repeatedly on a phone.
   Keyed on `pointer:coarse` rather than a width, because that is the actual
   question being asked — a small window on a laptop still has a mouse, and a
   large tablet still has fingers. The dots simply wrap onto more rows. */
@media (pointer:coarse){
  .dg-btn-sm{min-height:44px; padding:10px 14px}
  .dg-dot{width:44px; height:44px; border-radius:11px; font-size:14px}
  .dg-dot.is-flag::after{top:5px; right:5px}
}

/* ---- reduced motion ------------------------------------------------------
   The only motion here is decorative — cards lifting on hover, the score bar
   growing, buttons nudging down on press. Someone who has asked their system
   for less of it loses nothing by having all of it removed. */
@media (prefers-reduced-motion: reduce){
  .dg-set,.dg-btn,.dg-opt,.dg-dot,.dg-bar i{ transition:none !important }
  .dg-set:hover,.dg-dot:hover{ transform:none }
  .dg-btn:active,.dg-opt:active{ transform:none }
  /* The practice room calls scrollIntoView on every question change, and
     cryo-unified.css sets html{scroll-behavior:smooth} suite-wide, so 30 smooth
     scrolls is the largest single piece of motion in the app. cryo-ergo.css
     already clamps this under the same query; saying it here too means the app
     is correct on its own rather than by inheritance. */
  html{ scroll-behavior:auto !important }
}

/* ---- scrolling under the sticky bar --------------------------------------
   .dg-bar-top is position:sticky at top:0, and the practice room scrolls the
   candidate around with scrollIntoView on every question change and every tap in
   the 30-cell grid. block:"nearest"/"start" park the target flush at y=0 — which
   is underneath the bar. Measured on a 360x740 phone, where the bar wraps to
   three rows and is 100px tall: after a grid jump the card top sat at y=0, the
   bar's bottom edge at y=100, and the question's first line at y=54. The
   question-number chip and the top of the question were both covered.
   scroll-margin-top is the fix a sticky header is supposed to have; it costs
   nothing anywhere else because it only applies when something scrolls TO the
   element. The two values track the bar's two heights. */
.dg-q, .dg-card, .dg-key-q{ scroll-margin-top:70px }
@media (max-width:560px){
  .dg-q, .dg-card, .dg-key-q{ scroll-margin-top:112px }
}

@media (max-width:560px){
  .dg-q{padding:16px 14px 14px}
  .dg-q-text{font-size:16.5px}
  .dg-opt{font-size:15px; padding:12px}
  .dg-hero{padding:22px 18px; border-radius:16px}
  .dg-facts th{width:auto}
}
@media print{ .dg-bar-top,.dg-btn,.dg-nav-grid,.dg-search{display:none !important} }
