/* Chrome around the board: the pieces every JS module already creates but
   that tokens/layout/board.css never styled -- the live region, the modal
   host, the settings form, the hint strip, and the retry panels. Kept in its
   own file because tokens.css is parsed by the contrast gate and
   board.css/layout.css are asserted against by source-level regex tests;
   adding here keeps those checks unambiguous. */

/* The announcer sets this class on its aria-live region. Without a definition
   the region renders as ordinary visible text, so every announcement ("후보
   입력 모드 켜짐") would appear on screen. Clip rather than display:none --
   a hidden element is dropped from the accessibility tree and would never be
   announced at all. */
.visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

/* §10's 48px control floor (L3), applied where the buttons actually are.
   The modules that build them are not all in this change's scope, so the
   floor is expressed as a rule over the app's button hosts rather than as a
   class each module has to remember to add. */
.app-shell-header button,
.app-shell-header .lang-switch,
.app-shell-header .game-switch,
.digit-bar button,
.retry-panel button,
[role="dialog"] button,
.control {
    min-inline-size: var(--control-floor);
    min-block-size: var(--control-floor);
    padding: 0 12px;
    font: inherit;
    color: var(--fg-body);
    background: var(--bg-cell);
    border: 1px solid var(--line);
    border-radius: 6px;
    cursor: pointer;
}

.app-shell-header button:focus-visible,
.app-shell-header .lang-switch:focus-visible,
.app-shell-header .game-switch:focus-visible,
.digit-bar button:focus-visible,
.retry-panel button:focus-visible,
[role="dialog"] button:focus-visible {
    outline: 2px solid var(--focus);
    outline-offset: 2px;
}

/* Anchors, not buttons: switching language or game is a real navigation to a
   real URL, which is what lets a crawler follow it and a user bookmark it. The
   rules above give them the control's box; these give them the control's
   alignment, which an inline anchor does not get for free. */
.app-shell-header .lang-switch,
.app-shell-header .game-switch {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    text-decoration: none;
}

/* ------------------------------------------------------------- app shell */
.app-shell-header-host {
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 8px;
}

.app-shell-header {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

.board-area {
    display: flex;
    justify-content: center;
    padding: 8px;
}

.controls-area {
    /* Query source for the digit bar's own width -- see the @container rule
       in the digit bar section below. */
    container-type: inline-size;
    padding: 0 8px;
}

/* The wide-layout row gap (layout.css) already separates board and
   controls-area; when the digit bar itself is collapsed (desktop, no
   coarse pointer) its wrapper's own padding would otherwise add a stray
   trailing sliver of empty space past the board. */
.controls-area:has(.digit-bar[data-visibility="collapsed"]) {
    padding: 0;
}

/* Completion is signalled by a text badge, not by color alone (V4-05). */
.app-shell-header-host[data-state="solved"]::after {
    content: var(--i18n-solved);
    align-self: flex-start;
    padding: 4px 10px;
    border-radius: 999px;
    color: var(--fg-given);
    background: var(--bg-cell-selected);
}

.hint-strip {
    padding: 8px;
    color: var(--fg-candidate);
    background: var(--bg-cell-peer);
    border-radius: 6px;
}

.hint-strip::before {
    content: var(--i18n-hint);
}

/* ------------------------------------------------------------- digit bar */
/* layout.css sizes .digit-bar as a single 60px row. The pencil and erase
   controls put the bar over one row, so the fixed height has to give way to
   auto rows or it would clip everything past the first. */
.digit-bar {
    block-size: auto;
    grid-auto-rows: minmax(var(--control-floor), auto);
    row-gap: 6px;
}

/* Half the bar each, so the control row ends flush with the digit row above
   it. A single-digit column is far too narrow for a word: at that width
   "후보" breaks mid-word and "지우기" runs to three lines. */
.digit-bar button[data-role="pencil"],
.digit-bar button[data-role="erase"] {
    grid-column: span 9;
}

/* Nine targets at the 48px floor need 432px of row. When the bar is narrower
   than that the row used to outgrow the page and scroll it sideways, so it
   regroups as a 3x3 keypad (digits still span 2, of 6 columns) with the two
   controls sharing the row below. Shrinking the targets instead is not an
   option: L3's 48px is a floor, and a phone is where it matters most.
   The query is on the bar's own width rather than the viewport's because
   --board-width -- which the bar inherits -- is derived from dvh as well as
   vw, so a short landscape window can squeeze it at any viewport width. */
@container (max-width: 431px) {
    .digit-bar {
        grid-template-columns: repeat(6, 1fr);
    }

    .digit-bar button[data-role="pencil"],
    .digit-bar button[data-role="erase"] {
        grid-column: span 3;
    }
}

.digit-bar[data-visibility="collapsed"] {
    display: none;
}

.digit-bar button[data-active="1"] {
    background: var(--bg-cell-digit);
    border-color: var(--focus);
    border-width: 2px;
}

/* ------------------------------------------------------------ dialog host */
.dialog-host:empty {
    display: none;
}

[role="dialog"] {
    position: fixed;
    inset-block-start: 50%;
    inset-inline-start: 50%;
    transform: translate(-50%, -50%);
    z-index: 10;
    display: flex;
    flex-direction: column;
    gap: 12px;
    inline-size: min(90vw, 420px);
    max-block-size: 80dvh;
    overflow-y: auto;
    padding: 16px;
    color: var(--fg-body);
    background: var(--bg-cell);
    border: 2px solid var(--line);
    border-radius: 10px;
}

[role="dialog"] table {
    border-collapse: collapse;
    inline-size: 100%;
}

[role="dialog"] td {
    padding: 4px 8px;
    border-bottom: 1px solid var(--bg-cell-peer);
}

/* ------------------------------------------------------- settings and share */
.settings-form {
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.settings-form label {
    display: flex;
    gap: 8px;
    align-items: center;
}

.settings-form fieldset {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin: 0;
    padding: 8px;
    border: 1px solid var(--line);
    border-radius: 6px;
}

.share-fallback input {
    inline-size: 100%;
    padding: 8px;
    font: inherit;
    color: var(--fg-body);
    background: var(--bg-page);
    border: 1px solid var(--line);
}

/* ------------------------------------------------------------ retry panel */
.retry-panel {
    display: flex;
    flex-direction: column;
    gap: 12px;
    align-items: flex-start;
    margin: 16px;
    padding: 16px;
    background: var(--bg-cell-conflict);
    border: 1px solid var(--fg-conflict);
    border-radius: 8px;
}

.retry-panel button[data-highlight="1"] {
    border-color: var(--focus);
    border-width: 2px;
}

.retry-detail {
    margin: 0;
    color: var(--fg-candidate);
    font-size: 0.875rem;
}

/* The inert skeleton main.js paints before app.js loads. It has no content of
   its own, so it only reserves height to stop the first paint from jumping. */
[data-state="skeleton"] {
    min-block-size: 50dvh;
}

/* The site footer: the only path from a game to the practice page, and the
   only navigation that names all three. Kept quiet on purpose -- the board is
   what the page is for, and a prominent nav bar under it would compete with
   the game for attention that belongs to the puzzle.

   The whole strip is centred and text-sized rather than laid out as buttons:
   these are links a reader follows once, not controls used during play, so the
   48px control floor that governs the digit bar does not apply. They are still
   given generous padding, because a link that is hard to hit is a link that
   does not work on a phone. */
.site-footer {
    display: flex;
    justify-content: center;
    padding: 12px 16px 20px;
    font-size: 0.875rem;
}

.site-footer nav {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 4px 20px;
}

.site-footer a,
.site-footer [aria-current="page"] {
    padding: 8px 4px;
    color: var(--fg-candidate);
    text-decoration: none;
}

.site-footer a:hover,
.site-footer a:focus-visible {
    color: var(--fg-body);
    text-decoration: underline;
}

/* The current page is not a link, so it must not look like one. Weight and
   color carry it rather than an underline, which would read as a link that
   simply refuses to work. */
.site-footer [aria-current="page"] {
    color: var(--fg-body);
    font-weight: 600;
}

/* ------------------------------------------------------- completion card */

/* Four labelled rows inside the dialog host, which already supplies the panel,
   the focus trap and the buttons. Laid out as label-left / value-right rows
   rather than a table: there is no second column of data to align across rows,
   and a table would have a screen reader announce grid coordinates for what is
   really a short list of facts. */
.completion-card {
    display: flex;
    flex-direction: column;
    gap: 6px;
    min-inline-size: 15rem;
}

.completion-heading {
    margin: 0 0 6px;
    font-size: 1.0625rem;
    font-weight: 600;
}

.completion-row {
    display: flex;
    justify-content: space-between;
    gap: 16px;
    padding: 4px 0;
    border-block-end: 1px solid var(--bg-cell-given);
}

.completion-label {
    color: var(--fg-candidate);
}

.completion-value {
    font-variant-numeric: tabular-nums;
    font-weight: 600;
}

/* The row that just changed. Weight and colour together, never colour alone --
   and the heading above already says "a new best time" in words, so this is
   the second reading of something already stated rather than the only one. */
.completion-row-best .completion-value {
    color: var(--fg-user);
}

.completion-note {
    margin: 6px 0 0;
    color: var(--fg-candidate);
    font-size: 0.8125rem;
}
