File size: 6,447 Bytes
e16348e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
/* ── Responsive layout ─────────────────────────────────────────────────
   At 1180px and below the columns wrap: the board column takes a
   full-width row and the results and PGN columns wrap beneath it. Sizes
   are authored in rem. */
@media (max-width: 1180px) {
    html, body { height: auto; overflow-y: auto; }
    :root { --pgn-col-w: 18.75rem; }
    .content {
        grid-template-columns: minmax(0, 1fr) var(--pgn-col-w);
        height: auto;
        overflow: visible;
        padding: var(--space-4);
    }
    .left-col {
        grid-column: 1 / -1;
        height: auto;
    }
    /* Horizontal auto margins centre a fixed-width flex item on the
       cross axis of a column-direction container. */
    .board-group { margin: 0 auto; }

    .right-col, .pgn-col {
        height: min(60vh, 520px);
    }
}

/* ── Phone: swipeable screens ───────────────────────────────────────────
   Below 768px the layout is three horizontally swipeable screens in
   column order: board, results, PGN. Each screen fills the space between
   the header and the bottom screen navigation; a horizontal swipe moves
   to the next one, while a vertical swipe scrolls that screen's own
   content. The board is sized to the visible height so the whole board
   screen fits; below its 14rem floor the screen scrolls from the top. */
@media (max-width: 767px) {
    :root {
        --screen-nav-h: calc(3rem + env(safe-area-inset-bottom, 0px));
        --viewport-h: 100vh;

        /* Fixed heights above and around the board: three control rows,
           column padding 1rem, gaps 1.875rem, error line 0.875rem plus
           0.5rem slack, tray padding 1.25rem and tray borders 4px. The
           remainder holds the board and its two trays: 1.25 x board.
           Update when the height above the board changes. */
        --board-fit-h: calc((var(--viewport-h) - var(--header-h) - var(--screen-nav-h) - 5.5rem - 3 * var(--control-h) - 4px) / 1.25);
        --board-size: max(14rem, min(var(--board-size-cap), var(--board-fit-h)));
    }
    @supports (height: 100dvh) {
        :root { --viewport-h: 100dvh; }
    }
    html, body { overflow-x: hidden; }
    .content {
        grid-template-columns: repeat(3, 100vw);
        overflow-x: auto;
        overflow-y: hidden;
        overscroll-behavior-x: contain;
        scroll-snap-type: x mandatory;
        min-height: 0;
        height: calc(100vh - var(--header-h) - var(--screen-nav-h));
        height: calc(100dvh - var(--header-h) - var(--screen-nav-h));
        width: 100vw;
        max-width: none;
        padding: 0;
        gap: 0;
    }
    .left-col, .right-col, .pgn-col {
        grid-column: auto;
        max-width: 100vw;
        min-height: 0;
        height: calc(100vh - var(--header-h) - var(--screen-nav-h));
        height: calc(100dvh - var(--header-h) - var(--screen-nav-h));
        scroll-snap-align: start;
        /* Containing block for absolutely positioned descendants (e.g. .sr-only). */
        position: relative;
    }
    .left-col {
        overflow-y: auto;
        padding: var(--space-2) var(--space-4);
    }
    .board-group { margin: 0 auto; }
    .right-col, .pgn-col { padding: var(--space-4); overflow: hidden; }

    /* Logo and nav span two rows; the subtitle sits below the title. */
    .site-header {
        display: grid;
        grid-template-columns: auto minmax(0, 1fr) auto;
        grid-template-rows: auto auto;
        align-content: center;
        column-gap: 0.625rem;
        row-gap: 0;
    }
    .site-header__logo, .site-header__nav { grid-row: 1 / span 2; }
    .site-header__brand { display: contents; }
    .site-header__sep { display: none; }
    .site-header__title, .site-header__sub {
        grid-column: 2;
        min-width: 0;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
        line-height: 1.2;
    }
    .site-header__title { grid-row: 1; align-self: end; }
    .site-header__sub   { grid-row: 2; align-self: start; font-size: 0.6875rem; }

    .screen-nav { display: grid; }
    .toast-container { bottom: calc(var(--screen-nav-h) + var(--space-3)); }

    /* The moves list owns vertical panning so a drag on it is not claimed
       by .content's horizontal scroll-snap. */
    .moves-body-scroll {
        touch-action: pan-y;
        -webkit-overflow-scrolling: touch;
        overscroll-behavior-y: contain;
    }
    /* The table spans the full screen width, so it is not widened for the scrollbar. */
    .moves-body-scroll.has-vscroll .moves-table--body { width: 100%; }

    .move-line { --pgn-rank-width: var(--pgn-rank-w-compact); }
}

@media (max-width: 480px) {
    :root { --board-size-cap: min(360px, 88vw); }
    .left-col, .right-col, .pgn-col {
        padding-left:  max(var(--space-4), env(safe-area-inset-left));
        padding-right: max(var(--space-4), env(safe-area-inset-right));
    }
    .site-header {
        padding-left:  max(var(--space-5), env(safe-area-inset-left));
        padding-right: max(var(--space-5), env(safe-area-inset-right));
    }

    /* Title, count and CSV button do not fit one row at this width. */
    .panel-header { flex-wrap: wrap; row-gap: 6px; }

    /* .btn--grow deliberately doesn't shrink (readable label + icon at
       any width) - six buttons can't all fit one row this narrow, so
       the toolbar wraps instead of overflowing. */
    .fen-actions { flex-wrap: wrap; row-gap: 6px; }
}

/* ── Touch input sizing ─────────────────────────────────────────────────
   (hover: none) and (pointer: coarse) targets touchscreens regardless of
   viewport width. Control heights come from --control-h in tokens.css.
   Inputs use a >=16px font size because iOS Safari zooms the page when a
   focused input's font size is under 16px. */
@media (hover: none) and (pointer: coarse) {
    .fen-input            { font-size: var(--text-lg); }
    .pgn-dialog__textarea { font-size: var(--text-lg); }

    /* #board handles its own drag gestures; letting the browser also
       interpret them as page-scroll/pinch-zoom fights the drag. */
    .spare-piece, .promotion-piece-btn { touch-action: none; }
}