*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }

:root {
    --bg: #0d1a14;
    --felt: #17402f;
    --felt-2: #10312333;
    --panel: #1a2b23;
    --line: #2f4d3e;
    --text: #eef6f1;
    --muted: #9ab8a9;
    --accent: #f0c14b;
    --tile: #f6f2e7;
    --tile-edge: #cdc5b0;
    --wan: #b8352c;
    --tong: #2f6fb8;
    --tiao: #2f8a4d;
    --honour: #2b2b2b;
}

html, body { height: 100%; overscroll-behavior: none; }

body {
    position: fixed; inset: 0; overflow: hidden;
    color: var(--text);
    font-family: 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'Segoe UI', sans-serif;
    background:
        radial-gradient(circle at 50% 40%, #1d5540, #0c2018 70%),
        linear-gradient(180deg, #08150f, #0d1a14);
    user-select: none; -webkit-user-select: none;
    -webkit-tap-highlight-color: transparent;
    touch-action: manipulation;
}

.shell {
    display: flex; flex-direction: column;
    height: 100%; min-height: 100dvh;
    max-width: 1180px; margin: 0 auto;
    padding:
        max(6px, env(safe-area-inset-top))
        max(6px, env(safe-area-inset-right))
        max(8px, env(safe-area-inset-bottom))
        max(6px, env(safe-area-inset-left));
}

.toolbar { display: flex; align-items: center; gap: 6px; flex: 0 0 auto; height: 38px; }
.toolbar-spacer { flex: 1; }

.icon-btn {
    display: inline-flex; align-items: center; justify-content: center;
    min-width: 34px; height: 31px; padding: 0 10px;
    border: 1px solid var(--line); border-radius: 9px;
    background: var(--panel); color: var(--text);
    font-family: inherit; font-size: 0.88rem; line-height: 1;
    text-decoration: none; cursor: pointer;
}
.icon-btn-text { font-size: 0.76rem; font-weight: 600; }
.icon-btn:active { transform: scale(0.94); border-color: var(--accent); }

.hud { display: flex; gap: 5px; flex: 0 0 auto; margin: 5px 0; }
.hud span {
    flex: 1; display: flex; flex-direction: column; align-items: center;
    padding: 4px 2px; border-radius: 9px; background: rgba(255, 255, 255, 0.06);
}
.hud b { font-size: 0.86rem; font-variant-numeric: tabular-nums; }
.hud b.is-you { color: var(--accent); }
.hud i { font-style: normal; font-size: 0.56rem; letter-spacing: 0.08em; color: var(--muted); }

/* The table, seen from above. You are along the bottom, the player who follows
   you is on the right, the one opposite is at the top, and the one you may take
   a run from is on the left -- which is where they sit at a real table, and
   which is what makes "only from your left" mean anything.

   Tile sizes are variables because the same markup has to work on a phone held
   upright and on a desk, and because the pictures are painted at whatever size
   is asked for. */
.table {
    flex: 1 1 auto; min-height: 0;
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    grid-template-rows: auto minmax(0, 1fr) auto;
    grid-template-areas:
        ".    top    ."
        "left pool   right"
        ".    mine   .";
    gap: 6px;
    --tile-w: 30px; --tile-h: 41px;
    /* Fourteen tiles have to sit on one line on a phone held upright,
       so the ones in hand are their own size. Wrapping them puts the
       tile just drawn on a line of its own, which is the one tile
       being looked at. */
    --hand-w: 24px; --hand-h: 33px;
    --drop-w: 22px; --drop-h: 30px;
    --back-w: 9px;  --back-h: 15px;
}
.seat-top { grid-area: top; justify-self: center; }
.seat-left { grid-area: left; }
.seat-right { grid-area: right; }
.pool { grid-area: pool; }
.mine { grid-area: mine; }

.seat {
    display: flex; align-items: center; justify-content: center; gap: 5px;
    padding: 4px 7px; border-radius: 11px;
    background: rgba(255, 255, 255, 0.045);
    font-size: 0.64rem; color: var(--muted);
}
.seat.is-turn { background: rgba(240, 193, 75, 0.18); color: var(--text); }
.seat .who { font-size: 0.7rem; font-weight: 700; color: var(--text); white-space: nowrap; }
.seat .backs { display: flex; gap: 1px; }
.seat .backs i {
    width: var(--back-w); height: var(--back-h); border-radius: 2px;
    background: linear-gradient(180deg, #2f7d55, #1c5c3c);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.18);
    display: block;
}
.seat .held { display: flex; gap: 4px; flex-wrap: wrap; }
.seat .held .set { display: flex; gap: 1px; }

/* The sides run down the screen, so their tiles and their labels turn with them. */
.seat-left, .seat-right { flex-direction: column; align-self: center; }
.seat-left .backs, .seat-right .backs { flex-direction: column; }
.seat-left .backs i, .seat-right .backs i { width: var(--back-h); height: var(--back-w); }
.seat-left .held, .seat-right .held { flex-direction: column; }

/* The felt, with what everyone has thrown laid out in front of them. */
.pool {
    position: relative; min-height: 80px;
    /* Each pile sits in front of the player who threw it and grows toward the
       middle, which is where the middle is for. Centring the four instead made
       the block grow outward from the centre as it filled, and a discard pile
       is exactly the thing that fills -- it climbed over the seat above and the
       hand below, and the reserved version scrolled the top pile out of sight
       altogether. Growing inward, the gap in the middle absorbs it. */
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    grid-template-rows: auto minmax(0, 1fr) auto;
    grid-template-areas:
        ".      ptop  ."
        "pleft  .     pright"
        ".      pbot  .";
    justify-items: center;
    gap: 6px; padding: 10px;
    border-radius: 16px;
    background:
        radial-gradient(120% 90% at 50% 0%, rgba(255, 255, 255, 0.05), transparent 60%),
        rgba(0, 0, 0, 0.24);
    box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.05);
}
.drop { display: flex; flex-wrap: wrap; gap: 2px; align-content: flex-start; }
/* Six to a row, which is how a pile is laid out and what makes its length
   something to take in at a glance. The two at the sides run down the screen
   instead of across, because that is the direction they face.

   Each pile reserves room for three rows of six from the start. Without that
   the piles grew as they filled and pushed the whole block out past the felt,
   over the seat above and the hand below -- and a discard pile is exactly the
   thing that grows. Eighteen is more than a hand ever throws. */
.drop-top, .drop-bottom {
    width: calc(var(--drop-w) * 6 + 10px);
    justify-content: flex-start;
}
.drop-top { align-self: start; align-content: flex-start; }
.drop-bottom { align-self: end; align-content: flex-end; }
/* The two at the sides take the height they are given and wrap into a second
   column rather than growing past it, so a long game cannot push them out. */
.drop-left, .drop-right {
    flex-direction: column; flex-wrap: wrap;
    height: 100%; align-self: stretch;
}
.drop-left { justify-self: start; align-content: flex-start; }
.drop-right { justify-self: end; align-content: flex-end; }
.drop-top { grid-area: ptop; }
.drop-bottom { grid-area: pbot; }
.drop-left { grid-area: pleft; }
.drop-right { grid-area: pright; }
.drop .tile { width: var(--drop-w); height: var(--drop-h); cursor: default; }
.drop .tile.is-last { outline: 2px solid var(--accent); outline-offset: 1px; }

/* A tile is a painted picture rather than a letter in a box: dots are circles,
   bamboo is bamboo, and the characters carry their numeral over 萬. */
.tile {
    width: var(--tile-w); height: var(--tile-h); flex: 0 0 auto;
    border-radius: 5px;
    background-repeat: no-repeat; background-size: 100% 100%;
    box-shadow: 0 2px 0 rgba(0, 0, 0, 0.28);
    cursor: pointer;
}
.tile.is-drawn { margin-left: 12px; box-shadow: 0 2px 0 rgba(0,0,0,.28), 0 0 0 2px var(--accent); }
.hand .tile:hover { transform: translateY(-4px); }
.hand .tile { transition: transform 0.09s ease; }
.tile:active { transform: translateY(2px); box-shadow: none; }

.mine { display: flex; flex-direction: column; align-items: center; gap: 5px; }
.hand { display: flex; gap: 2px; justify-content: center; padding: 2px 0; }
.hand .tile { width: var(--hand-w); height: var(--hand-h); }
.myMelds { display: flex; gap: 8px; justify-content: center; flex-wrap: wrap; }
.myMelds .set { display: flex; gap: 1px; }
.myMelds .tile { transform: scale(0.66); transform-origin: bottom center; margin: 0 -5px; }

/* Only what can actually be done shows up here. */
.calls { display: flex; gap: 6px; justify-content: center; flex: 0 0 auto; min-height: 46px; margin-top: 4px; }
.calls button {
    min-width: 58px; min-height: 44px; padding: 0 12px;
    border: 1px solid var(--line); border-radius: 11px;
    background: var(--panel); color: var(--text);
    font-family: inherit; font-size: 0.95rem; font-weight: 700; cursor: pointer;
}
.calls button.win { border-color: var(--accent); background: rgba(240, 193, 75, 0.24); color: var(--accent); }
.calls button:active { transform: scale(0.96); }

.hint-text { margin-top: 4px; text-align: center; font-size: 0.66rem; color: var(--muted); min-height: 1.2em; }
.hint-text.is-warn { color: var(--accent); font-weight: 700; }

.overlay {
    position: absolute; inset: 0; display: none;
    align-items: center; justify-content: center; padding: 18px;
    background: rgba(5, 12, 9, 0.9);
    backdrop-filter: blur(5px); -webkit-backdrop-filter: blur(5px);
    z-index: 50;
}
.overlay.is-open { display: flex; }

.panel {
    width: 100%; max-width: 340px; max-height: 100%; overflow-y: auto;
    display: flex; flex-direction: column; gap: 10px;
    padding: 22px 18px;
    border: 1px solid var(--line); border-radius: 20px;
    background: linear-gradient(180deg, #204133, #0e1d16);
    text-align: center; animation: pop 0.22s ease;
}
@keyframes pop { from { opacity: 0; transform: translateY(12px) scale(0.97); } to { opacity: 1; transform: none; } }

.title {
    font-size: clamp(1.8rem, 8vw, 2.4rem); font-weight: 800; letter-spacing: 0.12em;
    background: linear-gradient(135deg, #ffe9ac, var(--accent) 55%, #d98b2b);
    -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent;
}
.panel-title { font-size: 1.5rem; font-weight: 800; color: var(--accent); }
.subtitle { color: var(--muted); font-size: 0.85rem; line-height: 1.7; }

.modes { display: flex; flex-direction: column; gap: 8px; margin-top: 4px; }
.mode {
    display: flex; align-items: center; justify-content: space-between;
    padding: 13px 16px;
    border: 1px solid var(--line); border-radius: 13px;
    background: rgba(255, 255, 255, 0.05); color: var(--text);
    font-family: inherit; font-size: 0.95rem; font-weight: 700; cursor: pointer;
}
.mode small { font-size: 0.68rem; font-weight: 500; color: var(--muted); }
.mode:active { transform: scale(0.98); border-color: var(--accent); }

.legend { display: flex; flex-direction: column; gap: 5px; margin-top: 6px; text-align: left; }
.legend h3 { font-size: 0.7rem; letter-spacing: 0.1em; color: var(--muted); font-weight: 600; }
.legend-row { display: flex; align-items: baseline; gap: 8px; font-size: 0.72rem; color: var(--muted); }
.legend-row b { flex: 0 0 auto; width: 2.4em; color: var(--text); font-size: 0.78rem; }

.btn {
    min-height: 46px; padding: 12px 20px;
    border: 1px solid var(--line); border-radius: 13px;
    background: rgba(255, 255, 255, 0.05); color: var(--text);
    font-family: inherit; font-size: 0.92rem; font-weight: 700;
    display: flex; align-items: center; justify-content: center; cursor: pointer;
}
.btn:active { transform: scale(0.97); }
.btn-primary { border-color: transparent; background: linear-gradient(135deg, #ffe6a8, #dda63a); color: #2a1c00; }

.stat-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 7px; }
.stat { padding: 9px 6px; border-radius: 11px; background: rgba(255, 255, 255, 0.06); }
.stat b { display: block; font-size: 1.05rem; font-variant-numeric: tabular-nums; }
.stat span { font-size: 0.62rem; color: var(--muted); }

@media (max-height: 720px) {
    .hud { margin: 3px 0; }
    .tile { width: 26px; height: 37px; }
    .tile .rank { font-size: 0.85rem; }
    .hint-text { display: none; }
}

@media (prefers-reduced-motion: reduce) { .panel { animation: none; } }

/* On a desk there is room for a proper table, so the tiles get the size they
   would have in the hand rather than the size a phone can spare. */
@media (min-width: 880px) and (min-height: 620px) {
    .table {
        --tile-w: 48px; --tile-h: 66px;
        --hand-w: 48px; --hand-h: 66px;
        --drop-w: 34px; --drop-h: 46px;
        --back-w: 15px; --back-h: 24px;
        gap: 12px;
    }
    .hand { gap: 4px; }
    .pool { min-height: 240px; padding: 18px; }
    .seat { font-size: 0.78rem; padding: 8px 12px; }
    .seat .who { font-size: 0.86rem; }
    .hud b { font-size: 1.15rem; }
    .hud i { font-size: 0.66rem; }
    .toolbar { height: 46px; }
}

@media (min-width: 1180px) and (min-height: 760px) {
    .table {
        --tile-w: 56px; --tile-h: 77px;
        --hand-w: 56px; --hand-h: 77px;
        --drop-w: 38px; --drop-h: 52px;
        --back-w: 17px; --back-h: 27px;
    }
}

/* A phone has no room for a table with three sides to it: the two side panels
   eat a third of the width and leave the felt too narrow to lay anything out
   in. Below this the three opponents become bars stacked above the table, and
   the felt gets the whole width -- the four piles still sit apart in it, so who
   threw what is still there to read. */
@media (max-width: 700px) {
    .table {
        grid-template-columns: minmax(0, 1fr);
        grid-template-rows: auto auto auto minmax(0, 1fr) auto;
        grid-template-areas: "top" "left" "right" "pool" "mine";
        gap: 4px;
    }
    .seat { justify-content: flex-start; }
    .seat-top { justify-self: stretch; }
    .seat-left, .seat-right { flex-direction: row; align-self: stretch; }
    .seat-left .backs, .seat-right .backs { flex-direction: row; }
    .seat-left .backs i, .seat-right .backs i { width: var(--back-w); height: var(--back-h); }
    .seat-left .held, .seat-right .held { flex-direction: row; }
    .pool { padding: 6px; }
}
