/* Code the Concept — mobile-first party theme (Okabe–Ito accent set, colorblind-safe).
   Three themes share one variable system: :root is light (default), [data-theme] blocks
   override it. Each head's index.html sets data-theme on <html> before first paint.
   Every text/background pair below is tuned to WCAG AA in all three themes:
   fills/borders keep the Okabe–Ito hues, text uses the matching "-ink" variants. */

:root {
    --bg: #f4f1ea;
    --surface: #ffffff;
    --surface-inset: #f7f5f0;
    --text: #26221c;
    --muted: #68635a;
    /* edge shadow for horizontally scrollable tab strips (scroll affordance) */
    --strip-shadow: rgba(38, 34, 28, .28);
    --border: #e4dfd5;
    --accent: #0072B2;
    --accent-contrast: #ffffff;
    --accent-warm: #E69F00;
    --success: #009E73;
    --danger: #D55E00;
    --pink: #CC79A7;
    /* text-safe variants of the accent hues (≥4.5:1 on surface/inset) */
    --warm-ink: #6d5600;
    --success-ink: #006b4e;
    --danger-ink: #a34400;
    --pink-ink: #96436d;
    /* banner pairs */
    --warn-bg: #fff8e1;
    --warn-text: #6d5600;
    --danger-bg: #fdeee4;
    --danger-text: #8a3c00;
    /* podium bars */
    --podium-silver: #b9c4cc;
    --podium-bronze: #d3a17e;
    /* the drawing surface is WHITE in every theme — drawings are dark ink on paper */
    --canvas: #ffffff;
    --canvas-border: #e4dfd5;
    --radius: 14px;
    --shadow: 0 2px 10px rgba(38, 34, 28, .07);
    color-scheme: light;
    font-size: 16px;
}

:root[data-theme="dark"] {
    --bg: #14161b;
    --surface: #1e2128;
    --surface-inset: #272b33;
    --text: #ece9e2;
    --muted: #b0aca0;
    --strip-shadow: rgba(0, 0, 0, .6);
    --border: #3a3f4a;
    /* Okabe–Ito sky blue reads as the same accent family, and carries dark text at 8:1 */
    --accent: #56B4E9;
    --accent-contrast: #10141a;
    --accent-warm: #E69F00;
    --success: #009E73;
    --danger: #D55E00;
    --pink: #CC79A7;
    --warm-ink: #e6a817;
    --success-ink: #2fc493;
    --danger-ink: #ff8f4d;
    --pink-ink: #d894b9;
    --warn-bg: #37310f;
    --warn-text: #f0d269;
    --danger-bg: #3c2315;
    --danger-text: #ffb38a;
    --podium-silver: #97a1ab;
    --podium-bronze: #b58057;
    --canvas: #ffffff;
    --canvas-border: #4a505c;
    --shadow: 0 2px 10px rgba(0, 0, 0, .45);
    color-scheme: dark;
}

:root[data-theme="sakura"] {
    --bg: #f9edf1;
    --surface: #fffbfc;
    --surface-inset: #f8e7ed;
    --text: #40222e;
    --muted: #7d5563;
    --strip-shadow: rgba(64, 34, 46, .28);
    --border: #ecd2dc;
    --accent: #b42a6f;
    --accent-contrast: #ffffff;
    --accent-warm: #E69F00;
    --success: #00926a;
    --danger: #D55E00;
    --pink: #CC79A7;
    --warm-ink: #775300;
    --success-ink: #00694d;
    --danger-ink: #a03d00;
    --pink-ink: #94406a;
    --warn-bg: #fbf1d3;
    --warn-text: #6d5600;
    --danger-bg: #fce4d7;
    --danger-text: #8a3c00;
    --podium-silver: #c3b3bd;
    --podium-bronze: #d6a17f;
    --canvas: #ffffff;
    --canvas-border: #ecd2dc;
    --shadow: 0 2px 10px rgba(64, 34, 46, .10);
    color-scheme: light;
}

* { box-sizing: border-box; }

html, body {
    margin: 0;
    padding: 0;
    background: var(--bg);
    color: var(--text);
    font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
    line-height: 1.45;
}

h1 { font-size: 1.6rem; margin: 0 0 .5rem; }
h2 { font-size: 1.15rem; margin: 0 0 .5rem; }
h3 { font-size: 1rem; margin: .75rem 0 .35rem; }
p { margin: .35rem 0; }
a { color: var(--accent); }

.muted { color: var(--muted); font-size: .9rem; }

/* ---------- splash / loading ---------- */
.app-splash {
    min-height: 100dvh;
    display: flex; flex-direction: column; align-items: center; justify-content: center; gap: .5rem;
}
.app-splash-mark { font-size: 3rem; animation: bob 1.2s ease-in-out infinite alternate; }
.app-splash-title { font-weight: 700; font-size: 1.3rem; }
.app-splash-hint { color: var(--muted); }
@keyframes bob { from { transform: translateY(-4px); } to { transform: translateY(4px); } }

.page-loading { text-align: center; padding: 3rem 1rem; color: var(--muted); }

#blazor-error-ui {
    background: var(--warn-bg); color: var(--warn-text); position: fixed; bottom: 0; left: 0; right: 0;
    padding: .75rem 1rem; display: none; z-index: 1000; box-shadow: 0 -2px 8px rgba(0,0,0,.15);
}
#blazor-error-ui .dismiss { float: right; cursor: pointer; }

/* ---------- shell ---------- */
.app-shell { min-height: 100dvh; display: flex; flex-direction: column; }

.app-bar {
    display: flex; align-items: center; justify-content: space-between; gap: .5rem;
    padding: .6rem .9rem;
    background: var(--surface);
    border-bottom: 2px solid var(--border);
    position: sticky; top: 0; z-index: 50;
}
.brand { font-weight: 800; text-decoration: none; color: var(--text); font-size: 1.05rem; white-space: nowrap; }
.app-bar-left { display: flex; align-items: center; gap: .7rem; min-width: 0; }
.app-bar-actions { display: flex; align-items: center; gap: .5rem; min-width: 0; }
.app-nav { display: flex; align-items: center; gap: .6rem; min-width: 0; }
.nav-user {
    display: inline-flex; align-items: center; gap: .4rem;
    min-height: 44px; /* a real 44px touch target for the profile chip */
    font-weight: 600; text-decoration: none; color: var(--text);
    max-width: 10rem; min-width: 0;
}
.nav-user-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ---------- primary navigation (MainLayout) ----------
   One link list renders twice: .primary-nav inline (≥768px) and .app-menu collapsed below.
   Later waves: add the link to PrimaryNavLinks in MainLayout.razor — both variants pick it up. */
.primary-nav { display: none; }
.primary-nav-link {
    display: inline-flex; align-items: center;
    min-height: 44px; padding: .3rem .7rem; border-radius: 8px;
    color: var(--text); text-decoration: none; font-weight: 600; white-space: nowrap;
}
.primary-nav-link:hover { background: var(--surface-inset); }
.primary-nav-link.active { color: var(--accent); background: var(--surface-inset); }
.app-menu { position: relative; }
.app-menu-toggle { min-height: 44px; }
.app-menu-backdrop { position: fixed; inset: 0; z-index: 60; background: transparent; }
.app-menu-panel {
    position: absolute; left: 0; top: calc(100% + .4rem); z-index: 61;
    display: flex; flex-direction: column; gap: .1rem; min-width: 11rem; padding: .3rem;
    background: var(--surface); border: 1px solid var(--border); border-radius: 12px;
    box-shadow: var(--shadow);
}
.app-menu-link {
    display: flex; align-items: center;
    min-height: 44px; padding: .4rem .8rem; border-radius: 8px;
    color: var(--text); text-decoration: none; font-weight: 600;
}
.app-menu-link:hover { background: var(--surface-inset); }
.app-menu-link.active { color: var(--accent); background: var(--surface-inset); }
/* The inline nav switches on only when the WORST case genuinely fits: brand + 6 links
   (admin user) + theme pill + a 20-char user chip + Log out. Measured, that clears ~1040px,
   so the collapsed ☰ Menu stays up to 1100px — no band may ever collide (see AppBarLayoutTests). */
@media (min-width: 1100px) {
    .primary-nav { display: flex; align-items: center; gap: .15rem; }
    .app-menu { display: none; }
}

/* ---------- avatar ----------
   Fixed square (inline width/height/font-size from the component) — the image and the initials
   fallback swap without any layout shift. The initial paints via content: attr(data-initial) so
   it never leaks into textContent (rows and chips assert on their text). The disc color is a
   fixed AA-against-white palette hashed from the username (theme-independent by design). */
.avatar {
    position: relative; display: inline-flex; flex: 0 0 auto;
    border-radius: 50%; overflow: hidden;
    color: #ffffff; font-weight: 700; line-height: 1;
    -webkit-user-select: none; user-select: none;
}
.avatar::before {
    content: attr(data-initial);
    position: absolute; inset: 0;
    display: flex; align-items: center; justify-content: center;
}
.avatar-img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
/* until the image has actually loaded, the fallback shows through */
.avatar[data-avatar-state="fallback"] .avatar-img { opacity: 0; }
/* once it has, the initial disappears (transparent avatars must not show a ghost letter) */
.avatar[data-avatar-state="image"]::before { visibility: hidden; }

/* ---------- theme switcher ---------- */
.theme-switcher { position: relative; }
.theme-menu-backdrop { position: fixed; inset: 0; z-index: 60; background: transparent; }
.theme-menu {
    position: absolute; right: 0; top: calc(100% + .4rem); z-index: 61;
    display: flex; flex-direction: column; gap: .1rem; min-width: 9.5rem; padding: .3rem;
    background: var(--surface); border: 1px solid var(--border); border-radius: 12px;
    box-shadow: var(--shadow);
}
.theme-option {
    display: flex; align-items: center; gap: .5rem;
    min-height: 44px; padding: .4rem .7rem;
    background: none; border: none; border-radius: 8px;
    font-size: .95rem; font-weight: 600; color: var(--text); text-align: left; cursor: pointer;
}
.theme-option:hover { background: var(--surface-inset); }
.theme-option-active { color: var(--accent); }
.theme-option-active::after { content: "✓"; margin-left: auto; }

@media (max-width: 767.98px) {
    /* keep the sticky bar uncrowded on phones and small tablets: icon-only theme trigger, and
       once the signed-in nav is present the wordmark yields (the 🧩 mark stays) and the user chip
       collapses to the avatar (the link keeps its accessible name via the img alt) */
    .theme-toggle-text { display: none; }
    .app-bar:has(.app-nav) .brand-name { display: none; }
    .nav-user { max-width: 5.5rem; }
    .app-bar:has(.app-nav) .nav-user-name { display: none; }
}

.app-main {
    flex: 1;
    width: 100%;
    max-width: 760px;
    margin: 0 auto;
    padding: 1rem .9rem 3rem;
}

/* ---------- primitives ---------- */
.card {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    padding: 1rem;
    margin-bottom: .9rem;
}
.card-inset { background: var(--surface-inset); border-radius: 10px; padding: .8rem; }
.center-card { text-align: center; padding: 2rem 1rem; }

.btn {
    display: inline-flex; align-items: center; justify-content: center; gap: .4rem;
    min-height: 44px; padding: .55rem 1.1rem;
    border-radius: 999px; border: 2px solid transparent;
    font-size: 1rem; font-weight: 700; cursor: pointer; text-decoration: none;
    transition: transform .06s ease, filter .15s ease;
    -webkit-tap-highlight-color: transparent;
}
.btn:active { transform: scale(.97); }
.btn:disabled { opacity: .5; cursor: not-allowed; }
.btn-primary { background: var(--accent); color: var(--accent-contrast); }
/* disabled primaries stay readable-but-clearly-disabled: muted ink on the inset surface
   (≥4.5:1 in all three themes) instead of a half-transparent accent wash */
.btn-primary:disabled {
    background: var(--surface-inset); color: var(--muted);
    border-color: var(--border); opacity: 1;
}
.btn-primary:hover:not(:disabled) { filter: brightness(1.1); }
.btn-ghost { background: transparent; color: var(--text); border-color: var(--border); }
.btn-ghost:hover:not(:disabled) { background: var(--surface-inset); }
.btn-active { border-color: var(--accent); color: var(--accent); }
.btn-small { min-height: 34px; padding: .25rem .7rem; font-size: .85rem; position: relative; }
/* compact buttons keep their look but honor the 44px touch-target rule via an invisible halo */
.btn-small::after { content: ""; position: absolute; inset: -5px; border-radius: inherit; }
.btn-big { font-size: 1.1rem; padding: .8rem 1.6rem; }
.btn-block { width: 100%; }

.input {
    width: 100%; min-height: 44px;
    padding: .5rem .75rem;
    border: 2px solid var(--border); border-radius: 10px;
    background: var(--surface); color: var(--text);
    font-size: 1rem;
}
.input:focus { outline: none; border-color: var(--accent); }
.input-big { font-size: 1.2rem; }
.input-code {
    text-transform: uppercase; letter-spacing: .5em; font-weight: 800; text-align: center; font-size: 1.4rem;
}

.field { display: flex; flex-direction: column; gap: .25rem; margin: .5rem 0; flex: 1; min-width: 0; }
.field > span { font-size: .85rem; font-weight: 600; color: var(--muted); }
.field-hint { font-size: .8rem; color: var(--danger-ink); }
/* the up-front (not-yet-failed) flavor of a field's requirements line */
.field-requirements { font-size: .8rem; }
.field-row { display: flex; gap: .6rem; flex-wrap: wrap; }

/* grouped fields (e.g. the step timers) — a real fieldset with a legend */
.field-group {
    border: 1px solid var(--border); border-radius: 10px;
    margin: .5rem 0; padding: 0 .7rem .35rem;
    min-width: 0; /* fieldsets default to min-content and would overflow narrow cards */
}
.field-group > legend { font-size: .85rem; font-weight: 600; color: var(--muted); padding: 0 .3rem; }
.timer-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: .6rem; }

.chip {
    display: inline-flex; align-items: center; gap: .25rem;
    background: var(--surface-inset); border: 1px solid var(--border);
    border-radius: 999px; padding: .15rem .6rem; font-size: .8rem; font-weight: 600;
}
.chip-host { border-color: var(--accent-warm); }
.chip-author { border-color: var(--accent); }

.banner-error, .banner-warn {
    display: flex; align-items: center; justify-content: space-between; gap: .5rem;
    border-radius: 10px; padding: .6rem .9rem; margin-bottom: .8rem; font-weight: 600;
}
.banner-error { background: var(--danger-bg); color: var(--danger-text); border: 1px solid var(--danger); }
.banner-warn { background: var(--warn-bg); color: var(--warn-text); border: 1px solid var(--accent-warm); }
.banner-dismiss { background: none; border: none; font-size: 1rem; cursor: pointer; color: inherit; }

/* ---------- auth ---------- */
.auth-card { max-width: 420px; margin: 8dvh auto 0; }
.auth-sub { color: var(--muted); margin-bottom: 1rem; }
.auth-switch { margin-top: 1rem; text-align: center; }

/* ---------- home ---------- */
.hero { text-align: center; padding: 1rem 0 1.4rem; }
.hero h1 { font-size: 2rem; }
.hero p { color: var(--muted); max-width: 34rem; margin: 0 auto; }
.home-cards { display: grid; grid-template-columns: 1fr; gap: .9rem; align-items: stretch; margin-bottom: .9rem; }
.home-cards .card { margin-bottom: 0; }
/* every card is a column with its CTA anchored to the bottom edge */
.home-card { display: flex; flex-direction: column; }
.home-card-cta { margin-top: auto; }
.home-card > :nth-last-child(2) { margin-bottom: .9rem; }
/* the secondary feature rows that keep the short cards from showing 200px voids at ≥640px */
.home-mini { list-style: none; display: flex; flex-direction: column; gap: .4rem; margin: .6rem 0 0; padding: 0; }
.home-mini li { color: var(--muted); font-size: .9rem; }
.how-to ol { margin: .4rem 0 .6rem 1.2rem; padding: 0; }
.how-to li { margin: .35rem 0; }

/* ---------- lobby ---------- */
.room-code-card { text-align: center; }
.room-code-row { display: flex; align-items: center; justify-content: center; gap: .7rem; margin: .3rem 0; }
.room-code { font-size: 2.2rem; font-weight: 800; letter-spacing: .35em; margin-left: .35em; }
.player-list { list-style: none; margin: 0; padding: 0; }
.player-row { display: flex; align-items: center; gap: .6rem; padding: .45rem 0; border-bottom: 1px solid var(--border); }
.player-row:last-child { border-bottom: none; }
.player-name { flex: 1; display: flex; align-items: center; gap: .4rem; font-weight: 600; min-width: 0; overflow-wrap: anywhere; }
.conn-dot { width: 10px; height: 10px; border-radius: 50%; flex-shrink: 0; }
.conn-dot.on { background: var(--success); }
.conn-dot.off { background: var(--border); }
.settings-summary { list-style: none; margin: 0; padding: 0; }
.settings-summary li { padding: .25rem 0; }
.lobby-actions { display: flex; flex-direction: column; align-items: center; gap: .6rem; margin-top: 1rem; }

/* ---------- play panels ---------- */
.play-panel { display: flex; flex-direction: column; }
.play-header { display: flex; align-items: center; justify-content: space-between; gap: .4rem; margin-bottom: .7rem; }
.play-header-chips { display: inline-flex; align-items: center; flex-wrap: wrap; gap: .3rem; min-width: 0; }

.countdown {
    font-weight: 800; font-size: 1.1rem;
    background: var(--surface); border: 2px solid var(--border); border-radius: 999px;
    padding: .2rem .8rem;
}
.countdown-urgent { color: var(--danger-ink); border-color: var(--danger); animation: pulse .6s ease-in-out infinite alternate; }
@keyframes pulse { from { transform: scale(1); } to { transform: scale(1.06); } }

.concept-card, .concept-banner { text-align: center; }
.concept-text { font-size: 1.9rem; margin: .3rem 0; }

.picked-row {
    display: flex; align-items: center; flex-wrap: wrap; gap: .45rem .55rem;
    min-height: 54px; padding: .55rem .5rem; margin-bottom: .6rem;
    background: var(--surface-inset); border-radius: 10px;
}
.picked-emoji { font-size: 1.7rem; background: none; border: none; cursor: pointer; padding: .1rem; }
.picked-count { margin-left: auto; color: var(--muted); font-size: .85rem; font-weight: 700; }
/* at N/N the counter flags the cap instead of staying quiet grey */
.picked-count-max { color: var(--warm-ink); }

.emoji-search { margin-bottom: .5rem; }
.emoji-tabs { display: flex; gap: .2rem; overflow-x: auto; margin-bottom: .4rem; }
.emoji-tab {
    font-size: 1.25rem; padding: .3rem .55rem; background: none;
    border: none; border-bottom: 3px solid transparent; cursor: pointer;
}
.emoji-tab-active { border-bottom-color: var(--accent); background: var(--surface-inset); border-radius: 8px 8px 0 0; }
.emoji-grid {
    display: grid; grid-template-columns: repeat(auto-fill, minmax(44px, 1fr));
    gap: 2px; max-height: 260px; overflow-y: auto;
}
.emoji-cell {
    font-size: 1.5rem; min-height: 44px;
    background: none; border: none; border-radius: 8px; cursor: pointer;
}
.emoji-cell:hover:not(:disabled) { background: var(--surface-inset); }
/* at the symbol cap the grid reads "full", exactly like .symbol-cell on the other tabs */
.emoji-cell:disabled { opacity: .4; cursor: not-allowed; }

.draw-tool { display: flex; flex-direction: column; gap: .6rem; }
/* Drawings are ink on paper: the canvas stays WHITE in every theme (dark strokes must
   stay readable); the themed border makes it read as a sheet on dark backgrounds. */
.draw-canvas, .content-drawing {
    width: 100%; max-width: 500px; aspect-ratio: 1; margin: 0 auto; display: block;
    background: var(--canvas); border: 2px solid var(--canvas-border); border-radius: 10px;
    touch-action: none;
}
.content-drawing { touch-action: auto; }
.draw-toolbar { display: flex; flex-direction: column; gap: .5rem; }
.swatch-row { display: flex; gap: .4rem; flex-wrap: wrap; justify-content: center; }
.swatch {
    width: 34px; height: 34px; border-radius: 50%; cursor: pointer;
    border: 3px solid var(--border);
}
.swatch-active { border-color: var(--text); transform: scale(1.12); }
.width-row { display: flex; gap: .4rem; justify-content: center; flex-wrap: wrap; }

.waiting .center-card { padding: 2.2rem 1rem; }
.progress-track {
    height: 12px; background: var(--surface-inset); border-radius: 999px; overflow: hidden; margin: .8rem 0 .3rem;
}
.progress-fill { height: 100%; background: var(--success); border-radius: 999px; transition: width .4s ease; }
.waiting-copy { margin-top: 1rem; font-style: italic; }

/* ---------- content display ---------- */
.content-emoji { font-size: 2.6rem; line-height: 1.3; text-align: center; padding: .5rem; word-break: break-word; }
.content-guess { font-size: 1.4rem; font-weight: 700; text-align: center; margin: .5rem 0; overflow-wrap: anywhere; }
.content-skipped { display: flex; align-items: center; gap: .6rem; color: var(--muted); font-style: italic; }
.skip-mark { font-size: 1.4rem; }

/* ---------- reveal ---------- */
.reveal-header { text-align: center; margin-bottom: .6rem; }
.reveal-chain { display: flex; flex-direction: column; }
.reveal-entry { animation: appear .45s ease; }
@keyframes appear { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }
.reveal-entry-head { display: flex; align-items: center; flex-wrap: wrap; gap: .4rem; margin-bottom: .5rem; }
.report-btn { margin-left: auto; background: none; border: none; cursor: pointer; opacity: .35; font-size: .95rem; }
.report-btn:hover { opacity: 1; }

.guess-result { text-align: center; }
.result-copy { font-size: 1.3rem; font-weight: 800; }
.result-correct { color: var(--success-ink); }
.result-close { color: var(--warm-ink); }
.result-miss { color: var(--muted); }

.vote-card { border: 2px solid var(--accent-warm); }
.vote-group { margin: .6rem 0; }
.vote-chips { display: flex; flex-wrap: wrap; gap: .4rem; margin-top: .3rem; }
.vote-chip { cursor: pointer; min-height: 38px; }
.vote-chip-active { background: var(--accent); color: var(--accent-contrast); border-color: var(--accent); }

.awards-list { list-style: none; margin: 0 0 .6rem; padding: 0; }
.awards-list li { padding: .25rem 0; }
.scoreboard { margin: 0; padding-left: 1.4rem; }
.scoreboard li { display: flex; justify-content: space-between; padding: .25rem 0; border-bottom: 1px dashed var(--border); }
.scoreboard li:last-child { border-bottom: none; }
.scoreboard-name { display: inline-flex; align-items: center; gap: .45rem; min-width: 0; overflow-wrap: anywhere; }

.reveal-actions { text-align: center; margin-top: .8rem; }

/* ---------- podium ---------- */
.podium { text-align: center; }
.podium-tie { font-weight: 700; color: var(--warm-ink); margin: .2rem 0 0; }
.podium-blocks { display: flex; align-items: flex-end; justify-content: center; gap: .7rem; margin: 1.4rem 0; }
.podium-block { display: flex; flex-direction: column; align-items: center; gap: .2rem; flex: 1; max-width: 150px; min-width: 0; }
.podium-medal { font-size: 2rem; }
.podium-name { font-weight: 800; word-break: break-word; }
.podium-points { color: var(--muted); font-weight: 700; }
.podium-bar { width: 100%; border-radius: 8px 8px 0 0; }
.podium-rank-1 .podium-bar { height: 110px; background: var(--accent-warm); }
.podium-rank-2 .podium-bar { height: 78px; background: var(--podium-silver); }
.podium-rank-3 .podium-bar { height: 54px; background: var(--podium-bronze); }
.podium-actions { margin-top: 1.2rem; }

/* ---------- profile ---------- */
.profile-identity { display: flex; align-items: center; gap: 1.1rem; }
/* the avatar doubles as the upload affordance: pointer cursor + camera badge + hover ring */
.avatar-click { position: relative; display: inline-flex; flex: 0 0 auto; cursor: pointer; border-radius: 50%; }
.avatar-click:hover .avatar { outline: 3px solid var(--accent); outline-offset: 2px; }
.avatar-camera {
    position: absolute; right: -2px; bottom: -2px;
    display: inline-flex; align-items: center; justify-content: center;
    width: 30px; height: 30px; font-size: .95rem;
    background: var(--surface); border: 2px solid var(--border); border-radius: 50%;
    box-shadow: var(--shadow); pointer-events: none;
}
.profile-identity-info { min-width: 0; }
.profile-identity-name { margin: 0; overflow-wrap: anywhere; }
.profile-identity-info > .muted { margin: .1rem 0 .55rem; }
.avatar-actions { display: flex; align-items: center; flex-wrap: wrap; gap: .5rem; }
/* the label IS the button; the real file input stretches invisibly across it */
.avatar-upload-label { position: relative; overflow: hidden; cursor: pointer; }
.avatar-upload-label input[type="file"] {
    position: absolute; inset: 0; width: 100%; height: 100%;
    opacity: 0; cursor: pointer;
}
.avatar-error { margin: .45rem 0 0; }

/* flex-wrap (not grid) so a trailing odd tile stretches across the last row instead of
   sitting orphaned in the first column (profile has 7 tiles, solo has 9) */
.stat-grid { display: flex; flex-wrap: wrap; gap: .7rem; margin-bottom: 1.2rem; }
.stat-card { flex: 1 1 140px; text-align: center; margin: 0; }
.stat-value { display: block; font-size: 1.7rem; font-weight: 800; }
.stat-label { color: var(--muted); font-size: .85rem; }
.history-scroll { overflow-x: auto; }
.history-table { width: 100%; border-collapse: collapse; font-size: .92rem; }
.history-table th, .history-table td { text-align: left; padding: .45rem .4rem; border-bottom: 1px solid var(--border); }
.history-table tr:last-child td { border-bottom: none; }

/* ---------- solo ---------- */
.resume-banner { border: 2px solid var(--accent-warm); }
.resume-actions { display: flex; flex-wrap: wrap; gap: .6rem; margin-top: .6rem; }

.cultural-note { max-width: 34rem; margin: 0 auto; }

.solo-verdict { text-align: center; }
.solo-verdict.verdict-correct { border: 2px solid var(--success); }
.solo-verdict.verdict-close { border: 2px solid var(--accent-warm); }
.solo-verdict .btn { margin-top: .8rem; }

.solo-report { color: var(--muted); }
.solo-report-confirm { display: inline-flex; align-items: center; flex-wrap: wrap; gap: .4rem; }
.solo-report-reason { width: auto; flex: 1 1 11rem; min-width: 9rem; max-width: 16rem; }
.rate-card .solo-report { margin-left: .5rem; }
.solo-verdict .solo-report { display: block; margin: .6rem auto 0; }

.star-rating { display: flex; align-items: center; flex-wrap: wrap; gap: .5rem; margin: .4rem 0; }
.star-rating-label { min-width: 4.8rem; font-size: .85rem; font-weight: 600; color: var(--muted); }
.star-chips { display: flex; gap: .3rem; }
.star-chip { min-width: 44px; min-height: 44px; justify-content: center; font-size: 1.15rem; cursor: pointer; }
.star-chip.star-filled { color: var(--warm-ink); border-color: var(--accent-warm); }
.star-rating-readonly .star-chip { cursor: default; opacity: .8; }

.solo-points { text-align: center; }
.solo-points .stat-value { font-size: 2rem; }
.summary-row-head { display: flex; align-items: center; flex-wrap: wrap; gap: .4rem; margin-bottom: .5rem; }
.summary-concept { font-weight: 700; }
.verdict-chip.verdict-correct { border-color: var(--success); color: var(--success-ink); }
.verdict-chip.verdict-close { border-color: var(--accent-warm); color: var(--warm-ink); }
.verdict-chip.verdict-miss { color: var(--muted); }
.summary-actions { display: flex; flex-wrap: wrap; justify-content: center; gap: .6rem; margin-top: 1rem; }

.rate-tabs { display: flex; gap: .4rem; margin: .6rem 0 .9rem; }
.rate-saved { color: var(--success-ink); font-weight: 700; font-size: .9rem; margin-right: .4rem; }
.rate-card-head { display: flex; align-items: center; flex-wrap: wrap; gap: .4rem; margin-bottom: .5rem; }
.chip-own { border-color: var(--pink); color: var(--pink-ink); }
.rate-concept { margin: .4rem 0 0; }
.rate-aggregate { margin: .2rem 0 .5rem; }
.rate-top { margin: .8rem 0 .4rem; }
.rate-top-title { font-size: 1.05rem; margin: 0 0 .5rem; }
.rate-top-list { display: flex; gap: .8rem; overflow-x: auto; padding-bottom: .3rem; }
.rate-top-item { flex: 0 0 auto; min-width: 11rem; max-width: 16rem; padding: .6rem .8rem; }
.rate-top-item .content-emoji { font-size: 1.4rem; }
.rate-top-line { display: flex; align-items: center; gap: .35rem; flex-wrap: wrap; margin: .2rem 0 0; }

/* ---------- symbol tokens & composer ---------- */
/* The token box is CONSTANT-size on every surface — content never grows it. */
.symbol-token {
    display: inline-flex; align-items: center; justify-content: center;
    width: 2.25rem; height: 2.25rem; flex: 0 0 auto; box-sizing: border-box;
    background: var(--surface); border: 1px solid var(--border); border-radius: 8px;
    font-size: 1.35rem; line-height: 1; color: var(--text);
    overflow: hidden; white-space: nowrap; text-overflow: ellipsis; padding: 0;
}
.symbol-token-big { width: 2.75rem; height: 2.75rem; font-size: 1.7rem; }
.symbol-token-removable { cursor: pointer; }
.symbol-token-removable:hover { border-color: var(--danger); }
.symbol-token-svg { width: 62%; height: 62%; flex: 0 0 auto; }

.symbol-cell {
    display: inline-flex; align-items: center; justify-content: center;
    background: none; border: none; border-radius: 8px; cursor: pointer; padding: 2px; min-height: 44px;
}
.symbol-cell:hover:not(:disabled) { background: var(--surface-inset); }
.symbol-cell:disabled { opacity: .4; cursor: not-allowed; }

.symbol-grid {
    display: grid; grid-template-columns: repeat(auto-fill, minmax(44px, 1fr));
    gap: 2px; max-height: 260px; overflow-y: auto;
}

.composer-tabs { display: flex; gap: .3rem; overflow-x: auto; margin: .2rem 0 .6rem; }
.composer-tab {
    padding: .35rem .7rem; background: none; font-weight: 600; color: var(--muted); white-space: nowrap;
    border: none; border-bottom: 3px solid transparent; cursor: pointer;
}
.composer-tab-active {
    color: var(--text); border-bottom-color: var(--accent);
    background: var(--surface-inset); border-radius: 8px 8px 0 0;
}
.composer-chips { display: flex; gap: .3rem; flex-wrap: wrap; margin-bottom: .5rem; }
.composer-chip { cursor: pointer; background: var(--surface); }
.composer-chip-active { border-color: var(--accent); color: var(--accent); }
.composer-search { margin-bottom: .5rem; }
.symbol-composer .btn-big { margin-top: .8rem; }

.content-symbols { display: flex; flex-wrap: wrap; gap: .3rem; justify-content: center; padding: .5rem; }
.rate-top-item .content-symbols .symbol-token { width: 2.25rem; height: 2.25rem; font-size: 1.35rem; }

/* picked-strip caret editing: tap a token to aim the next pick after it */
.picked-slot { position: relative; display: inline-flex; }
.picked-token-btn {
    display: inline-flex; align-items: center; justify-content: center;
    min-width: 44px; min-height: 44px; padding: 2px;
    background: none; border: none; border-radius: 8px; cursor: pointer;
}
.picked-token-btn:hover .symbol-token,
.picked-token-btn:focus-visible .symbol-token,
.picked-token-btn[aria-pressed="true"] .symbol-token { border-color: var(--accent); }
/* Overhangs the token's corner (notification-badge style) so its 44px circular halo clears
   the token button's own tap center — two full-size targets in one 44px slot. */
.picked-remove {
    position: absolute; top: -8px; right: -8px; z-index: 1;
    display: inline-flex; align-items: center; justify-content: center;
    width: 22px; height: 22px; padding: 0; font-size: .75rem; line-height: 1;
    background: var(--surface); border: 1px solid var(--border); border-radius: 50%;
    color: var(--muted); cursor: pointer;
}
/* small visual, full 44px touch halo — same trick as .btn-small */
.picked-remove::after { content: ""; position: absolute; inset: -11px; border-radius: inherit; }
.picked-remove:hover, .picked-remove:focus-visible { border-color: var(--danger); color: var(--danger-ink); }
.picked-edge {
    align-self: stretch; width: 44px; min-height: 44px; padding: 0;
    background: none; border: none; border-radius: 4px; cursor: pointer;
}
.picked-edge::before {
    content: ""; display: block; width: 4px; height: 2.25rem; margin: 0 auto;
    border-radius: 2px; background: var(--border);
}
.picked-edge:hover::before, .picked-edge:focus-visible::before,
.picked-edge[aria-pressed="true"]::before { background: var(--accent); }
.composer-caret {
    display: inline-block; width: 3px; height: 2.5rem; flex: 0 0 auto;
    border-radius: 2px; background: var(--accent);
    animation: caret-pulse 1.1s ease-in-out infinite alternate;
}
@keyframes caret-pulse { from { opacity: 1; } to { opacity: .35; } }
@media (prefers-reduced-motion: reduce) {
    .composer-caret { animation: none; }
}
.composer-hint { display: flex; align-items: center; flex-wrap: wrap; gap: .4rem; margin: -.2rem 0 .6rem; }
.composer-hint-btn {
    background: none; border: none; padding: 0; cursor: pointer;
    color: var(--accent); font-weight: 600; font-size: .9rem; text-decoration: underline;
}

/* Japanese dictionary tab: char cells with a tiny gloss/romaji caption */
.japanese-heading { color: var(--muted); font-size: .85rem; text-transform: uppercase; letter-spacing: .04em; margin: .6rem 0 .3rem; }
.japanese-grid { grid-template-columns: repeat(auto-fill, minmax(72px, 1fr)); }
.japanese-cell {
    display: inline-flex; flex-direction: column; align-items: center; justify-content: center; gap: .15rem;
    min-height: 56px; padding: 4px 2px;
    background: none; border: none; border-radius: 8px; cursor: pointer;
}
.japanese-cell:hover:not(:disabled) { background: var(--surface-inset); }
.japanese-cell:disabled { opacity: .4; cursor: not-allowed; }
.japanese-cell-caption {
    max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    font-size: .68rem; line-height: 1.2; color: var(--muted);
}

.method-row { align-items: center; }
.check-label { display: inline-flex; align-items: center; gap: .4rem; min-height: 44px; font-weight: 600; }
.check-label input[type="checkbox"] { width: 20px; height: 20px; accent-color: var(--accent); }

/* ---------- horizontal tab strips: scroll affordance ----------
   Every horizontally scrollable strip gets scrolling edge shadows (the fog scrolls with the
   content via background-attachment: local, the shadow stays pinned) so clipped tabs advertise
   themselves. --strip-bg matches the surface the strip sits on; --strip-shadow is themed. */
.emoji-tabs, .composer-tabs, .contribute-nav, .journey-nav, .admin-nav, .rate-top-list {
    --strip-bg: var(--bg);
    background-image:
        linear-gradient(to right, var(--strip-bg) 45%, transparent),
        linear-gradient(to left, var(--strip-bg) 45%, transparent),
        radial-gradient(farthest-side at 0 50%, var(--strip-shadow), transparent),
        radial-gradient(farthest-side at 100% 50%, var(--strip-shadow), transparent);
    background-position: left center, right center, left center, right center;
    background-size: 28px 100%, 28px 100%, 12px 100%, 12px 100%;
    background-repeat: no-repeat;
    background-attachment: local, local, scroll, scroll;
}
/* the composer strips live inside cards, so their fog must match the card surface */
.emoji-tabs, .composer-tabs { --strip-bg: var(--surface); }

/* ---------- touch ergonomics ----------
   On coarse pointers (and small screens as the fallback signal) every interactive control
   grows to the 44px platform minimum for real — not just via invisible halos. */
@media (pointer: coarse), (max-width: 767.98px) {
    .btn-small { min-height: 44px; padding: .3rem .85rem; }
    /* the avatar-only user chip stays a full 44×44 target */
    .nav-user { min-width: 44px; justify-content: center; }
    .emoji-tab, .composer-tab { min-height: 44px; }
    .vote-chip { min-height: 44px; }
    .swatch { width: 44px; height: 44px; }
    .report-btn { min-height: 44px; min-width: 44px; }
    .banner-dismiss { min-height: 44px; min-width: 44px; }
    .chip-input-field { min-height: 38px; }
    .picked-emoji { min-height: 44px; min-width: 44px; }
    .composer-hint-btn { min-height: 44px; }
}

/* ---------- wider screens ---------- */
@media (min-width: 640px) {
    .home-cards { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .hero h1 { font-size: 2.4rem; }
    .app-main { padding: 1.4rem 1.2rem 4rem; }
    .emoji-grid { max-height: 320px; }
    .symbol-grid { max-height: 320px; }
}

@media (min-width: 1100px) {
    /* pages with card collections get a wider column so the cards sit side by side
       instead of stacking into a skinny strip with acres of whitespace */
    .app-main:has(.home-cards) { max-width: 1240px; }
    .home-cards { grid-template-columns: repeat(4, minmax(0, 1fr)); }
    /* prose sections keep a readable measure inside the widened column */
    .app-main:has(.home-cards) .how-to { max-width: 46rem; margin-left: auto; margin-right: auto; }
    .app-main:has(.solo-rate) { max-width: 1100px; }
    .rate-list { display: grid; grid-template-columns: 1fr 1fr; gap: .9rem; align-items: start; }
}

/* ---------- contribute (the idea garden) ----------
   Its own identity inside the shared card language: a header strip with the section's purpose,
   pill tabs, sprouting card entrances (staggered, ≤200ms total, disabled under reduced motion),
   and vote tallies as quiet dots. Every hue below is a theme variable; text sits on -ink
   variants so all three themes stay AA. */
.contribute-page { display: flex; flex-direction: column; }
.contribute-hero {
    display: flex; align-items: center; gap: .9rem;
    padding: 1rem 1.1rem; margin-bottom: .9rem;
    background: linear-gradient(135deg, var(--surface), var(--surface-inset));
    border: 1px solid var(--border); border-left: 6px solid var(--success);
    border-radius: var(--radius); box-shadow: var(--shadow);
}
.contribute-hero-mark { font-size: 2.3rem; flex: 0 0 auto; }
.contribute-hero-copy h1 { margin: 0 0 .15rem; font-size: 1.45rem; }
.contribute-hero-copy p { margin: 0; max-width: 40rem; }

.contribute-nav { display: flex; gap: .35rem; margin-bottom: 1rem; overflow-x: auto; padding: 2px; }
.contribute-tab {
    display: inline-flex; align-items: center; gap: .35rem;
    min-height: 44px; padding: .3rem .9rem;
    border: 2px solid var(--border); border-radius: 999px;
    color: var(--text); text-decoration: none; font-weight: 600; white-space: nowrap;
}
.contribute-tab:hover { background: var(--surface-inset); }
.contribute-tab.active { border-color: var(--accent); color: var(--accent); background: var(--surface-inset); }

/* sprouting entrance — cards rise like seedlings; stagger caps at 150ms so the whole
   bed settles in under 200ms. Reduced motion switches it all off below. */
.garden-enter { animation: garden-in .35s ease backwards; }
.contribute-grid > .garden-enter:nth-child(2) { animation-delay: .05s; }
.contribute-grid > .garden-enter:nth-child(3) { animation-delay: .1s; }
.contribute-grid > .garden-enter:nth-child(n+4) { animation-delay: .15s; }
@keyframes garden-in { from { opacity: 0; transform: translateY(10px) scale(.98); } }

/* the submit form + its planted celebration */
.contribute-form, .contribute-success { width: 100%; max-width: 620px; margin-left: auto; margin-right: auto; }
.field-optional { font-weight: 400; color: var(--muted); }
.char-count { align-self: flex-end; font-size: .78rem; color: var(--muted); font-weight: 600; }
.char-count-over { color: var(--danger-ink); }
.tier-hint { font-size: .8rem; }
.note-input { resize: vertical; font-family: inherit; line-height: 1.4; }

.chip-input {
    display: flex; flex-wrap: wrap; align-items: center; gap: .35rem;
    min-height: 44px; padding: .35rem .5rem;
    background: var(--surface); border: 2px solid var(--border); border-radius: 10px;
}
.chip-input:focus-within { border-color: var(--accent); }
.chip-input-field {
    flex: 1; min-width: 9rem; min-height: 32px;
    border: none; background: none; color: var(--text); font-size: 1rem;
}
.chip-input-field:focus { outline: none; }
.chip-input-cap { font-size: .8rem; padding: .3rem .2rem; }
.synonym-chip { gap: .3rem; }
.chip-remove {
    position: relative; display: inline-flex; align-items: center; justify-content: center;
    width: 24px; height: 24px; padding: 0; font-size: .75rem; line-height: 1;
    background: none; border: none; border-radius: 50%; color: var(--muted); cursor: pointer;
}
/* small visual, full 44px touch halo — same trick as .btn-small */
.chip-remove::after { content: ""; position: absolute; inset: -10px; border-radius: inherit; }
.chip-remove:hover, .chip-remove:focus-visible { color: var(--danger-ink); background: var(--surface-inset); }

.contribute-success { text-align: center; padding: 2.2rem 1.2rem; border: 2px solid var(--success); }
.success-sprout { display: inline-block; font-size: 3rem; animation: sprout .5s ease; }
@keyframes sprout {
    from { opacity: 0; transform: translateY(14px) scale(.4); }
    60% { transform: translateY(-4px) scale(1.08); }
    to { opacity: 1; transform: none; }
}
.success-text { font-size: 1.15rem; font-weight: 700; overflow-wrap: anywhere; }
.success-actions { display: flex; flex-wrap: wrap; justify-content: center; gap: .6rem; margin: 1rem 0 .6rem; }
.success-again { color: var(--muted); }

/* the blind review stage: one focused card */
.review-stage { max-width: 620px; margin: 0 auto; width: 100%; }
.review-notice { margin: 0 0 .6rem; font-weight: 600; color: var(--success-ink); text-align: center; }
.review-card { border-top: 4px solid var(--accent); text-align: center; padding: 1.3rem 1.1rem; }
.review-text { font-size: 1.7rem; margin: .5rem 0; overflow-wrap: anywhere; }
.review-meta, .review-synonyms { display: flex; flex-wrap: wrap; justify-content: center; gap: .35rem; margin: .4rem 0; }
.review-note { max-width: 34rem; margin: .5rem auto; }
.review-comment-field { text-align: left; margin-top: .9rem; }
.review-actions { display: flex; flex-wrap: wrap; justify-content: center; gap: .7rem; margin-top: .9rem; }
.review-actions .btn { flex: 1 1 10rem; max-width: 15rem; }
.btn-approve { background: transparent; border-color: var(--success); color: var(--success-ink); }
.btn-approve:hover:not(:disabled) { background: var(--surface-inset); }
.btn-reject { background: transparent; border-color: var(--danger); color: var(--danger-ink); }
.btn-reject:hover:not(:disabled) { background: var(--surface-inset); }

/* quiet vote tallies: three dots per side, filled as votes land */
.vote-dots { display: flex; flex-wrap: wrap; justify-content: center; gap: .5rem 1.2rem; }
.dot-row { display: inline-flex; align-items: center; gap: .3rem; }
.dot { width: 10px; height: 10px; border-radius: 50%; border: 2px solid var(--border); }
.dot-approve.dot-filled { background: var(--success); border-color: var(--success); }
.dot-reject.dot-filled { background: var(--danger); border-color: var(--danger); }
.dot-row-label { font-size: .75rem; font-weight: 600; color: var(--muted); }

/* idea cards (my ideas + community) */
.contribute-grid { display: grid; grid-template-columns: 1fr; gap: .9rem; align-items: start; }
.contribute-grid .card { margin-bottom: 0; }
.idea-card-head { display: flex; align-items: center; flex-wrap: wrap; gap: .4rem; margin-bottom: .4rem; }
.idea-date { margin-left: auto; font-size: .8rem; white-space: nowrap; }
.idea-text { font-size: 1.25rem; margin: .2rem 0 .45rem; overflow-wrap: anywhere; }
.idea-meta { display: flex; flex-wrap: wrap; gap: .35rem; margin-bottom: .45rem; }
.idea-note { margin: .3rem 0 .5rem; }
.idea-votes { justify-content: flex-start; margin: .4rem 0; }

.status-badge {
    display: inline-flex; align-items: center; gap: .3rem;
    border: 2px solid; border-radius: 999px; padding: .12rem .6rem;
    font-size: .8rem; font-weight: 700; white-space: nowrap;
}
.status-pending { border-color: var(--accent-warm); color: var(--warm-ink); }
.status-accepted { border-color: var(--success); color: var(--success-ink); }
.status-rejected { border-color: var(--danger); color: var(--danger-ink); }
.status-retired { border-color: var(--border); color: var(--muted); }

.idea-comments { margin: .2rem 0; }
.idea-comment-list { list-style: none; margin: .3rem 0 0; padding: 0; }
.idea-comment {
    display: flex; gap: .45rem; align-items: baseline;
    margin: .3rem 0; padding: .45rem .6rem; font-size: .9rem;
    background: var(--surface-inset); border-left: 3px solid var(--border); border-radius: 0 8px 8px 0;
    overflow-wrap: anywhere;
}
.idea-comment.comment-approve { border-left-color: var(--success); }
.idea-comment.comment-reject { border-left-color: var(--danger); }
.idea-comment-sr {
    position: absolute; width: 1px; height: 1px; margin: -1px;
    overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}

.idea-stats {
    display: flex; flex-wrap: wrap; gap: .35rem .9rem;
    margin: .5rem 0 .2rem; padding: .5rem .7rem;
    background: var(--surface-inset); border-radius: 10px;
}
.idea-stats > div { display: flex; align-items: baseline; gap: .35rem; }
.idea-stats dt { font-size: .75rem; font-weight: 600; color: var(--muted); }
.idea-stats dd { margin: 0; font-weight: 800; font-size: .95rem; }

.garden-empty { text-align: center; padding: 2.2rem 1rem; }
.garden-empty-mark { display: block; font-size: 2.6rem; margin-bottom: .4rem; }
.garden-empty .btn { margin-top: .7rem; }
.load-more { margin-top: .9rem; }

@media (min-width: 640px) {
    .contribute-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (min-width: 1100px) {
    .app-main:has(.contribute-page) { max-width: 1240px; }
    .contribute-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
    /* the form and the review stage keep a readable measure inside the widened column */
    .contribute-form, .review-stage { margin-left: auto; margin-right: auto; width: 100%; }
    .contribute-form { max-width: 640px; }
}

@media (prefers-reduced-motion: reduce) {
    .garden-enter { animation: none; }
    .success-sprout { animation: none; }
}

/* ---------- activity (my journey) ----------
   The player's unified history. Identity per kind comes from a tinted left rail + icon
   (decorative — the title copy carries the meaning); moderation notices additionally sit on the
   warn banner palette so they read as official mail. Every hue is a theme variable; text stays on
   the theme's AA-tuned pairs (-ink variants, warn pair). */
.activity-page { display: flex; flex-direction: column; }
.journey-hero {
    display: flex; align-items: center; gap: .9rem;
    padding: 1rem 1.1rem; margin-bottom: .9rem;
    background: linear-gradient(135deg, var(--surface), var(--surface-inset));
    border: 1px solid var(--border); border-left: 6px solid var(--accent);
    border-radius: var(--radius); box-shadow: var(--shadow);
}
.journey-hero-mark { font-size: 2.3rem; flex: 0 0 auto; }
.journey-hero-copy h1 { margin: 0 0 .15rem; font-size: 1.45rem; }
.journey-hero-copy p { margin: 0; max-width: 40rem; }

.journey-nav { display: flex; gap: .35rem; margin-bottom: 1rem; overflow-x: auto; padding: 2px; }
.journey-tab {
    display: inline-flex; align-items: center; gap: .35rem;
    min-height: 44px; padding: .3rem .9rem;
    border: 2px solid var(--border); border-radius: 999px;
    color: var(--text); text-decoration: none; font-weight: 600; white-space: nowrap;
}
.journey-tab:hover { background: var(--surface-inset); }
.journey-tab.active { border-color: var(--accent); color: var(--accent); background: var(--surface-inset); }

/* the timeline keeps a readable measure even inside a widened column */
.act-timeline { width: 100%; max-width: 720px; margin: 0 auto; }

/* filter bar: multi-select chips, 44px touch, aria-pressed carries the state */
.act-filters { display: flex; flex-wrap: wrap; gap: .4rem; margin-bottom: 1rem; }
.act-filter {
    min-height: 44px; padding: .3rem .8rem; cursor: pointer;
    font-size: .85rem; color: var(--text); background: var(--surface);
}
.act-filter:hover { background: var(--surface-inset); }
.act-filter-active { border-color: var(--accent); color: var(--accent); background: var(--surface-inset); }

/* day groups: a pill header that rides just below the sticky app bar */
.act-day { margin-bottom: .5rem; }
.act-day-header {
    position: sticky; top: 3.6rem; z-index: 5;
    display: inline-flex; align-items: center; width: fit-content;
    margin: 0 0 .6rem; padding: .25rem .85rem;
    background: var(--surface); border: 1px solid var(--border); border-radius: 999px;
    font-size: .85rem; font-weight: 700; color: var(--muted);
    box-shadow: var(--shadow);
}

/* one entry: kind-tinted rail + icon + compact body */
.act-card {
    display: flex; gap: .7rem;
    padding: .8rem .9rem; margin-bottom: .7rem;
    border-left: 5px solid var(--act-rail, var(--border));
}
.act-kind-0 { --act-rail: var(--accent); }        /* encodings */
.act-kind-1 { --act-rail: var(--success); }       /* decodings */
.act-kind-2 { --act-rail: var(--podium-silver); } /* multiplayer games */
.act-kind-3 { --act-rail: var(--accent-warm); }   /* daily attempts */
.act-kind-4 { --act-rail: var(--pink); }          /* ratings given */
.act-kind-5 { --act-rail: var(--danger); }        /* reports filed */
.act-kind-6 { --act-rail: var(--accent-warm); }   /* moderation notices */
.act-icon { font-size: 1.35rem; flex: 0 0 auto; line-height: 1.5; }
.act-main { flex: 1; min-width: 0; }
.act-head { display: flex; align-items: center; flex-wrap: wrap; gap: .3rem .6rem; margin-bottom: .15rem; }
.act-title { margin: 0; font-size: 1rem; font-weight: 600; overflow-wrap: anywhere; }
.act-title strong { font-weight: 800; }
.act-time { margin-left: auto; font-size: .8rem; white-space: nowrap; }
/* inside timeline cards the timestamp pins to the top-right corner, so a wrapping title
   can't strand it in a detached mid-card position */
.act-card .act-head { position: relative; padding-right: 3rem; }
.act-card .act-head .act-time { position: absolute; top: .1rem; right: 0; margin-left: 0; }
.act-meta { display: flex; align-items: center; flex-wrap: wrap; gap: .35rem; margin: .35rem 0 0; }
.act-moderated { font-style: italic; }
/* content renders compact and left-aligned inside a feed card */
.act-card .content-emoji { font-size: 1.6rem; text-align: left; padding: .3rem 0; }
.act-card .content-symbols { justify-content: flex-start; padding: .3rem 0; }
.act-card .content-symbols .symbol-token { width: 2.25rem; height: 2.25rem; font-size: 1.35rem; }
.act-card .content-guess, .act-card .act-reason { font-size: 1.05rem; text-align: left; margin: .35rem 0; }
.act-card .content-drawing { max-width: 260px; margin: .35rem 0; }
/* read-only stars keep the look but drop the touch bulk — they're inert */
.act-card .star-rating { margin: .15rem 0; }
.act-card .star-rating-readonly .star-chip { min-width: 30px; min-height: 30px; font-size: .95rem; }

/* "how it made me feel" notes, given and received — quiet italic quotes on every surface;
   the doubled selector outweighs the act-card content-guess sizing above */
.feeling-quote, .act-card .feeling-quote {
    font-size: .95rem; font-weight: 400; font-style: italic; text-align: left;
    color: var(--muted); margin: .3rem 0;
}

/* moderation notices sit on the warn banner palette (AA pair in all three themes) */
.act-notice { background: var(--warn-bg); border-left-color: var(--accent-warm); }
.act-notice .act-title, .act-notice .muted, .act-notice .act-reason { color: var(--warn-text); }

/* visibility badges reuse the status-badge shell */
.visibility-hidden { border-color: var(--accent-warm); color: var(--warm-ink); }
.visibility-removed { border-color: var(--danger); color: var(--danger-ink); }

.act-empty-actions { display: flex; flex-wrap: wrap; justify-content: center; gap: .6rem; margin-top: .8rem; }

/* entrance: a gentle rise, stagger capped ≤150ms so the feed settles in under 200ms */
.act-enter { animation: act-in .25s ease backwards; }
.act-day .act-enter:nth-child(3), .concepts-grid > .act-enter:nth-child(2) { animation-delay: .05s; }
.act-day .act-enter:nth-child(4), .concepts-grid > .act-enter:nth-child(3) { animation-delay: .1s; }
.act-day .act-enter:nth-child(n+5), .concepts-grid > .act-enter:nth-child(n+4) { animation-delay: .15s; }
@keyframes act-in { from { opacity: 0; transform: translateY(8px); } }

/* concepts explorer */
.act-concepts-count { margin: -.4rem 0 .6rem; }
.concepts-grid { display: grid; grid-template-columns: 1fr; gap: .9rem; align-items: start; }
.concepts-grid .card { margin-bottom: 0; }
.concept-card { position: relative; }
/* accent at rest (not only on :hover, which never fires on touch) — the card IS a link */
.concept-link { color: var(--accent); text-decoration: none; }
.concept-link:hover { text-decoration: underline; }
/* stretched link: the whole card is clickable, the accessible name stays the concept text */
.concept-link::after { content: ""; position: absolute; inset: 0; border-radius: var(--radius); }
.concept-link:focus-visible { outline: none; }
.concept-link:focus-visible::after { outline: 3px solid var(--accent); outline-offset: -3px; }
.chip-origin { border-color: var(--pink); color: var(--pink-ink); }
.concept-counts { display: flex; flex-direction: column; gap: .15rem; margin: .45rem 0 0; font-size: .9rem; }

.concept-back {
    display: inline-flex; align-items: center; gap: .35rem;
    min-height: 44px; margin-bottom: .3rem;
    color: var(--accent); font-weight: 600; text-decoration: none;
}
.concept-back:hover { text-decoration: underline; }
.concept-detail-head { border-top: 4px solid var(--accent); }
.concept-section-title { margin: 1rem 0 .5rem; }
.concept-item { padding: .8rem .9rem; margin-bottom: .7rem; }
.concept-item .content-emoji { font-size: 1.6rem; text-align: left; padding: .3rem 0; }
.concept-item .content-symbols { justify-content: flex-start; padding: .3rem 0; }
.concept-item .content-guess { font-size: 1.05rem; text-align: left; margin: .35rem 0; }
.concept-item .content-drawing { max-width: 260px; margin: .35rem 0; }

/* profile: section heading with a trailing action */
.section-head { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: .3rem .6rem; }
.section-head h2 { margin: 0 0 .5rem; }

@media (min-width: 640px) {
    .concepts-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (min-width: 1100px) {
    /* only the concepts views widen; the timeline keeps its readable single column */
    .app-main:has(.concepts-grid) { max-width: 1240px; }
    .concepts-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

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

/* ---------- daily decode ---------- */
.daily-page { display: flex; flex-direction: column; gap: .9rem; }
.daily-header { display: flex; align-items: center; justify-content: space-between; gap: .6rem; flex-wrap: wrap; }
.daily-number { color: var(--muted); font-weight: 700; }
.daily-streak { white-space: nowrap; }
.daily-author-lead { font-size: 1.15rem; font-weight: 700; }
.daily-author-head { display: flex; align-items: center; gap: .7rem; margin-bottom: .3rem; }
.daily-attempts { display: flex; flex-direction: column; gap: .5rem; margin: .8rem 0 0; }
.daily-attempt-row {
    display: flex; justify-content: space-between; gap: .6rem;
    padding: .5rem .8rem; border: 2px solid var(--border); border-radius: 10px; font-weight: 600;
}
.daily-attempt-guess { min-width: 0; overflow-wrap: anywhere; }
.daily-attempt-row.attempt-correct { border-color: var(--success); color: var(--success-ink); }
.daily-attempt-row.attempt-close { border-color: var(--accent-warm); }
.daily-attempt-row.attempt-miss { color: var(--muted); }
.daily-guess-row { display: flex; gap: .6rem; margin-top: .8rem; }
.daily-guess-row .input { flex: 1; min-width: 0; }
.daily-finished { text-align: center; margin-top: .9rem; }
.daily-squares { font-size: 1.6rem; letter-spacing: .2rem; margin-bottom: .3rem; }
.daily-share { margin: .4rem 0; }

/* ---------- admin (moderation desk) ----------
   Data-dense but calm: the shared card language, no entrance animations, and every dangerous
   act behind a two-step confirm strip. All hues are theme variables; text sits on the tuned
   -ink/-text pairs so all three themes stay AA. */
.admin-page { display: flex; flex-direction: column; }
.admin-hero {
    display: flex; align-items: center; gap: .9rem;
    padding: 1rem 1.1rem; margin-bottom: .9rem;
    background: linear-gradient(135deg, var(--surface), var(--surface-inset));
    border: 1px solid var(--border); border-left: 6px solid var(--accent-warm);
    border-radius: var(--radius); box-shadow: var(--shadow);
}
.admin-hero-mark { font-size: 2.3rem; flex: 0 0 auto; }
.admin-hero-copy h1 { margin: 0 0 .15rem; font-size: 1.45rem; }
.admin-hero-copy p { margin: 0; max-width: 40rem; }

.admin-nav { display: flex; gap: .35rem; margin-bottom: 1rem; overflow-x: auto; padding: 2px; }
.admin-tab {
    display: inline-flex; align-items: center; gap: .35rem;
    min-height: 44px; padding: .3rem .9rem;
    border: 2px solid var(--border); border-radius: 999px;
    color: var(--text); text-decoration: none; font-weight: 600; white-space: nowrap;
}
.admin-tab:hover { background: var(--surface-inset); }
.admin-tab.active { border-color: var(--accent); color: var(--accent); background: var(--surface-inset); }

/* overview: tappable stat cards; open reports light up as the needs-attention signal */
.admin-stat { text-decoration: none; color: var(--text); display: block; }
.admin-stat:hover { border-color: var(--accent); }
.admin-stat-sub { display: block; font-size: .78rem; margin-top: .15rem; }
.admin-stat-attention { background: var(--warn-bg); border: 2px solid var(--accent-warm); }
.admin-stat-attention .stat-value, .admin-stat-attention .stat-label,
.admin-stat-attention .admin-stat-sub { color: var(--warn-text); }

/* shared card furniture */
.admin-card-head { display: flex; align-items: center; flex-wrap: wrap; gap: .4rem; margin-bottom: .45rem; }
.admin-card-head .act-time { margin-left: auto; }
.admin-action-row { display: flex; flex-wrap: wrap; gap: .5rem; margin-top: .5rem; }
.admin-inline-error { margin: .45rem 0; font-weight: 600; }
.admin-total { margin: 0 0 .6rem; }
.admin-empty { text-align: center; padding: 1.6rem 1rem; }
.admin-search { margin-bottom: .7rem; }

/* the two-step confirm strip; danger mood swaps the border, text stays on tuned inks */
.confirm-strip {
    display: flex; flex-wrap: wrap; align-items: center; gap: .5rem;
    margin-top: .5rem; padding: .6rem .7rem;
    background: var(--surface-inset); border: 2px solid var(--accent); border-radius: 10px;
}
.confirm-strip-danger { border-color: var(--danger); }
.confirm-strip-label { font-weight: 700; font-size: .9rem; flex: 1 1 100%; }
.confirm-strip-danger .confirm-strip-label { color: var(--danger-ink); }
.confirm-strip-reason { flex: 1 1 12rem; min-width: 0; background: var(--surface); }
.confirm-strip-actions { display: flex; gap: .4rem; }
.confirm-strip .btn-reject, .confirm-strip .btn-approve { background: var(--surface); }

/* reports queue — dense: the CONTENT + actor lead the card, the reason is a demoted muted
   quote, and tightened padding fits 4+ open reports on a 1080p screen */
.admin-report-card { border-left: 5px solid var(--act-rail, var(--border)); padding: .7rem .85rem; margin-bottom: .6rem; }
.admin-report-card .admin-card-head { margin-bottom: .3rem; }
.admin-report-preview { margin: .35rem 0; padding: .55rem .7rem; }
.admin-report-preview .admin-card-head { margin-bottom: .2rem; }
.admin-report-preview .content-emoji { font-size: 1.45rem; text-align: left; padding: .15rem 0; }
.admin-report-preview .content-symbols { justify-content: flex-start; padding: .15rem 0; }
.admin-report-preview .content-guess { font-size: 1.05rem; text-align: left; margin: .25rem 0; }
.admin-report-preview .content-drawing { max-width: 200px; margin: .25rem 0; }
.admin-report-gone { margin: .35rem 0; }
.admin-report-locator { margin: .1rem 0 .35rem; }
.admin-report-reason { margin: .3rem 0 0; font-size: .9rem; color: var(--muted); font-style: italic; overflow-wrap: anywhere; }
.admin-report-resolution { margin: .4rem 0 0; overflow-wrap: anywhere; }

/* visibility badges: Visible completes the Hidden/Removed set from the activity area */
.visibility-visible { border-color: var(--success); color: var(--success-ink); }

/* concepts corpus */
.admin-concept-text { font-size: 1.15rem; font-weight: 700; color: var(--text); overflow-wrap: anywhere; }
.admin-concept-text:hover { color: var(--accent); }
.admin-concept-meta { display: flex; align-items: center; flex-wrap: wrap; gap: .4rem; margin-bottom: .35rem; }
.admin-concept-meta .act-time { margin-left: auto; }
.admin-concept-counts { display: flex; flex-wrap: wrap; gap: .3rem .5rem; margin: .1rem 0 .2rem; }

/* concept detail */
.admin-detail-title { overflow-wrap: anywhere; }
.admin-detail-meta { margin: .3rem 0; }
.admin-decodings-toggle { margin-top: .5rem; }
.admin-detail-decoding { margin-top: .5rem; }
.admin-chains-hint { margin: -.3rem 0 .6rem; }
.admin-chain-entry { display: flex; flex-direction: column; gap: .1rem; margin: .4rem 0; }
.admin-chain-author { font-size: .8rem; font-weight: 600; }

/* users: one table that folds into cards below 768px via data-label pseudo-headers */
.admin-table-card { padding: .4rem .6rem; }
.admin-table { width: 100%; border-collapse: collapse; font-size: .92rem; }
.admin-table th, .admin-table td { text-align: left; padding: .5rem .4rem; border-bottom: 1px solid var(--border); vertical-align: middle; }
.admin-table tbody tr:last-child td { border-bottom: none; }
.admin-user-name { display: inline-flex; align-items: center; gap: .4rem; margin-right: .4rem; overflow-wrap: anywhere; }
.admin-row-actions { white-space: nowrap; }
.admin-row-actions .btn { margin-right: .35rem; }
.admin-user-hint { display: block; font-size: .78rem; margin-top: .2rem; white-space: normal; }
.admin-confirm-row td { border-bottom: 1px solid var(--border); }

/* invites: mint strip + the same folding table; codes read aloud, so they render monospace */
.admin-invites-generate { display: flex; align-items: center; gap: .6rem; margin-bottom: .7rem; }
.admin-invites-count { flex: 0 1 6.5rem; min-width: 4.5rem; }
.admin-invite-code {
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-weight: 700; letter-spacing: .05em; white-space: nowrap; margin-right: .4rem;
}
.admin-invite-code-dead { color: var(--muted); }
.admin-invite-new { border-color: var(--accent); color: var(--accent); }
.admin-invite-copied { font-size: .8rem; font-weight: 600; color: var(--success-ink); white-space: nowrap; }

@media (max-width: 767.98px) {
    .admin-table, .admin-table tbody, .admin-table tr, .admin-table td { display: block; }
    .admin-table thead { display: none; }
    .admin-table tr {
        border: 1px solid var(--border); border-radius: 10px;
        padding: .5rem .6rem; margin-bottom: .6rem;
    }
    .admin-table td { border-bottom: none; padding: .25rem 0; }
    .admin-table td::before {
        content: attr(data-label);
        display: block;
        font-size: .72rem; font-weight: 700; text-transform: uppercase; letter-spacing: .04em;
        color: var(--muted);
    }
    .admin-table td:not([data-label])::before { content: none; }
    .admin-row-actions { white-space: normal; }
    .admin-confirm-row { padding-top: 0; }
}

@media (min-width: 1100px) {
    .app-main:has(.admin-page) { max-width: 1240px; }
    .admin-stat-grid .stat-card { flex-basis: 200px; }
}

/* ---------- tutorial (how to play) ----------
   A guided, stepped walkthrough where the interactive element is the hero of every step.
   Progress dots + Back/Next; each hue is a theme variable, text sits on the tuned AA pairs.
   All entrance animation switches off under prefers-reduced-motion below. */
.tutorial-page { display: flex; flex-direction: column; max-width: 640px; margin: 0 auto; width: 100%; }
.tutorial-header { text-align: center; margin-bottom: .4rem; }
.tutorial-header h1 { margin-bottom: .3rem; }

.tutorial-progress { display: flex; justify-content: center; gap: .1rem; padding: .3rem 0 .6rem; }
/* the button is a real 44×44 target; the small dot is drawn by ::before, so the visual stays quiet */
.tutorial-dot {
    position: relative; width: 44px; height: 44px; padding: 0;
    border: none; border-radius: 50%; background: transparent; cursor: pointer;
}
.tutorial-dot::before {
    content: ""; position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
    width: 14px; height: 14px; box-sizing: border-box;
    border: 2px solid var(--muted); border-radius: 50%; background: transparent;
}
.tutorial-dot:disabled { cursor: not-allowed; }
.tutorial-dot:disabled::before { border-color: var(--border); }
.tutorial-dot-done::before { border-color: var(--success); background: var(--success); }
.tutorial-dot-active::before {
    border-color: var(--accent); background: var(--accent);
    transform: translate(-50%, -50%) scale(1.25);
}

.tutorial-step { padding: 1.1rem 1rem; }
.tutorial-step-title { text-align: center; margin-bottom: .7rem; }
.tutorial-step-title:focus { outline: none; } /* programmatic focus target (tabindex=-1), not interactive */
.tutorial-copy { text-align: center; max-width: 34rem; margin: .35rem auto .8rem; }

/* step 1 — the telephone-flow diagram; segments pop in staggered (≤1s total).
   Each arrow is welded to the node it points at (.tutorial-flow-seg), so a wrap break can
   never leave a dangling arrow pointing into empty space at a row's end. */
.tutorial-flow { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: .35rem; margin: 1rem 0; }
.tutorial-flow-seg {
    display: inline-flex; align-items: center; gap: .35rem;
    animation: tutorial-pop .4s ease backwards;
}
.tutorial-flow-node { display: flex; flex-direction: column; align-items: center; gap: .1rem; min-width: 3.4rem; }
.tutorial-flow-icon { font-size: 1.9rem; }
.tutorial-flow-label { font-size: .72rem; font-weight: 700; color: var(--muted); text-transform: uppercase; letter-spacing: .04em; }
.tutorial-flow-arrow { color: var(--muted); font-weight: 800; font-size: 1.15rem; }
.tutorial-flow-seg:nth-child(2) { animation-delay: .15s; }
.tutorial-flow-seg:nth-child(3) { animation-delay: .3s; }
.tutorial-flow-seg:nth-child(4) { animation-delay: .45s; }
.tutorial-flow-seg:nth-child(5) { animation-delay: .6s; }
@keyframes tutorial-pop { from { opacity: 0; transform: translateY(8px) scale(.8); } }

/* shared step furniture */
.tutorial-concept, .tutorial-reveal-concept { margin: .6rem 0; padding: 1rem .8rem; }
.tutorial-concept .chip { margin-top: .3rem; }
.tutorial-example-row, .tutorial-guess-actions, .tutorial-verdict-row { text-align: center; margin: .5rem 0; }
.tutorial-example, .tutorial-reference, .tutorial-ana { text-align: center; margin: .6rem 0; }
.tutorial-example .content-emoji, .tutorial-reference .content-emoji { padding: .3rem; }
.tutorial-gate-hint { text-align: center; margin: .7rem 0 0; }
.tutorial-done { text-align: center; font-weight: 700; color: var(--success-ink); margin: .7rem 0 0; }
.tutorial-protip { text-align: center; margin: .5rem 0 0; }
.tutorial-canvas-wrap { margin: .6rem 0; }
/* sample drawings render compact inside the tutorial shell */
.tutorial-ana .content-drawing, .tutorial-chain-entry .content-drawing { max-width: 240px; }

/* the sample chain (steps 5 and 6) */
.tutorial-mini-chain, .tutorial-chain { display: flex; flex-direction: column; gap: .5rem; margin: .6rem 0; }
.tutorial-chain-entry { text-align: center; }
.tutorial-chain-entry .content-emoji { padding: .3rem; }
.tutorial-chain-entry .content-guess { margin: .3rem 0; }

/* step 6 — mock blind vote + mini podium */
.tutorial-vote { text-align: center; margin: .8rem 0; }
.tutorial-vote-label { font-weight: 600; }
.tutorial-vote .vote-chips { justify-content: center; }
.tutorial-podium { text-align: center; }
.tutorial-podium .podium-blocks { margin: .9rem 0 .2rem; }
.tutorial-podium .podium-rank-1 .podium-bar { height: 64px; }
.tutorial-podium .podium-rank-2 .podium-bar { height: 46px; }
.tutorial-podium .podium-rank-3 .podium-bar { height: 32px; }

/* step 7 — satellite cards + adaptive CTA */
.tutorial-satellites { display: grid; grid-template-columns: 1fr; gap: .7rem; margin: .8rem 0; }
.tutorial-satellite {
    display: flex; flex-direction: column; gap: .15rem; margin: 0;
    text-align: center; text-decoration: none; color: var(--text);
}
.tutorial-satellite:hover { border-color: var(--accent); }
.tutorial-satellite h3 { margin: .1rem 0; }
.tutorial-satellite-icon { font-size: 1.8rem; }
.tutorial-cta { text-align: center; margin: .8rem 0 0; }

/* Back/Next + skip */
.tutorial-nav { display: grid; grid-template-columns: 1fr 1fr; gap: .6rem; align-items: center; }
.tutorial-nav .tutorial-skip { grid-column: 1 / -1; justify-self: center; }
/* text-styled but a real ≥44px action — "Skip tutorial" / "I'll skip drawing" are genuine actions */
.link-btn {
    display: inline-flex; align-items: center; justify-content: center;
    min-height: 44px; padding: 0 .4rem;
    background: none; border: none; cursor: pointer;
    color: var(--accent); font-weight: 600; font-size: .9rem; text-decoration: underline;
}

/* home entry points */
.hero .hero-cta { margin-top: .9rem; }
.how-to-more { margin: .6rem 0 0; font-weight: 600; }

@media (min-width: 640px) {
    .tutorial-satellites { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

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