/* Shared by the letter-drag exercises' <button class="gap"> and the keyboard exercise's
   <input class="gap"> inside a <span class="gap-slot">. Each rule here cost a debugging
   round in exercise 3; duplicating them into a second template would duplicate the traps.
   Tray, tile, layout and picked-up-letter rules stay in the template that owns them. */

/* An empty gap collapses to a few pixels tall, which reads as a dash rather than a slot and
   is far below the 24x24 CSS px pointer target WCAG 2.5.8 asks for. Hence the explicit box:
   one letter wide, one line tall, so the filled word reads as one word rather than a stem
   with letters off to the side. */
.gap { font: inherit; display: inline-block; box-sizing: border-box; min-width: 1.2em; height: 1.5em; line-height: 1.4; margin: 0 0.06em; padding: 0; border: none; border-bottom: 3px solid #595959; background: transparent; vertical-align: baseline; text-align: center; position: relative; }

/* An <input type="text"> is sized by its `size` attribute — 20 characters by default — and
   width alone cannot shrink it below the shared min-width above, so both are set. Narrower
   than the drag exercises' gaps on purpose: nothing is dropped into these, so the box only
   has to be an aimable caret target, and a narrow one keeps the word reading as a word.
   Still a target in a sentence, so WCAG 2.5.8's inline exception is what covers it rather
   than the 24x24 floor the tray tiles are held to. */
input.gap { min-width: 0; width: 0.72em; }

/* Better still where the browser has it: the gap is a small slot while empty and hugs the
   letter once one is typed, so the word reads as a word the whole way through rather than
   only after Submit. The fixed width above is the fallback, and it is a compromise — wide
   enough that 'ṃ' is not clipped, so wider than an empty slot needs to be. */
@supports (field-sizing: content) {
  /* min-width is the empty slot's whole width, so it is the narrowest letter's width rather
     than anything roomier: an empty gap wider than the letter that lands in it would shrink
     at Submit, which is the jump this rule exists to avoid. */
  input.gap { field-sizing: content; width: auto; min-width: 0.45em; }
}

/* The wrapper exists only to host the verdict glyph: ::after does not render on an <input>,
   which is a replaced element. It has to establish the positioning context the glyph is
   absolutely placed against, and sit on the text baseline like the input it wraps. */
.gap-slot { display: inline-block; position: relative; }

/* Scoped to the button host: an *empty inline-block button* aligns by its bottom margin edge
   rather than a text baseline, which is what made the gap jump as a letter landed. An
   <input> has a text baseline already and needs none of this. The zero-width space is in
   ::before, so textContent still reports only the letter the learner placed. */
button.gap::before { content: "\200b"; }

/* A letter-wide gap is a miserable target to drop into, but a word spelled across generous
   gaps reads as "nes a m". So the gaps are wide while there is still something to aim at,
   and tighten into the word at Submit, when there is not.
   Both hosts: the keyboard exercise's gaps are letter-sized while the learner types, but each
   one still carries its own side margins, and those add up — measured on 2026-08-12, the
   four-gap 'pañäkte' graded 16 CSS px wider than the same word set as plain text, against 6
   px for the two-gap 'nesäṃ'. Below about three gaps the slack is invisible, which is why
   this only showed up once a lesson's words stopped all being nesäṃ. */
#target[data-graded="true"] .gap { min-width: 0; margin: 0; }

/* Verdict marks are a glyph plus a border-style change, never colour alone (WCAG 1.4.1).
   #1a7f37 and #a4262c each clear 3:1 against white as non-text contrast for the border
   (WCAG 1.4.11), and the glyph carries the meaning on its own for anyone who sees neither
   colour. The glyph is a pseudo-element, so the selector names both hosts: the button
   carries its own mark, and the keyboard exercise's wrapper carries the mark for the input
   inside it, whose border the descendant selector colours. Defined once, rendered on
   whichever element can render it. */
.gap[data-verdict], .gap-slot[data-verdict] { position: relative; }
/* The mark hangs below the gap rather than sitting in the text: an inline glyph would print
   between the letters and the corrected word has to read as a word. */
.gap[data-verdict]::after, .gap-slot[data-verdict]::after { position: absolute; top: 100%; left: 50%; transform: translateX(-50%); font-size: 0.55em; line-height: 1; }
.gap[data-verdict="correct"], .gap-slot[data-verdict="correct"] .gap { border-bottom: 3px solid #1a7f37; }
.gap[data-verdict="correct"]::after, .gap-slot[data-verdict="correct"]::after { content: "✓"; color: #1a7f37; }
.gap[data-verdict="incorrect"], .gap-slot[data-verdict="incorrect"] .gap { border-bottom: 4px double #a4262c; }
.gap[data-verdict="incorrect"]::after, .gap-slot[data-verdict="incorrect"]::after { content: "✗"; color: #a4262c; }

/* aria-pressed is already toggled correctly by keyboard.js's setSelected() and
   drag_fill.js's blank-click handler; the selected-state rule below was simply missing,
   unlike the working click-identify exercise type's .sign-glyph[aria-pressed="true"] rule
   (sign_exercises/signs.css:37), which this matches.

   The focus rule uses box-shadow, not outline, and that's deliberate, not a style
   preference: outline is a single-value property, so an outline-based focus rule at equal
   specificity to the selected-state rule above would replace it instead of adding to it,
   collapsing a selected+focused blank down to just the focus indicator -- exactly the
   collapse this rule exists to prevent (WCAG 2.4.7 needs focus and selection to both stay
   visible together, not one replacing the other). box-shadow never competes with any of
   these outline declarations, so it stacks cleanly on every page
   that shares this file, not just keyboard.html. #005a9c on the page background #f4f2ee is
   ~6.4:1, passing WCAG 1.4.11 non-text contrast; the box-shadow ring uses the same color, so
   the same ratio holds for it. #fdfbf6 is the same background color used elsewhere in this
   codebase for a light gap/inset (sign_exercises/signs.css:55, the group-complete modal) --
   reused here as the box-shadow's inner ring so the outer blue ring reads as a second,
   separate indicator rather than touching the selected-state outline directly. outline-offset
   pushes the selected-state outline 2px past the border edge -- with the default 0 offset it
   sat in the same 0-3px band as the focus box-shadow's own cream ring, so a selected+focused
   blank painted as one merged ring instead of the two visually distinct ones described above. */
.gap[aria-pressed="true"] { outline: 3px solid #005a9c; outline-offset: 2px; }
.gap:focus-visible { box-shadow: 0 0 0 3px #fdfbf6, 0 0 0 6px #005a9c; }
