/* === Main page styles ================================================
   Extracted from the inline <style> block of index.html. Pairs with
   css/theme.css for design tokens and the per-game stylesheets under
   css/games/. Keep section banners — they map directly to the
   regions of the legacy inline block so diffs against the backup stay
   trivially reviewable.
   ====================================================================== */
/* === Theme tokens live in /css/theme.css ===================
   Light theme + dark theme variants are defined there. Page-
   level overrides (none today) would go here, after the linked
   stylesheet, so cascade order keeps the page in control of
   its own surface if it ever needs to override a token. */

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

/* Initial-load fade-in: suppresses the flash of unstyled / empty
   layout (empty family-nav, empty panels, stale default character,
   mobile col-tabs leaking onto desktop before panels.js injects CSS).
   Covers everything between the header and the SEO content.
   Removed once selectFamily has loaded the intended character.
   A fallback @keyframes animation clears the veil after 3s in case JS
   stalls or throws, so the page is never permanently hidden. */
.family-nav,
.col-tabs,
.game-stage {
    transition: opacity 0.25s ease;
}
body.loading .family-nav,
body.loading .col-tabs,
body.loading .game-stage {
    opacity: 0;
    pointer-events: none;
    animation: loading-veil-fallback 0s linear 3s forwards;
}
@keyframes loading-veil-fallback {
    to { opacity: 1; pointer-events: auto; }
}

body {
    font-family: 'Segoe UI', system-ui, -apple-system, sans-serif;
    background: var(--bg-outer);
    color: var(--text);
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: 1.5rem 1rem;
    transition: background 0.3s, color 0.3s;
    overflow-x: hidden;
}

.page-content {
    width: 100%;
    max-width: 1440px;
    background: transparent;
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: 0;
}

.top-section {
    width: 100%;
    background: transparent;
    /* Vertical padding only — horizontal padding removed so the
       header content's outer edges line up with the practice
       area's outer edges. Body provides the page-level inset. */
    padding: 0.8rem 0 0.5rem;
    display: flex;
    flex-direction: column;
    align-items: center;
}

/* SEO content section sits directly on the page paper — no
   panel background, no shadow. Continuous warm cream from
   header through practice area through SEO content. */
.seo-wrapper {
    width: 100%;
    max-width: 1440px;
    background: transparent;
    /* Match top-section: vertical padding only, no horizontal
       inset, so all three sections (header / practice / SEO)
       share the same outer edges. */
    padding: 0 0 1rem;
    margin: 10px auto 0;
}

@media (min-width: 1480px) {
    .seo-wrapper {
        border-radius: 0 0 12px 12px;
    }
}

/* Header CSS (site-header / brand-* / nav / lang-switcher /
   theme-toggle / switch-link) lives in /js/header.js's
   injectHeaderCSS(). Removed from inline to keep one source. */

.family-nav,
.char-row,
.card-area {
    user-select: none;
    -webkit-user-select: none;
}

/* === SEO Content === */
/* === Mobile portrait: fit everything above divider in one screen === */
@media (max-width: 600px) {
    body {
        padding: 0.8rem 0.5rem;
    }

    .page-content {
        padding: 0.8rem 0.5rem 0;
    }

    h1 { font-size: 1.2rem; }

    .ad-slot {
        margin: 0.5rem 0;
    }

    .family-nav {
        padding: 4px 0 8px;
        gap: 4px;
        /* Mobile: tab padding 8px + smaller font ≈ 35px */
        min-height: 35px;
    }

    .family-tab {
        padding: 4px 8px;
        font-size: 0.75rem;
    }

    .char-row {
        gap: 4px;
        margin-bottom: 0.6rem;
        padding-bottom: 0.5rem;
    }

    .char-mini {
        width: 42px;
        height: 52px;
    }

    .char-mini .char { font-size: 1.1rem; }
    .char-mini .romaji { font-size: 0.55rem; }


    .info-panel-top .romaji { font-size: 1.2rem; }
    .pronunciation-tip { font-size: 0.7rem; }

    /* Carousel mobile overrides in /js/carousel.js */

    /* below-card-row removed — stroke count in carousel */

    .card-actions {
        top: 4px;
        right: 4px;
        gap: 3px;
    }

    .card-btn {
        width: 26px;
        height: 26px;
    }

    .section-divider {
        margin-top: 1rem;
    }
}

/* Extra small phones */
@media (max-width: 600px) and (max-height: 700px) {
    .ad-slot { display: none; }

    /* Carousel extra-small overrides in /js/carousel.js */

    /* below-card-row removed */
}

.section-divider {
    width: 100%;
    max-width: 1400px;
    border: none;
    border-top: 1px solid var(--subtle-border);
    margin: 2rem auto 0;
}

.seo-content {
    width: 100%;
    max-width: 1400px;
    margin: 1.5rem auto 1rem;
    /* Horizontal padding removed so the "Learn Hiragana" heading
       and body text line up with the practice area's left/right
       edges (also at 1400px max). */
    padding: 1rem 0 0;
    color: var(--text-muted);
    font-size: 0.9rem;
    line-height: 1.7;
}

.seo-content h2 {
    color: var(--heading);
    font-size: 1.3rem;
    margin-bottom: 0.8rem;
}

.seo-content h3 {
    color: var(--text);
    font-size: 1rem;
    margin-top: 1.5rem;
    margin-bottom: 0.5rem;
}

.seo-content p {
    margin-bottom: 0.8rem;
}

.seo-content ol {
    padding-left: 1.2rem;
    margin-bottom: 0.8rem;
}

.seo-content li {
    margin-bottom: 0.4rem;
}

.seo-content details {
    margin-bottom: 0.5rem;
    border: 1px solid var(--subtle-border);
    border-radius: 8px;
    padding: 0.6rem 0.8rem;
}

.seo-content summary {
    cursor: pointer;
    color: var(--text);
    font-weight: 600;
    font-size: 0.9rem;
}

.seo-content details[open] summary {
    margin-bottom: 0.4rem;
}

.seo-content details p {
    margin-bottom: 0;
}

.site-footer {
    margin-top: 2rem;
    padding: 1rem;
    text-align: center;
    font-size: 0.8rem;
    color: var(--footer-color);
}

.site-footer a {
    color: var(--footer-link);
    text-decoration: none;
}

.site-footer a:hover {
    color: var(--text-muted);
}

/* === Family Navigation (horizontal carousel) === */
.family-nav {
    display: flex;
    gap: 6px;
    overflow-x: auto;
    width: 100%;
    max-width: 1400px;
    margin-bottom: 0;
    padding: 8px 0 8px;
    /* Reserve space for the tabs so the toolbar below doesn't
       jump down when JS finishes populating the carousel. Height
       = tab padding (12px) + line-height (~17px) + border (2px)
       + container padding (16px) ≈ 47px. */
    min-height: 47px;
    border-bottom: none;
    scrollbar-width: none;
    -ms-overflow-style: none;
    user-select: none;
    -webkit-user-select: none;
    cursor: grab;
    -webkit-overflow-scrolling: touch;
    box-sizing: border-box;
}

.family-nav:active {
    cursor: grabbing;
}

.family-nav::-webkit-scrollbar {
    display: none;
}

.family-tab {
    padding: 6px 12px;
    border-radius: 8px;
    background: transparent;
    border: 1px solid var(--container-border);
    color: var(--text-muted);
    font-size: 0.85rem;
    font-weight: 600;
    cursor: pointer;
    transition: all 0.2s;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    flex-shrink: 0;
    white-space: nowrap;
}

.family-tab:hover {
    background: var(--accent-hover);
    color: var(--text-muted);
}

.family-tab.active {
    background: transparent;
    border-color: var(--accent);
    color: var(--accent);
}

.family-tab.learned {
    color: var(--green);
    border-color: var(--green-border);
}

.family-tab.learned.active {
    background: transparent;
    border-color: var(--green);
    color: var(--green);
}

.family-tab.review {
    color: var(--orange);
    border-color: var(--orange-border);
}

.family-tab.review.active {
    background: transparent;
    border-color: var(--orange);
    color: var(--orange);
}

/* === Character Row (small cards) === */
.char-row {
    display: flex;
    gap: 8px;
    justify-content: center;
    margin-top: 6px;
    margin-bottom: 0.5rem;
    padding-bottom: 0;
    flex-wrap: wrap;
}

.char-mini {
    width: 52px;
    height: 64px;
    border-radius: 12px;
    background: transparent;
    border: 1px solid var(--container-border);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: all 0.2s;
}

@media (hover: hover) {
    .char-mini:hover {
        background: var(--accent-hover);
        border-color: var(--accent-border);
    }
}

.char-mini.active {
    background: transparent;
    border-color: var(--accent);
}

.char-mini .char {
    font-family: 'Noto Sans JP', sans-serif;
    font-size: 1.4rem;
    color: var(--text);
    line-height: 1;
    transition: opacity 0.3s, font-size 0.3s;
}

.char-mini.active .char {
    color: var(--heading);
}

.char-mini .romaji {
    font-size: 0.65rem;
    color: var(--text-faint);
    margin-top: 2px;
    transition: opacity 0.3s, font-size 0.3s, color 0.3s;
}

.char-mini.active .romaji {
    color: var(--accent);
}

/* Study mode: hide hiragana, show romaji prominently */
body.study-active .char-mini .char {
    font-size: 0;
    opacity: 0;
}

body.study-active .char-mini .romaji {
    font-size: 1rem;
    color: var(--text-muted);
    margin-top: 0;
}

body.study-active .char-mini.active .romaji {
    color: var(--accent);
}

body.study-active .info-panel-top .romaji {
    /* Already romaji — keep visible */
}

/* Keep pronunciation tip visible in study mode */

body.study-active .char-details {
    display: none;
}

body.study-active .card-mastery .level-name {
    color: var(--green);
    transition: color 0.3s;
}

/* === Card area wrapper === */
.game-stage {
    position: relative;
    width: 100%;
    display: flex;
    justify-content: center;
}

.card-area {
    display: flex;
    flex-direction: column;
    align-items: center;
    width: 100%;
    /* Match the 1400px max-width used by .site-header,
       .family-nav, and .seo-content so the practice area's
       outer edges line up with the header and SEO content. */
    max-width: 1400px;
    padding: 6px 0 0;
    position: relative;
    z-index: 1;
    opacity: 1;
    transform: translateX(0);
    /* Compound transition — opacity + slide together so the
       card-area visibly "exits stage left" when .hidden is added.
       Spatial cue matches the carousel's left/right vocabulary
       (right = forward), so leaving via the left reads as
       "moving past this activity." */
    transition: opacity 0.6s ease, transform 0.6s ease;
    user-select: none;
    -webkit-user-select: none;
    -webkit-touch-callout: none;
    -webkit-tap-highlight-color: transparent;
}

.card-area.hidden {
    opacity: 0;
    transform: translateX(-40px);
    pointer-events: none;
    z-index: 0;
}

/* Info bar above card */
.carousel-info-panel {
    position: relative;
    width: 100%;
    max-width: 100%;
    margin: 0 auto;
    background: transparent;
    border-radius: 8px;
    border: none;
    padding: 8px 12px 8px;
    display: flex;
    flex-direction: column;
    align-items: center;
    /* Fixed gap between the char-info widget and the tile row.
       (Previously used space-evenly + flex:1, but distributing free
       space shifts the tiles whenever anything above changes height —
       e.g. Free Hand vs Recall — even by a pixel.) */
    justify-content: flex-start;
    gap: 10px;
}

/* Char-info widget — single fixed-height row that holds either the
   static identity (romaji · tip) or the recall feedback flash, plus
   the absolutely-positioned stroke-count badge. The reserved height
   keeps everything below from shifting when state swaps. */
.info-panel-top {
    position: relative;
    width: 100%;
    height: 2.4em;
    border: 1px dashed var(--accent);
    border-radius: 6px;
}
.char-info-static,
.char-info-feedback {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    white-space: nowrap;
}
.char-info-feedback {
    display: none;
    font-weight: 700;
    letter-spacing: 0.03em;
}
.char-info-widget.feedback .char-info-static { display: none; }
.char-info-widget.feedback .char-info-feedback { display: flex; }

.info-panel-top .romaji {
    font-size: 1.4rem;
    color: var(--accent);
    font-weight: 700;
    letter-spacing: 0.05em;
}

.info-panel-top .separator {
    color: var(--text-faint);
    font-size: 0.85rem;
}

.pronunciation-tip {
    font-size: 0.8rem;
    color: var(--text-faint);
    font-style: italic;
}

/* Family cards inside the panel */
.carousel-info-panel .char-row {
    margin: 0;
    padding: 0;
    gap: 6px;
}

.stroke-count-btn {
    position: absolute;
    top: 50%;
    right: 8px;
    transform: translateY(-50%);
    width: 24px;
    height: 24px;
    border-radius: 50%;
    border: 1px solid var(--subtle-border);
    background: var(--subtle-bg);
    color: var(--accent);
    font-size: 0.75rem;
    font-weight: 700;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: all 0.2s;
    z-index: 2;
}

.stroke-count-btn:hover {
    background: var(--accent-bg);
    border-color: var(--accent-border);
}

.stroke-tooltip {
    display: none;
    position: absolute;
    top: 50%;
    right: 36px;
    transform: translateY(-50%);
    background: var(--bg);
    border: 1px solid var(--subtle-border);
    border-radius: 6px;
    box-shadow: 0 4px 12px rgba(0,0,0,0.1);
    padding: 6px 10px;
    font-size: 0.75rem;
    color: var(--text);
    white-space: nowrap;
    z-index: 10;
}

.stroke-tooltip.visible {
    display: block;
}

/* Score + mode row */
.card-status {
    width: 100%;
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 6px;
    padding: 0 4px;
    min-height: 24px;
}

.mode-label {
    display: none;
}

.mode-label.visible { display: none; }

/* Old card button styles removed — toolbar handles positioning */
.mode-label.trace { color: var(--orange); }
.mode-label.freehand { color: var(--accent); }
.mode-label.study { color: var(--green); }


/* === Main Card — just the canvas === */
.card {
    width: 290px;
    height: 290px;
    background: var(--card-bg);
    border-radius: 20px;
    box-shadow: var(--card-shadow);
    display: flex;
    align-items: center;
    justify-content: center;
    position: relative;
    overflow: hidden;
    cursor: pointer;
    transition: transform 0.3s ease, box-shadow 0.3s ease;
    /* pan-y so vertical page scrolls aren't blocked when the user
       drags from white space inside the canvas. The canvas's own
       pointerdown handler upgrades to full capture only when the
       touch lands on the character. */
    touch-action: pan-y;
    user-select: none;
    -webkit-user-select: none;
}

.card:hover {
    transform: translateY(-3px);
    box-shadow: var(--card-shadow-hover);
}

/* Guide lines handled by .carousel-grid */

.canvas-container {
    width: 100%;
    height: 100%;
    position: relative;
    touch-action: pan-y;
}

.canvas-container canvas {
    width: 100%;
    height: 100%;
    /* Allow vertical page scroll when the user touches empty
       white space. The pointerdown handler upgrades this to
       full capture only when the touch lands on the character. */
    touch-action: pan-y;
    -webkit-touch-callout: none;
}

.card-wrapper {
    display: flex;
    flex-direction: column;
    align-items: center;
    width: 100%;
    position: relative;
    gap: 6px;
    padding-bottom: 6px;
    flex: 1;
    touch-action: pan-y;
}

/* Canvas navigation row — full width, nav buttons flank the canvas */
.carousel-nav-row {
    display: flex;
    touch-action: pan-y;
    align-items: stretch;
    width: 100%;
}

.canvas-nav {
    flex: 0 0 36px;
    display: flex;
    align-items: center;
    justify-content: center;
    align-self: stretch;
    /* Quiet nav — just the arrow glyph, no panel chrome. Designer's
       Tegami treatment: transparent background, faint ink color,
       accent on hover only. */
    background: transparent;
    border: none;
    color: var(--text-faint);
    font-size: 1.8rem;
    font-weight: 400;
    cursor: pointer;
    user-select: none;
    -webkit-user-select: none;
    transition: color 0.15s, background 0.15s;
}
body.dark .canvas-nav {
    background: transparent;
}

.canvas-nav-left,
.canvas-nav-right {
    border-radius: 4px;
}

@media (hover: hover) {
    .canvas-nav:hover {
        color: var(--accent);
        background: var(--accent-bg);
    }
}

.canvas-nav:active {
    color: var(--accent);
    background: var(--accent-hover);
}

/* Recall mode: character progression is SRS-driven, not user-driven —
   grey out the canvas nav arrows and the character mini-tiles to
   prevent manual override. */
body.study-active .canvas-nav {
    opacity: 0.35;
    pointer-events: none;
    cursor: not-allowed;
}
body.study-active .char-mini {
    pointer-events: none;
    cursor: not-allowed;
}

@media (max-width: 600px) {
    .canvas-nav {
        flex: 0 0 30px;
        font-size: 1.5rem;
    }
    .carousel-info-panel { padding-top: 6px; }
}

/* === Carousel === */
/* Carousel CSS injected by /js/carousel.js */

.card.shake-wrong {
    animation: cardShake 0.4s ease-out;
    box-shadow: 0 0 0 3px var(--red), var(--card-shadow);
}
@keyframes cardShake {
    0% { transform: translateX(0); }
    20% { transform: translateX(-6px); }
    40% { transform: translateX(5px); }
    60% { transform: translateX(-3px); }
    80% { transform: translateX(2px); }
    100% { transform: translateX(0); }
}

.card.glow-warn {
    box-shadow: 0 0 0 3px var(--orange), var(--card-shadow);
    transition: box-shadow 0.8s ease-out;
}

.stroke-feedback {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    font-size: 1.2rem;
    font-weight: 700;
    letter-spacing: 0.05em;
    pointer-events: none;
    opacity: 0;
    transition: opacity 0.3s;
    z-index: 10;
    text-shadow: 0 1px 4px rgba(0,0,0,0.15);
}
/* Recall surfaces feedback in the romaji+tip line below the canvas
   instead of overlaying the writing area. Other modes still use the
   centered overlay. */
body.study-active .stroke-feedback { display: none; }

.freehand-score {
    position: absolute;
    top: 8px;
    right: 12px;
    font-size: 0.85rem;
    font-weight: 700;
    letter-spacing: 0.03em;
    pointer-events: none;
    opacity: 0;
    transition: opacity 0.3s;
    z-index: 10;
    text-shadow: 0 1px 3px rgba(0,0,0,0.15);
}

/* Below card: label + mastery */
.card-below {
    display: flex;
    align-items: center;
    justify-content: center;
    margin-top: 14px;
}




/* Action buttons below card */
/* Toolbar above carousel frame */
.carousel-toolbar {
    width: 100%;
    max-width: 100%;
    margin: 0 auto;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 4px 8px;
    background: var(--ink-fill);
    color: var(--on-ink);
    border-radius: 8px;
    border: 1px solid var(--ink-fill);
    box-shadow: 0 2px 8px rgba(0,0,0,0.12);
    position: relative;
    z-index: 5;
    min-height: 38px;
    box-sizing: border-box;
}

/* Default icon-button colors inside the dark toolbar — light icons on
   dark fill. Specific buttons (play, hint, recall.active) override. */
.carousel-toolbar .flag-btn { color: var(--on-ink-muted); }
.carousel-toolbar .flag-btn.flagged { color: var(--accent); opacity: 1; }
.carousel-toolbar .play-btn { background: rgba(255,255,255,0.08); border-color: var(--on-ink-border); color: var(--on-ink); }
.carousel-toolbar .play-btn:hover { background: var(--accent); color: #fff; border-color: var(--accent); }
.carousel-toolbar button.hint-btn { background: rgba(80,216,144,0.15); border-color: var(--green-border); color: var(--green); }
.carousel-toolbar button.opacity-trigger { background: rgba(255,255,255,0.08); border-color: var(--on-ink-border); color: var(--on-ink); }
.carousel-toolbar button.opacity-trigger:hover { background: var(--accent); color: #fff; border-color: var(--accent); }

.toolbar-left {
    position: absolute;
    left: 8px;
    display: flex;
    align-items: center;
    gap: 6px;
}

.toolbar-right {
    position: absolute;
    right: 8px;
    display: flex;
    align-items: center;
    gap: 6px;
}

.toolbar-btn {
    padding: 5px 16px;
    border-radius: 6px;
    border: 1px solid var(--subtle-border);
    background: var(--subtle-bg);
    color: var(--text);
    font-size: 0.82rem;
    font-weight: 700;
    cursor: pointer;
    transition: all 0.2s;
    white-space: nowrap;
    text-decoration: none;
    display: flex;
    align-items: center;
    gap: 4px;
}

@media (hover: hover) {
    .toolbar-btn:hover {
        background: var(--accent-bg);
        color: var(--accent);
        border-color: var(--accent-border);
    }
}
.toolbar-btn:active {
    background: var(--accent-bg);
    color: var(--accent);
}

.toolbar-arrow { font-size: 0.55rem; opacity: 0.6; }

/* Dropdown */
.toolbar-dropdown { position: relative; }

.toolbar-dropdown-panel {
    display: none;
    position: absolute;
    top: calc(100% + 4px);
    left: 0;
    background: var(--bg);
    border: 1px solid var(--subtle-border);
    border-radius: 8px;
    box-shadow: 0 8px 24px rgba(0,0,0,0.12);
    min-width: 160px;
    z-index: 100;
    overflow: hidden;
}

.toolbar-dropdown.open .toolbar-dropdown-panel { display: block; }

.toolbar-dropdown-item {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 10px 14px;
    color: var(--text);
    text-decoration: none;
    font-size: 0.8rem;
    font-weight: 500;
    border: none;
    background: none;
    width: 100%;
    cursor: pointer;
    transition: background 0.15s;
}

.toolbar-dropdown-item:hover { background: var(--accent-bg); color: var(--accent); }

.toolbar-dropdown-item #practice-sheet-char {
    font-family: 'Noto Sans JP', sans-serif;
    font-size: 1rem;
}

/* Mode toggle */
/* Segmented control housing all three modes (Trace | Free Hand | Recall).
   overflow:visible so the recall nudge popover isn't clipped — corners
   are rounded per-child instead. */
.mode-toggle {
    display: flex;
    border-radius: 8px;
    border: 1px solid var(--on-ink-border);
    box-shadow: 0 1px 4px rgba(0,0,0,0.15);
}

.mode-toggle-btn {
    padding: 5px 16px;
    border: none;
    /* Recessed dark tint so inactive buttons read as distinct
       surfaces against the lighter dark toolbar fill. */
    background: rgba(0, 0, 0, 0.22);
    color: var(--on-ink-muted);
    font-size: 0.82rem;
    font-weight: 700;
    cursor: pointer;
    transition: all 0.2s;
    white-space: nowrap;
    font-family: inherit;
}

/* Round outer corners only on edge children. The recall-wrap span is
   the rightmost child, so its inner button gets the right radius. */
.mode-toggle > :first-child,
.mode-toggle > :first-child > .mode-toggle-btn {
    border-top-left-radius: 7px;
    border-bottom-left-radius: 7px;
}
.mode-toggle > :last-child,
.mode-toggle > :last-child > .mode-toggle-btn {
    border-top-right-radius: 7px;
    border-bottom-right-radius: 7px;
}

@media (hover: hover) { .mode-toggle-btn:hover { color: var(--on-ink); background: var(--on-ink-hover); } }
.mode-toggle-btn.active { background: var(--accent); color: white; box-shadow: 0 2px 6px rgba(179,42,42,0.4); }

.recall-wrap { position: relative; display: inline-flex; }
.recall-btn-label { position: relative; z-index: 1; }

/* Tagline under the mode-toggle row explaining the progression */
.mode-tagline {
    text-align: center;
    font-size: 0.72rem;
    color: var(--text-faint);
    margin: 4px 0 0;
    line-height: 1.3;
    font-style: italic;
}
/* In Recall mode the tagline is repurposed for the per-character
   prompt instead of being hidden, so the canvas doesn't jump. */
body.study-active .mode-tagline { color: var(--accent); font-style: italic; }

/* Shared sizing for the three single-icon toolbar buttons so the
   toolbar layout stays stable regardless of which is active.
   Higher-specificity (button + class) beats the .toolbar-btn padding
   rule at the mobile breakpoint without resorting to !important. */
button.play-btn,
button.hint-btn,
button.opacity-trigger {
    width: 28px;
    height: 28px;
    min-width: 28px;
    padding: 0;
    box-sizing: border-box;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    font-size: 0.85rem;
    line-height: 1;
    gap: 0;
}

/* Single shared slot for the three context buttons. Whichever button
   is active for the current mode occupies this position; the others
   are visibility:hidden but stay in the grid cell. */
.toolbar-action-slot {
    display: grid;
    width: 28px;
    height: 28px;
}
.toolbar-action-slot > * {
    grid-area: 1 / 1;
}

.play-btn {
    background: var(--accent-bg);
    border-color: var(--accent-border);
    color: var(--accent);
}
.play-btn:hover {
    background: var(--accent);
    color: white;
    border-color: var(--accent);
}
/* Hide-but-keep-space so hiding Play in practice modes doesn't
   shift the rest of the toolbar. */
.play-btn.hidden {
    visibility: hidden;
}

/* Exercise dropdown — quick-launch a game without going through Recall */
.exercise-dropdown {
    position: relative;
}
.exercise-trigger {
    font-size: 0.75rem;
    padding: 4px 8px;
    line-height: 1;
    /* Match the recessed dark tint used on the mode-toggle buttons
       so the right-side toolbar buttons read as distinct surfaces. */
    background: rgba(0, 0, 0, 0.22);
    border-color: var(--on-ink-border);
    color: var(--on-ink);
}
@media (hover: hover) {
    .exercise-trigger:hover {
        background: var(--on-ink-hover);
        border-color: var(--on-ink);
        color: var(--on-ink);
    }
}
.exercise-dropdown-panel {
    display: none;
    position: absolute;
    top: calc(100% + 6px);
    right: 0;
    background: var(--bg);
    border: 1px solid var(--subtle-border);
    border-radius: 8px;
    box-shadow: 0 8px 24px rgba(0,0,0,0.12);
    padding: 6px;
    z-index: 100;
    min-width: 120px;
    flex-direction: column;
    gap: 4px;
}
.exercise-dropdown.open .exercise-dropdown-panel {
    display: flex;
}
.exercise-option {
    background: transparent;
    border: 1px solid transparent;
    border-radius: 6px;
    padding: 6px 10px;
    font-size: 0.8rem;
    color: var(--text);
    cursor: pointer;
    text-align: left;
    font-family: inherit;
}
@media (hover: hover) {
    .exercise-option:hover {
        background: var(--accent-bg);
        color: var(--accent);
    }
}
/* Recall mode greys out the Exercise dropdown — visible but disabled. */
body.study-active .exercise-dropdown {
    opacity: 0.35;
    pointer-events: none;
}

/* Hint button — rendered as a "?" icon, hidden-but-spaced when the
   current mode doesn't support hints. */
.hint-btn {
    visibility: hidden;
    background: var(--green-bg);
    border-color: var(--green-border);
    color: var(--green);
}

.hint-btn:hover {
    background: var(--green);
    color: white;
    border-color: var(--green);
}

.hint-btn.visible {
    visibility: visible;
}

.flag-btn {
    font-size: 1rem;
    line-height: 1;
    opacity: 0.4;
    transition: all 0.2s;
}

.flag-btn:hover {
    opacity: 0.7;
}

.flag-btn.flagged {
    opacity: 1;
    color: var(--red);
}

/* Stroke color/opacity picker — round indicator + popover panel */
.color-picker-wrap {
    position: relative;
    display: inline-flex;
    align-items: center;
    margin-left: 4px;
}
.color-picker-btn {
    width: 28px;
    height: 28px;
    padding: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background: transparent;
    border: 1px solid var(--on-ink-border);
}
.color-picker-btn:hover { background: var(--on-ink-hover); }
.color-picker-swatch {
    width: 16px;
    height: 16px;
    border-radius: 50%;
    background: conic-gradient(#e74c3c, #f39c12, #2ecc71, #1abc9c, #3498db, #9b59b6, #e74c3c);
    border: 1px solid rgba(0,0,0,0.18);
    box-shadow: inset 0 0 0 1px rgba(255,255,255,0.18);
}
.color-picker-panel {
    position: absolute;
    top: calc(100% + 8px);
    left: 0;
    min-width: 220px;
    background: var(--bg);
    color: var(--text);
    border: 1px solid var(--subtle-border);
    border-radius: 10px;
    padding: 10px;
    box-shadow: 0 12px 36px rgba(0,0,0,0.18);
    z-index: 200;
    display: none;
}
.color-picker-panel.open { display: block; }
.color-multi-btn {
    display: block;
    width: 100%;
    padding: 6px 10px;
    margin-bottom: 8px;
    border-radius: 6px;
    background: transparent;
    border: 1px solid var(--subtle-border);
    color: var(--text);
    font-size: 0.78rem;
    font-weight: 700;
    cursor: pointer;
    background-image: linear-gradient(90deg, #e74c3c, #f39c12, #2ecc71, #3498db, #9b59b6);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
}
.color-multi-btn:hover { border-color: var(--accent); }
.color-multi-btn.active {
    border-color: var(--accent);
    box-shadow: 0 0 0 2px var(--accent-bg);
}
.color-swatch-grid {
    display: grid;
    grid-template-columns: repeat(5, 28px);
    gap: 8px;
    justify-content: center;
    margin-bottom: 10px;
}
.color-swatch {
    width: 28px;
    height: 28px;
    border-radius: 50%;
    border: 2px solid transparent;
    cursor: pointer;
    padding: 0;
    box-shadow: inset 0 0 0 1px rgba(0,0,0,0.18);
    transition: transform 0.1s, border-color 0.15s;
}
.color-swatch:hover { transform: scale(1.08); }
.color-swatch.active { border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-bg); }
.color-opacity-row {
    display: flex;
    align-items: center;
    gap: 8px;
    padding-top: 8px;
    border-top: 1px solid var(--subtle-border);
}
.color-opacity-label {
    font-size: 0.72rem;
    font-weight: 700;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.05em;
}
.color-opacity-slider { flex: 1; min-width: 0; }
.color-opacity-val {
    font-size: 0.78rem;
    font-weight: 700;
    color: var(--text);
    min-width: 38px;
    text-align: right;
}

/* Panel header — group the right-side action buttons */
.panel-header-actions {
    display: flex;
    align-items: center;
    gap: 6px;
}
.panel-header-icon-btn {
    padding: 4px 8px;
    font-size: 1rem;
    line-height: 1;
    opacity: 0.7;
}
.panel-header-icon-btn:hover { opacity: 1; }
.flag-filter-btn.active {
    background: var(--red);
    border-color: var(--red);
    color: #fff;
    opacity: 1;
}
.sound-toggle-btn.active {
    background: var(--accent);
    border-color: var(--accent);
    color: #fff;
    opacity: 1;
}
.sound-toggle-btn svg { display: block; }

/* Container always present so the toolbar slot is reserved.
   Hide the entire wrapper (not just the trigger) when not in trace
   mode — otherwise the empty wrapper sits on top of the shared
   toolbar-action-slot and intercepts clicks meant for Play / Hint. */
.opacity-dropdown {
    position: relative;
}
.opacity-dropdown:not(.visible) {
    visibility: hidden;
}
.opacity-trigger {
    background: var(--accent-bg);
    border-color: var(--accent-border);
    color: var(--accent);
}
.opacity-trigger:hover {
    background: var(--accent);
    color: white;
    border-color: var(--accent);
}

.opacity-dropdown-panel {
    display: none;
    position: absolute;
    /* Opens UPWARD from the trigger. The trigger now sits in the
       canvas-action-slot near the bottom of col-center; a downward
       popup would clip past the column edge. */
    bottom: calc(100% + 6px);
    left: 50%;
    transform: translateX(-50%);
    background: var(--bg);
    border: 1px solid var(--subtle-border);
    border-radius: 8px;
    box-shadow: 0 8px 24px rgba(0,0,0,0.12);
    padding: 12px 8px;
    z-index: 100;
}

.opacity-dropdown.open .opacity-dropdown-panel {
    display: flex;
    align-items: center;
    justify-content: center;
}

.opacity-slider-v {
    -webkit-appearance: slider-vertical;
    appearance: slider-vertical;
    writing-mode: vertical-lr;
    direction: rtl;
    width: 20px;
    height: 100px;
    accent-color: var(--accent);
    cursor: pointer;
}

/* Hide dropdown during practice */
body.study-active .toolbar-dropdown-panel,
body.practice-active .toolbar-dropdown-panel {
    display: none !important;
}

@media (max-width: 600px) {
    .carousel-toolbar {
        width: 96vw;
        gap: 4px;
        padding: 3px 6px;
        /* Drop center alignment so the three groups can space out
           evenly without the absolutely-positioned right group
           overlapping the centered mode-toggle. */
        justify-content: space-between;
    }
    /* Pull toolbar-left/right out of absolute positioning on mobile
       so they participate in the flex layout. */
    .carousel-toolbar .toolbar-left,
    .carousel-toolbar .toolbar-right {
        position: static;
        left: auto;
        right: auto;
    }
    .toolbar-btn { font-size: 0.72rem; padding: 4px 8px; }
    .mode-toggle-btn { font-size: 0.72rem; padding: 4px 10px; }
    .exercise-trigger { font-size: 0.7rem; padding: 4px 6px; }
}

/* Overlay shown in Recall mode before the user has drawn anything —
   gives a prompt like "Write 'a' from memory" in the empty canvas.
   Always laid out (display:flex) so opacity transitions interpolate
   cleanly across character switches; pointer-events:none keeps it
   from interfering when invisible. Visible only while the body has
   study-active and *not* study-drawing.  */
.study-hint-overlay {
    display: flex;
    position: absolute;
    inset: 0;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 6px;
    pointer-events: none;
    color: var(--text-faint);
    text-align: center;
    padding: 0 12px;
    opacity: 0;
    transition: opacity 0.4s ease;
}
body.study-active:not(.study-drawing) .study-hint-overlay { opacity: 1; }
/* During a beat-sequenced recall transition (Character → Swipe etc.),
   pin the canvas overlay to 0 with no transition so it can't ghost-
   appear while the parent .card-area is fading out. Without this
   the overlay's own 0→1 transition fires the moment study-drawing
   is cleared, briefly compositing the romaji/tip/bar against the
   fading parent — exactly the "completed character repeats" jank. */
body.recall-transitioning .study-hint-overlay {
    opacity: 0 !important;
    transition: none !important;
}

/* SRS dual-ring gauge for the currently-selected character — sits to
   the left of the char-row tiles, vertically centered on the row.
   Absolute positioning keeps the tile row's own centering intact. */
.char-row-wrap {
    position: relative;
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
}
/* Char-row SRS gauge is hidden everywhere now. SRS state is still
   tracked in the background; the gauge component is just no longer
   surfaced to the user. */
.char-row-srs-gauge { display: none; }
/* Small audio-on-click toggle inside the char-info widget, mirroring
   the stroke-count badge on the right. Half-opaque by default so it
   doesn't distract; jumps to full opacity + accent fill when active. */
.char-row-sound-toggle {
    position: absolute;
    left: 8px;
    top: 50%;
    transform: translateY(-50%);
    width: 22px;
    height: 22px;
    border-radius: 50%;
    border: 1px solid var(--ink-border);
    background: transparent;
    color: var(--text-faint);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    opacity: 0.5;
    padding: 0;
    z-index: 2;
    transition: opacity 0.15s, background 0.15s, color 0.15s, border-color 0.15s;
}
.char-row-sound-toggle:hover { opacity: 1; }
.char-row-sound-toggle.active {
    background: var(--accent);
    border-color: var(--accent);
    color: #fff;
    opacity: 1;
}
.char-row-sound-toggle svg { display: block; }
.study-hint-romaji {
    font-size: 2.4rem;
    font-weight: 700;
    color: var(--accent);
    letter-spacing: 0.04em;
    line-height: 1;
    opacity: 0.85;
}
.study-hint-prompt {
    font-size: 0.9rem;
    font-style: italic;
    opacity: 0.85;
}
/* Draggable progress bar toward graduation. ONLY the tick captures
   pointer events — the track + label are transparent to clicks so
   the user can keep drawing strokes that pass behind the bar. */
.study-hint-attempts {
    margin-top: 10px;
    min-height: 28px;
    display: flex;
    justify-content: center;
}
.advance-bar {
    position: relative;
    width: 200px;
    height: 28px;
}
.advance-bar-track {
    position: absolute;
    left: 0;
    right: 0;
    top: 6px;
    height: 2px;
    background: var(--text);
    opacity: 0.55;
    border-radius: 1px;
    pointer-events: none;
}
.advance-bar-tick {
    position: absolute;
    top: 0;
    width: 3px;
    height: 14px;
    background: var(--red);
    border-radius: 1.5px;
    transform: translateX(-50%);
    transition: left 0.45s cubic-bezier(0.2, 0.9, 0.3, 1.1);
}
/* Expanded invisible hit zone around the tick (parent overlay's
   pointer-events: none is overridden here so only the tick can
   catch a drag — clicks elsewhere on the bar pass through to the
   canvas, so an in-progress stroke isn't blocked). */
body.study-active:not(.study-drawing) .study-hint-overlay .advance-bar-tick {
    pointer-events: auto;
    cursor: grab;
    touch-action: none;
}
body.study-active:not(.study-drawing) .study-hint-overlay .advance-bar-tick.dragging {
    cursor: grabbing;
}
.advance-bar-tick::before {
    content: '';
    position: absolute;
    inset: -8px -12px;
}
/* During drag, kill the tick's eased transition so it tracks the
   pointer 1:1 instead of lagging behind. */
.advance-bar-tick.dragging { transition: none; }
.advance-bar-label {
    position: absolute;
    right: 0;
    top: 14px;
    font-size: 0.7rem;
    color: var(--text-muted);
    opacity: 0.8;
    transform: translateX(50%);
    pointer-events: none;
}

/* === Recall intro overlay — landing screen shown each time the user
   enters Recall mode. Cushions the involuntary character jump by
   orienting them on overall progress and the next due character.
   Family rows are clickable, letting the user override the default
   jump (current family's first unlearned). */

/* card-actions removed — buttons now in toolbar */

/* === Reading + Writing gauge circles on mini cards === */
.char-mini .gauge-row {
    display: flex;
    gap: 3px;
    margin-top: 3px;
    justify-content: center;
}
.char-mini .gauge-circle {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: transparent;
    border: 1px solid var(--text-faint);
    transition: background-color 0.3s, border-color 0.3s;
}
.char-mini .gauge-circle.filled {
    border-color: transparent;
}

/* === Card mastery display === */
.card-mastery {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    margin-top: 6px;
    font-size: 0.75rem;
    color: var(--text-faint);
    cursor: pointer;
    padding: 4px 12px 4px 6px;
    border-radius: 20px;
    border: 1.5px solid var(--subtle-border);
    background: var(--card-bg);
    transition: all 0.2s;
}

.card-mastery:hover {
    border-color: var(--accent-border);
    background: var(--accent-bg);
}

.card-mastery.active {
    border-color: var(--green);
    background: var(--green-bg);
}

.card-mastery .mastery-ring {
    width: 28px;
    height: 28px;
    position: relative;
}

.card-mastery .mastery-ring svg {
    width: 100%;
    height: 100%;
    transform: rotate(-90deg);
}

.card-mastery .mastery-ring circle {
    fill: none;
    stroke-width: 3;
}

.card-mastery .mastery-ring .ring-bg {
    stroke: var(--ring-bg);
}

.card-mastery .mastery-ring .ring-fill {
    stroke: var(--accent);
    stroke-linecap: round;
    transition: stroke-dashoffset 0.4s;
}

.card-mastery .level-text {
    color: var(--text-muted);
}

.card-mastery .level-name {
    color: var(--accent);
    font-weight: 600;
}

.char-details {
    margin-top: 6px;
    text-align: center;
    font-size: 0.82rem;
}

.char-example {
    color: var(--text-faint);
}

/* Swipe game styles moved to css/games/swipe.css. */

/* Fall game styles moved to css/games/fall.css. */

.overlay-title {
    font-size: 1.3rem;
    font-weight: 700;
    color: var(--red);
    margin-bottom: 6px;
}

.overlay-title.success {
    color: var(--green);
}

.overlay-stats {
    font-size: 0.85rem;
    color: var(--text-muted);
    margin-bottom: 16px;
}

.overlay-buttons {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
    justify-content: center;
}

.overlay-btn {
    padding: 8px 24px;
    border-radius: 20px;
    background: transparent;
    border: 1px solid var(--accent);
    color: var(--accent);
    font-size: 0.85rem;
    font-weight: 600;
    cursor: pointer;
    font-family: inherit;
    transition: all 0.2s;
}

.overlay-btn:hover {
    background: var(--accent-hover);
}

.overlay-btn-secondary {
    background: var(--close-bg);
    border-color: var(--puck-border);
    color: var(--text-muted);
}

.overlay-btn-secondary:hover {
    background: var(--close-hover);
}

/* Rain game styles moved to css/games/rain.css. */

/* Report Card Button */

/* Utility row — right-justified, above SEO divider */
/* Ad container */
.ad-slot {
    width: 100%;
    max-width: 1400px;
    height: 60px;
    max-height: 60px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--subtle-bg);
    border: 1px solid var(--subtle-border);
    border-radius: 12px;
    margin: 0.5rem 0;
    overflow: hidden;
    position: relative;
}

.ad-slot .ad-placeholder {
    font-size: 1.1rem;
    font-weight: 600;
    color: var(--text-faint);
    letter-spacing: 0.05em;
    opacity: 0.5;
    z-index: 1;
}

.ad-slot .ad-bg-chars {
    position: absolute;
    inset: 0;
    pointer-events: none;
    overflow: hidden;
}

.ad-slot .ad-bg-char {
    position: absolute;
    font-family: 'Noto Sans JP', sans-serif;
    font-weight: 900;
    color: var(--text);
    opacity: 0.04;
    line-height: 1;
    user-select: none;
    -webkit-user-select: none;
}

@media print {
    .ad-slot { display: none !important; }
}

.util-row {
    display: flex;
    justify-content: flex-end;
    align-items: center;
    width: 100%;
    max-width: 1400px;
    gap: 8px;
    margin-top: 0.5rem;
    padding-bottom: 0.5rem;
    border-bottom: 1px solid var(--divider);
}

.util-btn {
    width: 32px;
    height: 32px;
    border-radius: 50%;
    background: var(--subtle-bg);
    border: 1.5px solid var(--subtle-border);
    color: var(--text-faint);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    transition: all 0.2s;
    text-decoration: none;
}

.util-btn:hover {
    border-color: var(--accent-border);
    color: var(--accent);
    background: var(--accent-bg);
}

.util-btn svg {
    width: 16px;
    height: 16px;
}

.util-char {
    font-family: 'Noto Sans JP', sans-serif;
    font-size: 1.1rem;
    font-weight: 700;
    line-height: 1;
}

.romaji-alt {
    display: none;
}

body.study-active .char-alt {
    display: none;
}

body.study-active .romaji-alt {
    display: inline;
}

.util-char .romaji-alt {
    font-family: 'Segoe UI', system-ui, sans-serif;
    font-size: 0.75rem;
}

.family-tab .char-alt {
    font-family: 'Noto Sans JP', sans-serif;
}

.family-tab .romaji-alt {
    text-transform: uppercase;
}

/* Report Card Modal */
.report-modal-backdrop {
    position: fixed;
    inset: 0;
    background: rgba(0,0,0,0.5);
    z-index: 1000;
    display: flex;
    align-items: flex-start;
    justify-content: center;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.3s;
    padding: 20px;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
}

.report-modal-backdrop.visible {
    opacity: 1;
    pointer-events: auto;
}

.report-modal {
    max-width: 420px;
    width: 100%;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 16px;
    margin: auto;
    padding: 20px 0;
    flex-shrink: 0;
}

.report-card {
    width: 100%;
    background: var(--card-bg);
    border-radius: 20px;
    padding: 24px;
    box-shadow: 0 8px 32px rgba(0,0,0,0.15);
}

.report-header {
    text-align: center;
    margin-bottom: 20px;
}

.report-title {
    font-size: 1.3rem;
    font-weight: 700;
    color: var(--heading);
    margin: 0 0 8px 0;
}

.report-overall {
    font-size: 0.85rem;
    color: var(--text-muted);
}

.report-overall strong {
    color: var(--accent);
    font-size: 1.1rem;
}

.report-grid {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.report-family {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 6px 0;
}

.report-family-name {
    width: 36px;
    font-size: 0.75rem;
    font-weight: 600;
    color: var(--text-muted);
    text-align: right;
    flex-shrink: 0;
}

.report-bar-track {
    flex: 1;
    height: 18px;
    background: var(--subtle-bg);
    border-radius: 9px;
    overflow: hidden;
    position: relative;
}

.report-bar-fill {
    height: 100%;
    border-radius: 9px;
    background: var(--accent);
    transition: width 0.6s ease;
    min-width: 0;
}

.report-bar-fill.complete {
    background: var(--green);
}

.report-bar-label {
    position: absolute;
    right: 8px;
    top: 50%;
    transform: translateY(-50%);
    font-size: 0.6rem;
    font-weight: 600;
    color: var(--text-muted);
}

.report-family-chars {
    display: flex;
    gap: 3px;
    flex-shrink: 0;
}

.report-char-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--subtle-bg);
    border: 1px solid var(--divider);
}

.report-char-dot.in-progress {
    background: var(--accent);
    border-color: var(--accent);
}

.report-char-dot.learned {
    background: var(--green);
    border-color: var(--green);
}

.report-footer {
    text-align: center;
    margin-top: 16px;
    padding-top: 12px;
    border-top: 1px solid var(--divider);
}

.report-site {
    font-size: 0.7rem;
    color: var(--text-faint);
    letter-spacing: 0.02em;
}

.report-actions {
    display: flex;
    gap: 8px;
    align-items: center;
}

.report-share-btn {
    width: 40px;
    height: 40px;
    border-radius: 50%;
    border: 1.5px solid var(--subtle-border);
    background: var(--card-bg);
    color: var(--text);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: all 0.2s;
}

.report-share-btn:hover {
    border-color: var(--heading);
    color: var(--heading);
    background: var(--card-bg);
    box-shadow: 0 2px 8px rgba(0,0,0,0.12);
    transform: translateY(-1px);
}
